老铁们,大家好,相信还有很多朋友对于深入解析:AVPlayer技术细节全解析和的相关问题不太懂,没关系,今天就由我来为大家分享分享深入解析:AVPlayer技术细节全解析以及的问题,文章篇幅可能偏长,希望可以帮助到大家,下面一起来看看吧!
我们先用思维导图作为本文的目录索引:
AVPlayer详解系列(一)参数设置_IOSAVPlayer.png
为什么使用AVPlayer:
首先,使用iOS平台播放视频。可用的选项通常包括这四个。它们各自的功能和作用如下:
使用环境优缺点MPMoviePlayerControllerMediaPlayer 简单易用且不可定制AVPlayerViewControllerAVKit 简单易用且不可定制AVPlayerAVFoundation 高度可定制且功能强大不支持流媒体直播功能AVPlayer 是最佳选择。
另外,AVPlayer是一款功能齐全的视频播放器,可以播放任何格式。
支持视频格式: WMV、AVI、MKV、RMVB、RM、XVID、MP4、3GP、MPG等
支持音频格式:MP3、WMA、RM、ACC、OGG、APE、FLAC、FLV等。
所以不得不说苹果自己的儿子还是很强大的,是视频开发的首选。
如何使用
AVPlayer存在于AVFoundation框架中,使用时需要导入:
import
几个播放相关的参数
在创建播放器之前,我们需要先了解一些播放器相关的类
AVPlayer:控制播放器的播放、暂停、播放速度
AVURLAsset : AVAsset 的子类,使用URL 实例化。实例化的对象包含了该URL对应的视频资源的所有信息。
AVPlayerItem:管理资源对象并提供播放数据源。
AVPlayerLayer: 负责显示视频。如果不加这个类,就只有声音没有图像。
我们的文章将重点讨论这些参数。光讲这些你可能还不太明白,所以我们就从最简单的播放器开始,一点点展开功能,详细解释一下这些参数的作用。
最简单的播放器
根据上面的描述,我们知道AVPlayer是播放的必要条件,所以我们可以构建的极简播放器是:
NSURL *playUrl=[NSURL URLWithString:@"http://baobab.wdjcdn.com/14573563182394.mp4"];
self.player=[[AVPlayer alloc] initWithURL:playUrl];
[自我玩家玩];
是不是很简单,只有三行代码!
但它太简单了,只能完成音频播放,并没有图片。回顾上面播放相关类的介绍,是因为缺少AVPlayerLayer;作为一个播放器,我不能只播放一个视频,我还想根据需要切换视频,那么我们就必须添加AVPlayerItem。
添加这两个属性后,玩家看起来像这样:
NSURL *playUrl=[NSURL URLWithString:@"http://baobab.wdjcdn.com/14573563182394.mp4"];
self.playerItem=[AVPlayerItem playerItemWithURL:playUrl];
//如果要切换视频,需要调用AVPlayer的replaceCurrentItemWithPlayerItem:方法。
self.player=[AVPlayer playerWithPlayerItem:_playerItem];
self.playerLayer=[AVPlayerLayer playerLayerWithPlayer:self.player];
self.playerLayer.frame=_videoView.bounds;
//放置玩家的视图
[self.videoView.layer addSublayer:self.playerLayer];
[_玩家玩];
播放器现在更加完整了,我们可以在我们创建的容器中看到图片了!
更多功能
但作为一款视频播放器,它仍然有很多不尽如人意的功能。比如:就没有暂停、快进、快退、倍速播放等功能。另外,如果遇到URL错误,是否会有播放失败的提示以及播放完成的相关提示。
为了完成这个,我们需要更多地了解AVPlayerItem 和AVPlayerLayer。
1.AVPlayer控制
前面提到过,该类控制视频播放行为,其使用也比较简单。
播放视频:
[自我玩家玩];
暂停视频:
[自我暂停];
改变速度:
自我玩家率=1.5; //注意,改变播放速度要到视频开始播放后才会生效。
还有其他的控件,我们可以切换到系统API来查看。
2.AVPlayerItem的控制
作为一个资源管理对象,AVPlayerItem控制着视频从创建到销毁的许多状态。
1.播放状态状态
typedef 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)对象更改:(NSDictionary*)更改上下文:(void *)上下文{
if ([对象isKindOfClass:[AVPlayerItem 类]]) {
if ([keyPath isEqualToString:@"status"]) {
开关(_playerItem.status){
案例AVPlayerItemStatusReadyToPlay:
//这里建议放视频播放
[自玩];
中断;情况AVPlayerItemStatusUnknown:
NSLog(@"AVPlayerItemStatusUnknown");
休息;
案例AVPlayerItemStatusFailed:
NSLog(@"AVPlayerItemStatusFailed")
休息;
默认:
休息;
}
}
}
虽然我们可以直接调用[self.player play];设置播放配置后进行播放,更安全的方法是回调收到AVPlayerItemStatusReadyToPlay时进行播放
2.视频时间信息
AVPlayer中有一个特殊的结构体CMTime来表示时间。
类型定义结构{
CMTimeValue 值; //帧号
CMTimeScale 时间刻度; //帧率(视频每秒有多少帧)
CMTimeFlags 标志;
CMTimeEpoch 纪元;
}CMTime;
CMTime 以分数形式表示时间,value 表示分子,timescale 表示分母,flags 是表示指定时间状态的位掩码。
要获取当前播放时间,可以使用value/timescale方法:
float currentTime=self.playItem.currentTime.value/item.currentTime.timescale;
还有系统提供的方法,我们用它来获取视频总时长:
浮动总时间=CMTimeGetSeconds(item.duration);
如果我们想添加一个定时标签来不断更新当前播放进度,有一个系统方法:
(id)addPeriodicTimeObserverForInterval:(CMTime)间隔队列:(可为空的dispatch_queue_t)队列usingBlock:(void (^)(CMTime time))block;方法名顾名思义,“添加周期时间观察者”,参数1内部是CMTime类型,参数2Queue是串行队列。如果传入NULL,则为默认主线程。参数3是CMTime的块类型。
简而言之,block是在一定时间后执行的。
例如,在:中,我们将间隔设置为CMTimeMake(1, 10),并刷新块中的标签,即每秒刷新10次。
正常情况下每秒观察一次播放进度就可以了,所以可以这样写:
[self.player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:nil usingBlock:^(CMTime 时间) {
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);
浮动持续时间=CMTimeGetSeconds(timeRange.duration);
NSTimeInterval TotalBuffer=startSeconds +urationSeconds; //缓冲区总长度
NSLog(@"当前缓冲时间:%f",totalBuffer);
}
4. 播放缓冲区为空
视频缓存内容是否满足播放要求。 YES:显示圆形动画提示。
监听playbackBufferEmpty我们可以得到缓存不足导致视频无法加载的情况:
[self.playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
在KVO回调:中
if ([keyPath isEqualToString:@"playbackBufferEmpty"]) {
//一些代码显示加载
}
5.playbackLikelyToKeepUp缓存是否可以满足播放
playbackLikelyToKeepUp 和playbackBufferEmpty 是一对,用于监控缓冲区是否足以播放
[self.playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];
/* . */
if([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) {
//由于AVPlayer缓存不足,会自动暂停。因此,如果缓存足够的话,需要手动播放才能继续播放。
[_玩家玩];
}
AVURL资产
播放只有一个URL的视频太不安全了。其他人可以轻松捕获链接并窃取链接。为此,我们需要对视频链接的请求头进行验证。这个功能可以借助AVURLAsset来完成。
AVPlayerItem除了用URL初始化外,还可以用AVAsset初始化,但不能直接使用AVAsset。我们来看一下AVURLAsset :的一个初始化方法
/*!
@参数网址
引用媒体资源的NSURL 实例。
@参数选项
NSDictionary 的实例,包含用于指定AVURLAsset 初始化选项的键。请参阅上面的AVURLAssetPreferPreciseDurationAndTimingKey 和AVURLAssetReferenceRestrictionsKey。
*/
(instancetype)URLAssetWithURL:(NSURL *)URL options:(nullable NSDictionary*)options;AVURLAssetPreferPreciseDurationAndTimingKey。该key对应的值是一个布尔值,用于指示资源是否需要前进以精确显示时长和读取随机时间内容。准备。
除了苹果官方推出的这个功能之外,他还可以设置请求头。这算是一个隐藏功能,因为苹果并没有明确提到这个功能,我费了好大劲才找到的。
NSMutableDictionary * headers=[NSMutableDictionary 字典];
[标头setObject:@"yourHeader"forKey:@"用户代理"];
self.urlAsset=[AVURLAssetURLAssetWithURL:self.videoURLoptions:@{@"AVURLAssetHTTPHeaderFieldsKey" : 标头}];
//初始化玩家项目
self.playerItem=[AVPlayerItemplayerItemWithAsset:self.urlAsset];
补充:后来了解到这个参数是非公开API,但是多人测试项目上线后不会受到影响。
播放相关通知
1.声音类别:
//声音中断通知(电话呼叫)
AVAudioSessionInterruptNotification
//耳机插入和拔出的通知
AVAudioSessionRouteChangeNotification
根据userInfo判断具体状态
2. 播放类别
//播放完成
AVPlayerItemDidPlayToEndTimeNotification
//播放失败
AVPlayerItemFailedToPlayToEndTimeNotification
//异常中断
AVPlayerItemPlaybackStalledNotification
对于播放完成的通知,我们可以这样写:
[[NSNotificationCenter defaultCenter] addObserver:self 选择器:@selector(playerMovieFinish:) name:AVPlayerItemDidPlayToEndTimeNotification object:[self.player currentItem]];
3. 系统状态
//输入背景
UIApplicationWillResignActiveNotification
//返回前台
UIApplicationDidBecomeActiveNotification
提示: 我们必须记住在不使用时删除所有通知和KVO 使用。
概括
【深入解析:AVPlayer技术细节全解析】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
终于找到了这篇详细讲解AVPlayer的文章,想要自己开发一个视频播放器
有17位网友表示赞同!
以前一直没明白AVPlayer怎么用,看完这篇文章恍然大悟!
有18位网友表示赞同!
学习iOS要掌握AVPlayer的知识,现在终于有机会好好研究一下了
有7位网友表示赞同!
这篇文档写的很清晰易懂,对AVPlayer的理解提升了很多
有5位网友表示赞同!
想要实现视频缓冲和播放进度条功能,AVPlayer应该非常方便吧
有11位网友表示赞同!
希望文章能涵盖更多进阶的使用技巧,比如如何处理不同格式的视频文件
有16位网友表示赞同!
学习iOS开发真是太棒了!有了AVPlayer可以制作出更酷炫的应用
有12位网友表示赞同!
现在终于明白为什么AVPlayer这么受开发者欢迎了!
有17位网友表示赞同!
看完文章想立马试试自己调用的AVPlayer进行视频播放
有7位网友表示赞同!
学习新技术总是充满挑战,但看这种精妙的讲解让人更加兴奋!
有9位网友表示赞同!
想要制作一个智能视频播放器,AVPlayer应该可以完美满足我的需求
有7位网友表示赞同!
AVPlayer的功能非常强大,可以实现很多精妙的操作效果
有17位网友表示赞同!
文章中提到的播放速度调节真是太棒了!终于可以根据自己的心情调整观看速度
有8位网友表示赞同!
学习AVPlayer可以提升我的iOS开发能力,为未来的职业发展打好基础
有9位网友表示赞同!
对AVPlayer这个概念有了更深刻的理解,期待将它应用到我的项目中
有12位网友表示赞同!
感谢作者分享这篇详细的AVPlayer解析文章,帮助我解决了很多疑惑!
有18位网友表示赞同!
视频播放是手机应用程序不可缺少的功能,掌握AVPlayer真是必学!
有7位网友表示赞同!
这篇文章让我对iOS开发充满了信心!
有7位网友表示赞同!