@interface PlayerView : UIView
@property (nonatomic, strong) AVPlayer *avPlayer;
@end
1. 配置
AVPlayer本身是无法显示视频的,首先要把AVPlayer添加到AVPlayerLayer。
@abstract Indicates the instance of AVPlayer for which the AVPlayerLayer displays visual output
在PlayerView中重写+ (Class)layerClass;
方法,使得PlayerView的 underlying layer 为 AVPlayerLayer:
+ (Class)layerClass
{
return [AVPlayerLayer class];
}
然后初始化AVPlayer:
+ (instancetype)playerWithPlayerItem:(AVPlayerItem *)item;
+ (instancetype)initWithPlayerItem:(AVPlayerItem *)item;
AVPlayerItem可以根据AVAsset创建,可以创建在线资源item,也可以是本地资源item。
创建AVPlayer之后就添加到AVPlayerLayer。
[(AVPlayerLayer *)self.layer setPlayer:self.avPlayer];
2. 使用
播放和暂停。
+ (void)play;
+ (void)pause;
音量控制。
@property (nonatomic) float volume;
@property (nonatomic, getter=isMuted) BOOL muted;
切换播放Item。
- (void)replaceCurrentItemWithPlayerItem:(nullable AVPlayerItem *)item;
获取播放状态和缓存进度,这需要监听AVPlayer中当前播放的item中的属性变化。
[self.avPlayer.currentItem addObserver:self
forKeyPath:@"status"
options:NSKeyValueObservingOptionNew
context:nil];
[self.avPlayer.currentItem addObserver:self
forKeyPath:@"loadedTimeRanges"
options:NSKeyValueObservingOptionNew
context:nil];
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
AVPlayerItem *playerItem = (AVPlayerItem *)object;
if ([keyPath isEqualToString:@"status"]) {
if ([playerItem status] == AVPlayerStatusReadyToPlay) {
// 正常播放
}
else if ([playerItem status] == AVPlayerStatusFailed) {
// 播放失败
// show retry
}
else {
// 未知错误
// show retry
}
}
else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
NSArray *loadedTimeRanges = [playerItem loadedTimeRanges];
CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue]; // 获取缓冲区域
float startSeconds = CMTimeGetSeconds(timeRange.start);
float durationSeconds = CMTimeGetSeconds(timeRange.duration);
NSTimeInterval result = startSeconds + durationSeconds; // 计算缓冲总进度
}
}