使用AVPlayer前需要‘“#import <AVFoundation/AVFoundation.h>”,要通过AVPlayer来播放视频需要用到以下3项:
@property(nonatomic,strong)AVPlayer * player; //播放属性
@property(nonatomic,strong)AVPlayerItem * playerItem; //播放属性
@property(nonatomic,strong)AVPlayerLayer * playerLayer; //播放属性
在开发中,单纯使用AVPlayer类是无法显示视频的,要将视频层添加至AVPlayerLayer中,这样才能将视频显示出来
#ragma mark - 懒加载控件 -
- (AVPlayer *)player{
if (!_player) {
_player = [[AVPlayer alloc] init];
}
return _player;
}
- (AVPlayerLayer *)playerLayer{
if (!_playerLayer) {
_playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
_playerLayer.frame = self.bounds;
_playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
}
return _playerLayer;
}
把视频播放器的Layer加到视图Layer上,播放视频
[self.layer addSublayer:self.playerLayer];
self.playerItem = [[AVPlayerItem alloc] initWithURL:playerURL];
[_player replaceCurrentItemWithPlayerItem:_playerItem];
[_player play];
我的自定义播放器
MoivePlayer.h
#import <UIKit/UIKit.h>
#import "PlayerCommandView.h" //控制界面
@interface MoivePlayer : UIView
@property(nonatomic,strong)PlayerCommandView * CommandView; //控制界面
@property(nonatomic,strong)NSURL * playerURL; //视频地址
@property(nonatomic,strong)UIViewController * superVc; //播放器主页面
/*******************************************************************/
@end
MoivePlayer.m
#import "MoivePlayer.h"
#import <AVFoundation/AVFoundation.h>
@interface MoivePlayer()
@property(nonatomic,strong)AVPlayer * player; //播放属性
@property(nonatomic,strong)AVPlayerItem * playerItem; //播放属性
@property(nonatomic,strong)AVPlayerLayer * playerLayer; //播放属性
@property(nonatomic,assign)BOOL isFullScreen; //是否是全屏
@end
@implementation MoivePlayer
- (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
[self initStep];
}
return self;
}
#pragma mark - 懒加载控件 -
- (AVPlayer *)player{
if (!_player) {
_player = [[AVPlayer alloc] init];
}
return _player;
}
- (AVPlayerLayer *)playerLayer{
if (!_playerLayer) {
_playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
_playerLayer.frame = self.bounds;
_playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
}
return _playerLayer;
}
- (PlayerCommandView *)CommandView{
if (!_CommandView) {
_CommandView = [[PlayerCommandView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
_CommandView.backgroundColor = [UIColor clearColor];
}
return _CommandView;
}
- (void)setPlayerURL:(NSURL *)playerURL{
self.playerItem = [[AVPlayerItem alloc] initWithURL:playerURL];
[_player replaceCurrentItemWithPlayerItem:_playerItem];
[self.playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];// 监听loadedTimeRanges属性
}
#pragma mark - 初始化 -
- (void)initStep{
[self.layer addSublayer:self.playerLayer];
[self addSubview:self.CommandView];
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(stup) userInfo:nil repeats:YES];
/*------------------------------*/
[self play];
[self progressSlider];
[self fullScreen];
_isFullScreen = NO;
/*------------------------------*/
[self gestureAction];
}
#pragma mark - Bottomview上的按钮响应方法 -
- (void)play{
[_player play];
__weak typeof(self)weakself = self;
_CommandView.playActionBlock = ^ (int n){
if (n==1) {
[weakself.player pause];
}
if (n==0) {
[weakself.player play];
}
};
}
- (void)progressSlider{
__weak typeof(self)weakself = self;
_CommandView.slideActionBlock = ^(int n){
if (n==100) {
if (_player.status == AVPlayerStatusReadyToPlay) {
CGFloat total = _playerItem.duration.value/_playerItem.duration.timescale;
NSInteger dragedSeconds = floorf(total * _CommandView.slider.value);
CMTime dragedCMTime = CMTimeMake(dragedSeconds, 1);
[weakself.player pause];
[weakself.player seekToTime:dragedCMTime completionHandler:^(BOOL finished) {
[weakself.player play];
}];
}
}
};
}
- (void)fullScreen{
__weak typeof(self)weakself = self;
_CommandView.fullActionBlock = ^(int n){
if (n==200) {
if (weakself.isFullScreen) {
[weakself removeFromSuperview];
[weakself.superVc.view addSubview:weakself];
[UIView animateWithDuration:0.5 animations:^{
weakself.transform = CGAffineTransformMakeRotation(2*M_PI);
weakself.frame = CGRectMake(0, 0, 375, 240);
weakself.playerLayer.frame = CGRectMake(0, 0, 375, 240);
weakself.CommandView.frame = CGRectMake(0, 0, 375, 240);
} completion:^(BOOL finished) {
}];
}else{
[weakself removeFromSuperview];
[[UIApplication sharedApplication].keyWindow addSubview:weakself];
[UIView animateWithDuration:0.5 animations:^{
CGRect MovieRect = weakself.frame;
MovieRect.size.width = [UIScreen mainScreen].bounds.size.height;
MovieRect.size.height = [UIScreen mainScreen].bounds.size.width;
weakself.frame = MovieRect;
weakself.playerLayer.frame = MovieRect;
weakself.CommandView.frame = MovieRect;
weakself.center = [UIApplication sharedApplication].keyWindow.center;
weakself.transform = CGAffineTransformMakeRotation(M_PI_2);
} completion:^(BOOL finished) {
}];
}
_isFullScreen = !_isFullScreen;
}
};
}
#pragma mark - 手势相关 -
- (void)gestureAction{
__weak typeof(self)weakself = self;
_CommandView.gestureActionBlock = ^(int n){
if (n == 1) {
if (!weakself.CommandView.bottomView.hidden) {
weakself.CommandView.bottomView.hidden = !weakself.CommandView.bottomView.hidden;
weakself.CommandView.topView.hidden = !weakself.CommandView.topView.hidden ;
}else{
weakself.CommandView.bottomView.hidden = !weakself.CommandView.bottomView.hidden;
weakself.CommandView.topView.hidden = !weakself.CommandView.topView.hidden ;
}
}
if (n==2) {
if (weakself.player.status == AVPlayerStatusReadyToPlay) {
[weakself.player pause];
weakself.CommandView.playBtn.selected = YES;
}else {
[weakself.player play];
weakself.CommandView.playBtn.selected = NO;
}
}
};
}
#pragma mark - 计时器事件 -
- (void)stup
{
if (_playerItem.duration.timescale !=0) {
_CommandView.slider.maximumValue = 1;
_CommandView.slider.value = CMTimeGetSeconds([_playerItem currentTime])/(_playerItem.duration.value/_playerItem.duration.timescale);
NSInteger proMin = CMTimeGetSeconds([_player currentTime])/60; //当前秒
NSInteger proSec = (NSInteger)CMTimeGetSeconds([_player currentTime]) % 60; //当前分钟
NSInteger durMin = (NSInteger)_playerItem.duration.value / _playerItem.duration.timescale / 60;//总秒
NSInteger durSec = (NSInteger)_playerItem.duration.value / _playerItem.duration.timescale % 60;//总分钟
_CommandView.currentTimeLabel.text = [NSString stringWithFormat:@"%02ld:%02ld / %02ld:%02ld", proMin, proSec, durMin, durSec];
}
if (_player.status == AVPlayerStatusReadyToPlay) {
// [_activity stopAnimating];
}else{
//[_activity startAnimating];
}
}
#pragma mark - KVO键值观察 -
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
AVPlayerItem *playerItem = (AVPlayerItem *)object;
if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
NSTimeInterval timeInterval = [self availableDuration]; // 计算缓冲进度
CMTime duration = self.playerItem.duration;
CGFloat totalDuration = CMTimeGetSeconds(duration);
[_CommandView.progress setProgress:timeInterval / totalDuration animated:NO];
}
if ([playerItem status] == AVPlayerStatusReadyToPlay) {
// _duration = playerItem.duration.value / playerItem.duration.timescale; //视频总时间
}
}
- (NSTimeInterval)availableDuration {
NSArray *loadedTimeRanges = [[_player currentItem] loadedTimeRanges];
CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue]; // 获取缓冲区域
float startSeconds = CMTimeGetSeconds(timeRange.start);
float durationSeconds = CMTimeGetSeconds(timeRange.duration);
NSTimeInterval result = startSeconds + durationSeconds; // 计算缓冲总进度
return result;
}
@end
下方播放器控制类
PlayerCommandView.h
#import <UIKit/UIKit.h>
typedef void(^playActionBlock)(int n);
typedef void(^slideActionBlock)(int n);
typedef void(^fullActionBlock)(int n);
typedef void(^gestureActionBlock)(int n);
typedef void(^panActionBlock)(int n);
@interface PlayerCommandView : UIView
@property(nonatomic,copy)playActionBlock playActionBlock;
@property(nonatomic,copy)slideActionBlock slideActionBlock;
@property(nonatomic,copy)fullActionBlock fullActionBlock;
@property(nonatomic,copy)gestureActionBlock gestureActionBlock;
@property(nonatomic,copy)panActionBlock panActionBlock;
@property(nonatomic,strong) UIView * topView; //顶部视图
@property(nonatomic,strong) UIView * bottomView; //底部视图
@property(nonatomic,strong) UIProgressView * progress; // 缓冲条
@property(nonatomic,strong) UISlider * slider; // 进度条
@property(nonatomic,strong) UILabel * currentTimeLabel; // 当前播放时间
@property(nonatomic,strong) UIButton * playBtn; //播放、暂停按钮
@property(nonatomic,strong) UIButton * screenBtn; //全屏按钮
@property(nonatomic,strong) UITapGestureRecognizer * tapGesture; //单击手势
@property(nonatomic,strong) UITapGestureRecognizer * doubleTapGesture; //双击手势
@property(nonatomic,strong) UIPanGestureRecognizer * panGesture; //拖动手势
@end
PlayerCommandView.m
#import "PlayerCommandView.h"
@interface PlayerCommandView()
{
BOOL _hasMoved; //手势是否移动过
BOOL _isTouchDirection; //是否判断出手势方向
CGPoint _touchBeginPoint; //触摸开始的点
}
@end
@implementation PlayerCommandView
- (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
[self initStep];
}
return self;
}
- (void)layoutSubviews{
_topView.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height * 0.1);
_bottomView.frame = CGRectMake(0, self.frame.size.height - 40, self.frame.size.width, 40);
_playBtn.frame = CGRectMake(5, 5, 30, 30);
_progress.frame = CGRectMake(self.frame.size.width * 0.15, 20, self.frame.size.width * 0.5, 15);
_slider.frame = CGRectMake(self.frame.size.width * 0.15, 13, self.frame.size.width * 0.5, 15);
_currentTimeLabel.frame = CGRectMake(self.frame.size.width * 0.65 + 5 , 10, self.frame.size.width * 0.3, 20);
_screenBtn.frame = CGRectMake(self.frame.size.width - 30, 5, 30, 30);
}
#pragma mark - 懒加载 -
- (UIView *)topView{
if (!_topView) {
_topView = [[UIView alloc] init];
_topView.backgroundColor = [UIColor brownColor];
}
return _topView;
}
- (UIView *)bottomView{
if (!_bottomView) {
_bottomView = [[UIView alloc] init];
_bottomView.backgroundColor = [UIColor brownColor];
}
return _bottomView;
}
- (UIButton *)playBtn{
if (!_playBtn) {
_playBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_playBtn setImage:[UIImage imageNamed:@"pauseBtn"] forState:UIControlStateNormal];
[_playBtn setImage:[UIImage imageNamed:@"playBtn"] forState:UIControlStateSelected];
[_playBtn addTarget:self action:@selector(playBtnAction:) forControlEvents:UIControlEventTouchUpInside];
}
return _playBtn;
}
- (UIProgressView *)progress{
if (!_progress) {
_progress = [[UIProgressView alloc] init];
}
return _progress;
}
- (UISlider *)slider{
if (!_slider) {
_slider = [[UISlider alloc] init];
[_slider setThumbImage:[UIImage imageNamed:@"iconfont-yuan.png"] forState:UIControlStateNormal];
[_slider addTarget:self action:@selector(progressSlider:) forControlEvents:UIControlEventValueChanged];
_slider.minimumTrackTintColor = [UIColor colorWithRed:30 / 255.0 green:80 / 255.0 blue:100 / 255.0 alpha:1];
//生成透明的图形
UIGraphicsBeginImageContextWithOptions((CGSize){ 1, 1 }, NO, 0.0f);
UIImage * transparentImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.slider setMinimumTrackImage:transparentImage forState:UIControlStateNormal];
[self.slider setMaximumTrackImage:transparentImage forState:UIControlStateNormal];
}
return _slider;
}
- (UILabel *)currentTimeLabel{
if (!_currentTimeLabel) {
_currentTimeLabel = [[UILabel alloc] init];
_currentTimeLabel.textColor = [UIColor whiteColor];
_currentTimeLabel.font = [UIFont systemFontOfSize:12];
_currentTimeLabel.text = @"00:00/00:00";
}
return _currentTimeLabel;
}
- (UIButton *)screenBtn{
if (!_screenBtn) {
_screenBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_screenBtn addTarget:self action:@selector(screenBtnAction:) forControlEvents:UIControlEventTouchUpInside];
[_screenBtn setImage:[UIImage imageNamed:@"icon_full"] forState:UIControlStateNormal];
}
return _screenBtn;
}
- (UITapGestureRecognizer *)tapGesture{
if (!_tapGesture) {
_tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
_tapGesture.numberOfTapsRequired = 1;
_tapGesture.numberOfTouchesRequired = 1;
}
return _tapGesture;
}
- (UIPanGestureRecognizer *)panGesture{
if (!_panGesture) {
_panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
[_panGesture setMaximumNumberOfTouches:1];
[_panGesture setMinimumNumberOfTouches:1];
}
return _panGesture;
}
- (UITapGestureRecognizer *)doubleTapGesture{
if (!_doubleTapGesture) {
_doubleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
[_doubleTapGesture setNumberOfTapsRequired:2];
}
return _doubleTapGesture;
}
#pragma mark - 初始化 -
- (void)initStep
{
[self addSubview:self.topView];
[self addSubview:self.bottomView];
[_bottomView addSubview:self.playBtn];
[_bottomView addSubview:self.progress];
[_bottomView addSubview:self.slider];
[_bottomView addSubview:self.currentTimeLabel];
[_bottomView addSubview:self.screenBtn];
[self addGestureRecognizer:self.tapGesture];
[self addGestureRecognizer:self.doubleTapGesture];
[self addGestureRecognizer:self.panGesture];
}
#pragma mark - 按钮的点击事件 -
- (void)playBtnAction:(UIButton *)button
{
if (button.selected) {
if (_playActionBlock) {
_playActionBlock(0);
}
}else{
if (_playActionBlock) {
_playActionBlock(1);
}
}
button.selected = !button.selected;
}
- (void)progressSlider:(UISlider *)slider{
if (_slideActionBlock) {
_slideActionBlock(100);
}
}
- (void)screenBtnAction:(UIButton *)button{
if (_fullActionBlock) {
_fullActionBlock(200);
}
}
#pragma mark - 手势相关 -
- (void)tapAction:(UITapGestureRecognizer *)gesture
{
if (gesture.numberOfTapsRequired == 1) {
if (_gestureActionBlock) {
_gestureActionBlock(1);
}
}
if (gesture.numberOfTapsRequired == 2 ) {
if (_gestureActionBlock) {
_gestureActionBlock(2);
}
}
}
- (void)panAction:(UIPanGestureRecognizer *)gesture
{
CGPoint touchPoint = [gesture locationInView:self];
NSLog(@"%f,%f",touchPoint.x,touchPoint.y);
}
@end
使用
MoivePlayer * Player = [[MoivePlayer alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 240)];
Player.playerURL = [NSURL URLWithString:@"http://7xnujb.com2.z0.glb.qiniucdn.com/zczs02%2Fsj2-001.mp4"];
Player.superVc = self;
[self.view addSubview:Player];