在调试我们项目中的某个页面时,发现 AVPlayerLayer 出现黑屏但有声音。
经过我们的经验和层次判断,问题应该是在 AVPlayerLayer 上。
毕竟 AVPlayerLayer:负责显示视频,如果没有添加该类,只有声音没有画面,比较符合。
网上常见的两种情况
- 1、缺少 videoGravity 的设置
playerLayer.videoGravity = AVLayerVideoGravityResizeAspect
- 2、viewDidLayoutSubviews 移到 loadPlayer方法中 执行
self.playerLayer.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
同上,就是 playerLayer.frame 的 frame 没有设置好。
暂停下,先回归下 基本概念
- AVPlayerItem: 提供视频信息,一个AVPlayerItem对应着你提供的一个视频Url资源
- AVPlayerLayer:它主要负责的就是视频的显示,继承自CALayer
- AVPlayer:它主要负责的是管理视频播放,暂停等等,相当于一个视频管理器
根据URL创建AVPlayerItem , 把AVPlayerItem 提供给 AVPlayer, AVPlayerLayer 显示视频,AVPlayer 控制视频, 播放, 暂停, 跳转 等等, 播放过程中获取缓冲进度,获取播放进度。
那么出现闪黑屏和黑屏,很大概率是 AVPlayerLayer 这一块出问题,毕竟有声音的。随着我这进一步测试,准确的发现这个问题时:
第二次进入时才黑屏的。
最终发现第二次重新进入 self.playerLayer 为空,必须初始化就好了。
抓住关键点,问题就好了,确实是出现在 AVPlayerLayer 上的。
- 然而黑屏解决了,发现还是不完美,每次都会闪烁下的
一个情况是,我们在 iOS 9 上为了一个过渡效果增加了间隔时间
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.playView.playerLayer setPlayer:self.avPlayer];
});
然而在 iOS 13 上这个效果则让闪一下,发现将时间设置在 0.1 的间隔时间就好了。
// 添加预览图
[self addPrImageView];
// 系统高点的设备间隔时间长了,会闪一下
CGFloat time = NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_9_x_Max ? 0.1 : 0.5;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(time * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//去除预览图
[self.preImageView removeFromSuperview];
// 设置播放层
[self.playView.playerLayer setPlayer:self.avPlayer];
});
PS : 为了那个过渡效果,增加了一个预览图,获取画面的第一帧。
- (UIImage *)getVideoPreViewImage:(NSURL *)path {
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:path options:nil];
AVAssetImageGenerator *assetGen = [[AVAssetImageGenerator alloc] initWithAsset:asset];
assetGen.appliesPreferredTrackTransform = YES;
CMTime time = CMTimeMakeWithSeconds(0.0, 600);
NSError *error = nil;
CMTime actualTime;
CGImageRef image = [assetGen copyCGImageAtTime:time actualTime:&actualTime error:&error];
UIImage *videoImage = [[UIImage alloc] initWithCGImage:image];
CGImageRelease(image);
return videoImage;
}
回归下:
- 黑屏: 是因为 AVPlayerLayer 为空导致的
- 闪烁:是因为不同系统版本上导致的,展示的间隔时间长了,AVPlayerLayer 效果不一样 。
具体的 AVPlayerLayer 是哪些细节点不一样,还需要进一步研究。
PS:
1、有时如果是在 Cell 上用, AVPlayer 还有注意,复用的问题。
2、依然有黑屏的时候,注意等到缓冲好后再切换下显示的,注意这个 playbackLikelyToKeepUp
这个属性的监听就OK了。
网友评论