美文网首页
AVPlayer使用详解

AVPlayer使用详解

作者: OwenWong | 来源:发表于2020-01-13 16:28 被阅读0次

iOS平台播放视频,系统提供了下面三种方式:MPMoviePlayerController、AVPlayerViewController、AVPlayer。前两种简单易用,但不可定制。最后一种AVPlayer:功能强大,可定制度高,唯一美中不足的是需要将视频层添加至AVPlayerLayer中,这样才能将视频显示出来。

开发时这样做

在ViewController的@interface中添加以下属性:

@property (nonatomic ,strong) AVPlayer *player;
@property (nonatomic ,strong) AVPlayerItem *playerItem;
@property (nonatomic , strong) PlayerView *playerView;

PlayerView继承自UIView,不过重写了set和get方法,用于将player添加至playerView的AVPlayerLayer中,这样视频画面才能显示出来。在PlayerView.h中声明一个AVPlayer对象,由于默认的layer是CALayer,而AVPlayer只能添加至AVPlayerLayer中,所以我们改变一下layerClass,这样PlayerView的默认layer就变了,之后我们可以把在viewController中初始化的AVPlayer对象赋给AVPlayerLayer的player属性。

////PlayerView.h 
@property (nonatomic ,strong) AVPlayer *player;
 
////PlayerView.m
+ (Class)layerClass {
    return [AVPlayerLayer class];
}
- (AVPlayer *)player {
    return [(AVPlayerLayer *)[self layer] player];
}
- (void)setPlayer:(AVPlayer *)player {
    [(AVPlayerLayer *)[self layer] setPlayer:player];
}

然后执行下面代码,即可播放视频:

NSURL *videoUrl = [NSURL URLWithString:@"http://www.jxvdy.com/file/upload/201405/05/18-24-58-42-627.mp4"];
self.playerItem = [AVPlayerItem playerItemWithURL:videoUrl];
// status 播放状态
[self.playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
// loadedTimeRanges 缓存时间
[self.playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
// playbackBufferEmpty 缓存不足
[self.playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
// playbackLikelyToKeepUp 缓存充足
[self.playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];

self.player = [AVPlayer playerWithPlayerItem:self.playerItem];
[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(moviePlayDidEnd:) name:AVPlayerItemDidPlayToEndTimeNotificationobject:self.playerItem];

AVPlayerItem监听的几个对象:

  1. status 播放状态
typedef NS_ENUM(NSInteger, AVPlayerItemStatus) {
    AVPlayerItemStatusUnknown,//未知
    AVPlayerItemStatusReadyToPlay,//准备播放
    AVPlayerItemStatusFailed//播放失败
};

使用KVO监测playItem.status,可以获取播放状态的变化

  1. loadedTimeRanges 缓存时间
    监测它可以知道视频的缓存情况,必要时可在缓存完成后将视频存入本地。
  2. playbackBufferEmpty与playbackLikelyToKeepUp,这两个是一对,即通常配对使用
    playbackBufferEmpty可以让我们在缓存不够(视频加载不出来)时,暂停播放显示loading;
    playbackLikelyToKeepUp则告诉我们缓存足够播放,此时重启播放。
    KVO监听:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    
    if ([object isKindOfClass:[AVPlayerItem class]]) {
        if ([keyPath isEqualToString:@"status"]) {
            switch (_playerItem.status) {
                case AVPlayerItemStatusReadyToPlay:
                    //推荐将视频播放放在这里
                    [self play];
                    break;
                case AVPlayerItemStatusUnknown:
                    NSLog(@"AVPlayerItemStatusUnknown");
                    break;
                case AVPlayerItemStatusFailed:
                    NSLog(@"AVPlayerItemStatusFailed")
                    break;
                default:
                    break;
            }
        }else if ([keyPath isEqualToString:@"loadedTimeRanges"]){
          NSArray *array = _playerItem.loadedTimeRanges;
          CMTimeRange timeRange = [array.firstObject CMTimeRangeValue];//本次缓冲时间范围
          float startSeconds = CMTimeGetSeconds(timeRange.start);
          float durationSeconds = CMTimeGetSeconds(timeRange.duration); 
          NSTimeInterval totalBuffer = startSeconds + durationSeconds;//缓冲总长度
          NSLog(@"当前缓冲时间:%f",totalBuffer);
        }else if ([keyPath isEqualToString:@"playbackBufferEmpty"]) {
          //some code show loading   
        }else if([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) {    
          //由于 AVPlayer 缓存不足就会自动暂停,所以缓存充足了需要手动播放,才能继续播放  
          [_player play];      
      }
    }
}

AVPlayerItem的几个常用通知:

//播放完成
AVPlayerItemDidPlayToEndTimeNotification
//播放失败
AVPlayerItemFailedToPlayToEndTimeNotification
//异常中断
AVPlayerItemPlaybackStalledNotification
// 使用
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerMovieFinish:) name:AVPlayerItemDidPlayToEndTimeNotification object:[self.player currentItem]];

参考:
1、AVPlayer的基本使用
2、AVPlayer详解系列(一)参数设置

相关文章

网友评论

      本文标题:AVPlayer使用详解

      本文链接:https://www.haomeiwen.com/subject/cemgactx.html