礼包兑换

视频播放之AVPlayer、AVPlayerItem、AVPlayerLayer

二、AVPlayerItem的控制

AVPlayerItem作为资源管理对象,它控制着视频从创建到销毁的诸多状态。

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

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

[self.playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];

在监听回调中:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)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; }

}}

虽然设置完播放配置我们可以直接调用[self.player play];进行播放,但是更稳妥的方法是在回调收到AVPlayerItemStatusReadyToPlay时进行播放

2、视频的时间信息

在AVPlayer中时间的表示有一个专门的结构体CMTime

typedef struct{ CMTimeValue value; // 帧数 CMTimeScale timescale; // 帧率(影片每秒有几帧) CMTimeFlags flags; CMTimeEpoch epoch;} CMTime;

CMTime是以分数的形式表示时间,value表示分子,timescale表示分母,flags是位掩码,表示时间的指定状态。

获取当前播放时间,可以用value/timescale的方式:

float currentTime = self.playItem.currentTime.value/item.currentTime.timescale;

还有一种利用系统提供的方法,我们用它获取视频总时间:

float totalTime = CMTimeGetSeconds(item.duration);

如果我们想要添加一个计时的标签不断更新当前的播放进度,有一个系统的方法:

(id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block;

方法名如其意, “添加周期时间观察者” ,参数1 interal 为CMTime 类型的,参数2 queue为串行队列,如果传入NULL就是默认主线程,参数3 为CMTime 的block类型。简而言之就是,每隔一段时间后执行 block。比如:我们把interval设置成CMTimeMake(1, 10),在block里面刷新label,就是一秒钟刷新10次。

正常观察播放进度一秒钟一次就行了,所以可以这么写:

[self.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:nil usingBlock:^(CMTime time) {

AVPlayerItem *item = WeakSelf.playerItem; NSInteger currentTime = item.currentTime.value/item.currentTime.timescale; NSLog(@"当前播放时间:%ld",currentTime);}];

3、loadedTimeRange 缓存时间

获取视频的缓存情况我们需要监听playerItem的loadedTimeRanges属性

[self.playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];

在KVO的回调里:

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);}

4、playbackBufferEmpty表示视频缓存内容是否可以满足播放需求,YES:显示转圈动画提示。

监听playbackBufferEmpty我们可以获取当缓存不够,视频加载不出来的情况:

[self.playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];

在KVO回调里:

if ([keyPath isEqualToString:@"playbackBufferEmpty"]) {

//some code show loading}

5、playbackLikelyToKeepUp 缓存是否可以满足播放

playbackLikelyToKeepUp和playbackBufferEmpty是一对,用于监听缓存足够播放的状态

[self.playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];/* ... */if([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) {//由于 AVPlayer 缓存不足就会自动暂停,所以缓存充足了需要手动播放,才能继续播放[_player play];}

三、AVPlayerLayer 主要就是显示视频的画布,

播放相关通知1、声音类://声音被打断的通知(电话打来)AVAudioSessionInterruptionNotification//耳机插入和拔出的通知AVAudioSessionRouteChangeNotification

根据userInfo判断具体状态

2、播放类//播放完成AVPlayerItemDidPlayToEndTimeNotification//播放失败AVPlayerItemFailedToPlayToEndTimeNotification//异常中断AVPlayerItemPlaybackStalledNotification

对于播放完成的通知我们可以这么写:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerMovieFinish:) name:AVPlayerItemDidPlayToEndTimeNotification object:[self.player currentItem]];

3、系统状态//进入后台UIApplicationWillResignActiveNotification//返回前台UIApplicationDidBecomeActiveNotification

提示:所有通知和KVO的使用我们都要记得在不用时remove掉。

总结,目前是,视频播放基本组件,可以根据自己的需求进行扩展,可以自定义,暂停、播放,滑动快进、倍速播放等操作

Copyright © 2088 网游折扣情报网 - 全网比价领福利 All Rights Reserved.
友情链接