AVPlayer是驱动播放用例的中心阶层,是用于管理媒体资产的回放和定时的控制器对象。它提供了控制播放器传输行为的界面,例如播放,暂停,改变播放速度的能力,以及在媒体时间线内寻找各个时间点的能力,主要使用一个AVPlayer播放本地和远程基于文件的媒体。AVPlayer一次只能播放一个媒体资源。播放器可以使用其- (void)replaceCurrentItemWithPlayerItem:(nullable AVPlayerItem *)item
方法被重新使用来播放额外的媒体资产,但是它一次只管理单个媒体资产的播放。该框架还提供了一个 AVQueuePlayer 子类,该类可以使用来创建和管理媒体资产的队列,以便按顺序播放。
+ (instancetype)playerWithURL:(NSURL *)URL / - (instancetype)initWithURL:(NSURL *)URL
根据给定URL生成单个的视听资源,会隐式创建一个AVPlayerItem;+ (instancetype)playerWithPlayerItem:(nullable AVPlayerItem *)item / - (instancetype)initWithPlayerItem:(nullable AVPlayerItem *)item
根据Item生成视听资源 ;@property (nonatomic, readonly) AVPlayerStatus status
指示播放器是否可用于播放,KVO重点观测属性;
typedef NS_ENUM(NSInteger, AVPlayerStatus) {
AVPlayerStatusUnknown, //表示播放器的状态尚未知道,因为它尚未尝试加载新的媒体资源
AVPlayerStatusReadyToPlay, // 表示播放器已准备好播放AVPlayerItem实例
AVPlayerStatusFailed // 表示播放器由于错误而不能再播放AVPlayerItem实例
};
-
@property (nonatomic, readonly, nullable) NSError *error
当状态是AVPlayerStatusFailed时描述导致失败的错误,其他情况为nil;
-@property (nonatomic, readonly) BOOL outputObscuredDueToInsufficientExternalProtection
由于外部保护不足,解码输出是否被遮蔽,指因为当前设备配置不满足外部保护机制的要求,播放器是否有意模糊当前项目的视觉输出。可观察属性;
播放控制相关⏬
@property (nonatomic) float rate;
目前的播放速度,0.0值暂停视频,导致timeControlStatus
的值更改为AVPlayerTimeControlStatusPaused
,而1.0值以自然速率播放当前项目。如果关联的播放器项为AVPlayerItem属性canPlaySlowForward
或canPlayFastForward
返回YES,则可以使用0.0和1.0之外的其他比率。如果AVPlayerItem的canPlayReverse
,canPlaySlowReverse
和canPlayFastReverse
属性返回YES,则支持负值范围;- (void)play
开始播放,与将rate值直接设置为1.0是等效的;- (void)pause
暂停,与将rate值直接设置为0.0是等效的;
下面一些属性在iOS 10之后才可以使用:
-
@property (nonatomic, readonly) AVPlayerTimeControlStatus timeControlStatus NS_AVAILABLE(10_12, 10_0)
指示当前是否正在播放,无限期暂停播放,或在等待适当的网络条件时暂停播放,这一状态只有在automaticallyWaitsToMinimizeStalling
属性为YES的情况下才有意义;
typedef NS_ENUM(NSInteger, AVPlayerTimeControlStatus) {
/**
当播放`rate`变为0.0时,进入此状态.此更改可能是调用`pause`方法或
更改播放的`rate`属性为0.0的结果,但也可能由于外部事件(如iOS中断)
而发生。在这种状态下,播放会无限期地暂停,直到播放速率变为大于0.0的
值: 接收到具有非零值的-setRate:或-playImmediatelyAtRate:,
并且有足够的媒体数据已被缓冲以进行播放为止。
*/
AVPlayerTimeControlStatusPaused,
/**
当播放器在AVPlayerTimeControlStatusPlaying状态下因为播放缓冲器
变空而播放停止时或者在AVPlayerTimeControlStatusPaused状态下,播
放速度从0.0被设置为其他值但是并没有足够的媒体数据已经被缓冲可以用来进
行播放时或者播放器没有Item去进行播放时,即player的currentItem为nil
时会进入此状态。在等待缓冲时,可以尝试通过 -playImmediatelyAtRate:
方法开始播放任何其他可用的媒体数据。
*/
AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate,
/**
在这种状态下,播放正在进行,速率(rate)的更改将立即生效。 如果因为媒体
数据不足而播放失败,则timeControlStatus的属性值将更改为
AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate
*/
AVPlayerTimeControlStatusPlaying
} NS_ENUM_AVAILABLE(10_12, 10_0);
-
@property (nonatomic, readonly, nullable) AVPlayerWaitingReason reasonForWaitingToPlay NS_AVAILABLE(10_12, 10_0);
当timeControlStatus
的值为AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate
时,表示等待的原因,其他情况下该属性值为nil,可KVO来有条件地指示播放器在不同状态下的UI;typedef NSString * AVPlayerWaitingReason NS_STRING_ENUM;
定义的播放器等待播放的原因的枚举类型;AVF_EXPORT AVPlayerWaitingReason const AVPlayerWaitingToMinimizeStallsReason
表示播放器在开始播放之前正在等待合适的缓冲区情况。这一原因意味着在automaticallyWaitToMinimizeStalling
属性为YES时,以指定的速率播放可能会导致播放缓冲区在播放完成之前变为空。当automaticallyWaitToMinimizeStalling
属性为NO时,timeControlStatus
不会成为AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate
;AVF_EXPORT AVPlayerWaitingReason const AVPlayerWaitingWhileEvaluatingBufferingRateReason
表示播放器正在监视播放缓冲区填充率,以确定播放是否可能不中断地完成。这一原因意味着automaticallyWaitToMinimizeStalling
属性为YES时,尚未确定以指定速率开始播放是否可能导致缓冲区变空。 当短暂的初始监视期结束后将开始播放或者将原因的值切换到AVPlayerWaitingToMinimizeStallsReason,不建议在此状态下显示指示等待状态的UI;AVF_EXPORT AVPlayerWaitingReason const AVPlayerWaitingWithNoItemToPlayReason
指示播放器因为automaticallyWaitToMinimizeStalling
是YES,且currentItem为nil导致播放等待;
- (void)playImmediatelyAtRate:(float)rate
立即以指定的速率播放可用媒体数据。此方法以指定的速率播放可用媒体数据,无论是否有足够的媒体缓冲以确保流畅播放。如果播放缓冲区中存在媒体数据,则调用此方法会将播放器的播放速率更改为指定速率,并将其timeControlStatus
更改为AVPlayerTimeControlStatusPlaying
。如果播放器缓冲的媒体数据不足以开始播放,如果不会发布AVPlayerItemPlaybackStalledNotification
通知,播放器将在播放期间暂停;-
@property (nonatomic) BOOL automaticallyWaitsToMinimizeStalling NS_AVAILABLE(10_12, 10_0)
指示播放器是否应自动延迟播放以尽量减少停顿。该属性主要是影响timeControlStatus
属性的AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate
值得出现时机;如果该属性为YES,且播放器从暂停状态变为开始播放状态,则该播放器将尝试当前的Item是否可以在当前指定的rate下播放到最后。如果确定可能遇到延迟,那么播放器的
timeControlStatus
属性值将变为AVPlayerTimeControlStatusWaitingToPlayAtSpecifiedRate
,直到延迟的可能性已经变成最小时,播放将自动开始。当播放器在播放期间出现播放的缓冲区耗尽且播放停止类似情况时,当延迟的可能性已经变成最小时,播放将重新开始 ;当你需要精确控制播放开始时间或者使用AVAssetResourceLoader委托来加载媒体数据时,需要将此属性设置为NO。如果此属性的值为NO,则
reasonForWaitingToPlay
不能采用AVPlayerWaitingToMinimizeStallsReason
的值,且只要播放缓冲区不为空,不管会不会播放到最后,播放都会将立即开始播放。 如果播放缓冲区变空并且播放停止,则播放器的timeControlStatus
属性值将变为AVPlayerTimeControlStatusPaused
此属性默认为YES,对于播放在线视频流时其行为与该属性设置为YES相同,对于播放本地文件,其行为与该属性设置为NO相同。
- (CMTime)currentTime
返回Item的当前时间;- (void)seekToDate:(NSDate *)date; / - (void)seekToTime:(CMTime)time
拖动滑块播放跳跃播放,跳到指定的播放时间;- (void)seekToDate:(NSDate *)date completionHandler:(void (^)(BOOL finished))completionHandler / - (void)seekToTime:(CMTime)time completionHandler:(void (^)(BOOL finished))completionHandler
移动播放光标跳跃播放,并在搜索操作已完成或被中断时调用指定的块 ;- (void)seekToTime:(CMTime)time toleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter
查找的时间将在[time -toleranceBefore,time+ toleranceAfter],将kCMTimeZero传递给toleranceBefore和toleranceAfter以请求采样精确查找,这可能会导致额外的解码延迟。全部传递kCMTimePositiveInfinity,则与seekToTime:方法相同。一般采用此方法实现精准跳跃播放;- (void)seekToTime:(CMTime)time toleranceBefore:(CMTime)toleranceBefore toleranceAfter:(CMTime)toleranceAfter completionHandler:(void (^)(BOOL finished))completionHandler
在上面的方法上添加了一个被打断或者完成后的block;-
- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block;
在播放期间请求定期调用给定的块以报告更改时间。interval:间隔 --- 根据播放器当前的时间进度,在正常播放期间周期性调用block;queue:执行队列,该队列必须为串行队列,传入NULL将使用主队列,传入并发队列将导致异常;返回值是一个符合NSObject协议的对象。只要希望播放器调用时间观察器,就必须保留这个返回的值;当时间跳转和播放开始或停止时,block块也被调用;
对
-addPeriodicTimeObserverForInterval:queue:usingBlock:
的每次调用都应与对应的-removeTimeObserver:
调用配对。不调用
-removeTimeObserver:
释放观察者对象将导致异常。
// 官方示例:
- (void)addPeriodicTimeObserver {
// Invoke callback every half second
CMTime interval = CMTimeMakeWithSeconds(0.5, NSEC_PER_SEC);
// Queue on which to invoke the callback
dispatch_queue_t mainQueue = dispatch_get_main_queue();
// Add time observer
self.timeObserverToken =
[self.player addPeriodicTimeObserverForInterval:interval
queue:mainQueue
usingBlock:^(CMTime time) {
// Use weak reference to self
// Update player transport UI
}];
}
-
- (id)addBoundaryTimeObserverForTimes:(NSArray
该方法为边界检测方法 -- 当在正常播放期间特定的时间经过,该Block就会调用;*)times queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(void))block
// 官方示例:
- (void)addBoundaryTimeObserver {
NSMutableArray *times = [NSMutableArray array];
// Set initial time to zero
CMTime currentTime = kCMTimeZero;
// Get asset duration
CMTime assetDuration = self.asset.duration;
// Divide the asset duration into quarters
CMTime interval = CMTimeMultiplyByFloat64(assetDuration, 0.25);
// Build boundary times at 25%, 50%, 75%, 100%
while (CMTIME_COMPARE_INLINE(currentTime, <, assetDuration)) {
currentTime = CMTimeAdd(currentTime, interval);
[times addObject:[NSValue valueWithCMTime:currentTime]];
}
// Add time observer
self.timeObserverToken =
[self.player addBoundaryTimeObserverForTimes:times
queue:dispatch_get_main_queue()
usingBlock:^{
// Use weak reference to self
// Update user interface state
}];
}
-
- (void)removeTimeObserver:(id)observer;
取消时间观察者,与上面两个方法对应配对使用。此方法执行后正在执行的Block依然可能继续执行,可以使用将该方法添加至配对方法执行的队列进行调用或者使用dispatch_sync()
同步调用等待任何正在运行的block完成执行后调用该方法;
// 官方示例
- (void)removeBoundaryTimeObserver {
if (self.timeObserverToken) {
[self.player removeTimeObserver:self.timeObserverToken];
self.timeObserverToken = nil;
}
}
@property (nonatomic) float volume
指示播放器的当前音频音量; 0.0表示静音所有音频,1.0表示以当前Item的全部音量播放。注意:此属性用于控制相对于系统音量的播放器音量,不要用此属性来实现媒体播放的音量滑块。 为此,请使用MPVolumeView,该外观可自定义,并提供用户期望的标准媒体播放行为。可以使用MediaPlayer框架中MPVolumeView类来呈现用于控制系统音量的标准用户界面。@property (nonatomic, getter=isMuted) BOOL muted
指示播放器的音频输出是否静音。 只影响播放器实例的音频静音,而不影响设备是否静音;
配置媒体选择标准设置⏬
@property (nonatomic) BOOL appliesMediaSelectionCriteriaAutomatically
表示是否应将当前选择条件自动应用于AVPlayerItems,iOS 7以上默认是YES;- (void)setMediaSelectionCriteria:(nullable AVPlayerMediaSelectionCriteria *)criteria forMediaCharacteristic:(AVMediaCharacteristic)mediaCharacteristic
为媒体应用具有指定特征的自动选择条件。参数criteria为AVPlayerMediaSelectionCriteria
对象, mediaCharacteristic为AVMediaCharacteristic
类型参数,但在这里只支持AVMediaCharacteristicLegible
字幕资源,AVMediaCharacteristicAudible
音轨资源,AVMediaCharacteristicVisual
视频资源三种特征。具体请参考AVMediaFormat.h
文件;- (nullable AVPlayerMediaSelectionCriteria *)mediaSelectionCriteriaForMediaCharacteristic:(AVMediaCharacteristic)mediaCharacteristic
返回具有指定媒体特征的媒体的自动选择条件;
外部播放支持相关⏬
@property (nonatomic) BOOL allowsExternalPlayback
指示播放器是否允许切换到外部播放模式,默认YES;@property (nonatomic, readonly, getter=isExternalPlaybackActive) BOOL externalPlaybackActive
指示播放器当前是否正在以外部播放模式播放视频;@property (nonatomic) BOOL usesExternalPlaybackWhileExternalScreenIsActive
表示播放器在“外部屏幕”模式处于活动状态时是否应自动切换到“外部播放”模式,默认是NO,如果allowExternalPlayback为NO,则不起作用;@property (nonatomic, copy) AVLayerVideoGravity externalPlaybackVideoGravity
设置用于外部播放的视频重力选项;
将播放同步到外部源⏬
这类方法仅适用于基于文件的播放,暂时不支持HLS(HTTP Live Streaming)的设置。
- (void)setRate:(float)rate time:(CMTime)itemTime atHostTime:(CMTime)hostClockTime NS_AVAILABLE(10_8, 6_0)
将当前项目的播放速率和时间与外部源同步。itemTime为与播放item相匹配的精准的时间,如果要使用Item的currentTime则需要指定为kCMTimeInvalid。hostClockTime为同步播放的主机时间,如果指定为kCMTimeInvalid,则rate和itemTime的设置均不需要任何的外部同步。在iOS 10之后使用该方法时一定要先将automaticallyWaitsToMinimizeStalling
设置为NO,否者会引起异常。- (void)prerollAtRate:(float)rate completionHandler:(nullable void (^)(BOOL finished))completionHandler
以给定的rate在当前时间开始加载媒体数据,以为播放准备媒体管道;- (void)cancelPendingPrerolls
取消任何挂起的预卷请求,并调用相应的完成处理操作。上面一个方法的取消操作;@property (nonatomic, retain, nullable) __attribute__((NSObject)) CMClockRef masterClock
这个属性的默认值是NULL,这意味着主时钟是自动选择的。非NULL属性时,此属性将覆盖item的时间基础的主时钟自动选择。这在纯视频电影与其他音源播放的音频同步时,是非常有用的;
与AVPlayerItem相关⏬
@property (nonatomic, readonly, nullable) AVPlayerItem *currentItem
获取与当前播放器关联的Item;- (void)replaceCurrentItemWithPlayerItem:(nullable AVPlayerItem *)item
替换当前的Item。若参数Item与播放器当前Item是同一个则无影响,需要注意的是该方法对于AVQueuePlayer类是不适用的,若多个Item情况下调用该方法会爆异常;@property (nonatomic) AVPlayerActionAtItemEnd actionAtItemEnd
指示当AVPlayerItem到达结束时间时播放器应执行的动作;
typedef NS_ENUM(NSInteger, AVPlayerActionAtItemEnd)
{
/**
指示当AVPlayerItem达到其结束时间时,播放器将自动前进到其
队列中的下一个项目。此值仅支持AVQueuePlayer类的播放器。
如果对非AVQueuePlayer类设置此值则会发生异常。
*/
AVPlayerActionAtItemEndAdvance = 0,
/**
播放完成后自动将rate设置为0.0使视频暂停。
*/
AVPlayerActionAtItemEndPause = 1,
/**
表示当AVPlayerItem达到其结束时间时,播放器将不采取任何行动。
播放器的播放速度不会改变,其currentItem不会改变,其currentTime
将会随着时间的推移而不断地增加或减少。
*/
AVPlayerActionAtItemEndNone = 2,
};
AVQueuePlayer子类
+ (instancetype)queuePlayerWithItems:(NSArray
初始化;*)items; / - (AVQueuePlayer *)initWithItems:(NSArray *)items - (NSArray
设置或获取相关联的一组AVPlayerItem ;*)items; - (void)advanceToNextItem;
从播放队列中删除当前Item,结束当前Item的播放,并启动播放器队列中下一个Item的播放;- (BOOL)canInsertItem:(AVPlayerItem *)item afterItem:(nullable AVPlayerItem *)afterItem;
该值表示给定的AVPlayerItem是否可以插入到队列中指定Item的后面;- (void)insertItem:(AVPlayerItem *)item afterItem:(nullable AVPlayerItem *)afterItem;
插入操作;- (void)removeItem:(AVPlayerItem *)item;
移除指定Item,如果要删除的item正在播放,则与-advanceToNextItem
具有相同的效果。;- (void)removeAllItems;
移除所有Item;
AVPlayerLayer相关
+ (AVPlayerLayer *)playerLayerWithPlayer:(nullable AVPlayer *)player
通过AVPlayer,直接指定AVPlayer的视觉输出;@property (nonatomic, retain, nullable) AVPlayer *player
播放器层显示视觉输出的播放器;@property(copy) AVLayerVideoGravity videoGravity;
定义视频在AVPlayerLayer中的显示方式,默认方式AVLayerVideoGravityResizeAspect;
typedef NSString * AVLayerVideoGravity NS_STRING_ENUM;
/**
保留宽高比的情况下,尽量适合layer的bounds。
*/
AVF_EXPORT AVLayerVideoGravity const AVLayerVideoGravityResizeAspect
/**
保留宽高比的情况下,完全填充layer的bounds。
*/
AVF_EXPORT AVLayerVideoGravity const AVLayerVideoGravityResizeAspectFill
/**
拉伸填充满layer的bounds。
*/
AVF_EXPORT AVLayerVideoGravity const AVLayerVideoGravityResize
@property(nonatomic, readonly, getter=isReadyForDisplay) BOOL readyForDisplay
指示第一个视频帧已准备好显示相关AVPlayer,
将此属性作为标识当视图中的AVPlayerLayer可以最佳显示的时候。当此属性为NO时,一个AVPlayerLayer可以被显示,或者是可见的,但是该层将不具有任何用户可见的内容,直到值变为YES。@property (nonatomic, readonly) CGRect videoRect
视频显示框在接受者bounds内的当前尺寸和位置。可观察属性;@property (nonatomic, copy, nullable) NSDictionary
这个属性可以用来定制播放到播放器层的像素缓冲区的格式。(暂时不知道用处~);*pixelBufferAttributes NS_AVAILABLE(10_11, 9_0);
// 官方示例
// PlayerView.h
@interface PlayerView : UIView
@property AVPlayer *player;
@property (readonly) AVPlayerLayer *playerLayer;
@end
// PlayerView.m
@implementation PlayerView
- (AVPlayer *)player {
return self.playerLayer.player;
}
- (void)setPlayer:(AVPlayer *)player {
self.playerLayer.player = player;
}
// Override UIView method
+ (Class)layerClass {
return [AVPlayerLayer class];
}
- (AVPlayerLayer *)playerLayer {
return (AVPlayerLayer *)self.layer;
}
@end