czb1n

不是谁的谁,在乎你是你

0%

iOS基于AVPlayer自定义播放器

简介

  • 用AVPlayer实现一个播放器
1
2
3
4
5
@interface PlayerView : UIView

@property (nonatomic, strong) AVPlayer *avPlayer;

@end

配置

AVPlayer本身是无法显示视频的,首先要把AVPlayer添加到AVPlayerLayer。

@abstract Indicates the instance of AVPlayer for which the AVPlayerLayer displays visual output

在PlayerView中重写+ (Class)layerClass; 方法,使得PlayerView的 underlying layer 为 AVPlayerLayer:

1
2
3
4
 + (Class)layerClass
{
return [AVPlayerLayer class];
}

然后初始化AVPlayer:

1
2
+ (instancetype)playerWithPlayerItem:(AVPlayerItem *)item;
+ (instancetype)initWithPlayerItem:(AVPlayerItem *)item;

AVPlayerItem可以根据AVAsset创建,可以创建在线资源item,也可以是本地资源item。
创建AVPlayer之后就添加到AVPlayerLayer。

1
[(AVPlayerLayer *)self.layer setPlayer:self.avPlayer];

使用

播放和暂停。

1
2
+ (void)play;
+ (void)pause;

音量控制。

1
2
@property (nonatomic) float volume;
@property (nonatomic, getter=isMuted) BOOL muted;

切换播放Item。

1
- (void)replaceCurrentItemWithPlayerItem:(nullable AVPlayerItem *)item;

获取播放状态和缓存进度,这需要监听AVPlayer中当前播放的item中的属性变化。

1
2
3
4
5
6
7
8
9
[self.avPlayer.currentItem addObserver:self
forKeyPath:@"status"
options:NSKeyValueObservingOptionNew
context:nil];

[self.avPlayer.currentItem addObserver:self
forKeyPath:@"loadedTimeRanges"
options:NSKeyValueObservingOptionNew
context:nil];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- (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;
}
}