1. 名词解释:(1)AVPlayer 负责控制播放(管理和调控)
使用 AVPlayer 时需要注意,AVPlayer 本身并不能显示视频, 显示视频的是 AVPlayerLayer。 AVPlayerLayer 继承自 CALayer,添加到 view.layer 上就可以使用了。
- (void)play; —— 播放
- (void)pause; —— 暂停
(2)AVPlayerLayer 画面显示播放 —- View
(3)AVPlayerItem 提供数据 —- 数据源
AVPlayItem 相当于 Model 层,包含Media的信息和播放状态,并提供这些数据给视频观察者。
status: 播放器状态变化
loadedTimeRange :缓存大小
2. 整个播放视频的步骤。
(1)首先,得到视频的URL
(2)根据URL创建AVPlayerItem
(3)把AVPlayerItem 提供给 AVPlayer
(4)AVPlayerLayer 显示视频。
(5)AVPlayer 控制视频, 播放, 暂停, 跳转 等等。
(6)播放过程中获取缓冲进度,获取播放进度。
(7)视频播放完成后做些什么,是暂停还是循环播放,还是停留在最后一帧图像。
3. 初始化一个AVPlayer用来播放
#pragma mark -- life cycle
- (void)createAVPlay
{
// 监测设备方向
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
//旋转屏幕通知
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onDeviceOrientationChange)
name:UIDeviceOrientationDidChangeNotification
object:nil];
//播放完成通知
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(avPlayDidEnd)
name:AVPlayerItemDidPlayToEndTimeNotification
object:nil];
/* 1. 初始化一个View,是用来放置播放器用的,此处是self
2. 初始化播放器AVPlayerItem,用来设置播放视屏的URL或者本地视屏资源
3. 初始化一个AVPlayer对象,来接收AVPlayerItem传过来的资源
4. 初始化一个AVPlayerLayer对象,将AVPlayer对象叠加在其上面
5. 将AVPlayerLayer对象添加到self的layer层上
*/
// 初始化播放器item
self.playerItem = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:self.movieUrlString]];
// 监听播放器状态变化
[self.playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
// 监听缓存大小
[self.playerItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
// 初始化一个AVPlayer
self.player = [[AVPlayer alloc] initWithPlayerItem:self.playerItem];
// 初始化播放器的Layer
self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
//此处为默认视频填充模式
self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
// 添加playerLayer到self.layer
[self.layer insertSublayer:self.playerLayer atIndex:0];
/* layer的填充属性
AVLayerVideoGravityResizeAspect 等比例拉伸,会留白
AVLayerVideoGravityResizeAspectFill // 等比例拉伸,会裁剪
AVLayerVideoGravityResize // 保持原有大小拉伸
*/
}
// 监听播放器的变化属性
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
if ([keyPath isEqualToString:@"status"])
{
AVPlayerItemStatus statues = [change[NSKeyValueChangeNewKey] integerValue];
switch (statues)
{
case AVPlayerItemStatusReadyToPlay:
{
[self hiddenLoading];
[self setNeedsLayout];
[self layoutIfNeeded];
// 5. 添加playerLayer到self.layer
//[self.layer insertSublayer:self.playerLayer atIndex:0];
// 最大值直接用sec,以前都是
// CMTimeMake(帧数(slider.value * timeScale), 帧/sec)
[self.avPlayControlView setSliderMaxValue:CMTimeGetSeconds(self.playerItem.duration)];
[self initTimer];
// 启动定时器 5秒自动隐藏
if (!self.autoDismissTimer)
{
self.autoDismissTimer = [NSTimer timerWithTimeInterval:8.0 target:self selector:@selector(autoHiddenControlView) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.autoDismissTimer forMode:NSDefaultRunLoopMode];
}
}
break;
case AVPlayerItemStatusUnknown:
NSLog(@"--AVPlayerItemStatusUnknown");
break;
case AVPlayerItemStatusFailed:
NSLog(@"--AVPlayerItemStatusFailed");
break;
default:
break;
}
}
else if ([keyPath isEqualToString:@"loadedTimeRanges"]) // 监听缓存进度的属性
{
// 计算缓存进度
NSTimeInterval timeInterval = [self availableDuration];
// 获取总长度
CMTime duration = self.playerItem.duration;
CGFloat durationTime = CMTimeGetSeconds(duration);
// 监听到了给进度条赋值
[self.avPlayControlView setProgress:timeInterval / durationTime];
}
}
本工程的演示demo地址 点击打开链接