最近项目中想重新统一视频播放,在此开发中遇到一些问题,在此记录,亦供大家参考。
一
- 错误信息
player item failed:Error Domain=AVFoundationErrorDomain Code=-11839 “Cannot Decode” UserInfo={NSUnderlyingError= 0x123456 {Error Domain=NSOSStatusErrorDomain Code=-12913 “(null)”}, NSLocalizedFailureReason=The decoder required for this media is busy., NSLocalizedRecoverySuggestion=Stop any other actions that decode media and try again., NSLocalizedDescription=Cannot Decode}
原因
“内存泄露”(可能性最大)或者 “人为故意” 导致AVPlayer通道创建过多!被AVFoundation限制解码。
由于iOS硬件的局限性,AVFoundation限制了当前设备中视频播放器的支持数量,据相关资料显示这个数量是4,即同时存在5个播放器实例则就可能得到该错误。
当然,以上的限制不是说你不能新建超过4个AVPlayer实例,而是指“渲染通道”。调用方法:
AVPlayer * player = [AVPlayer playerWithPlayerItem:somePlayerItem];
即会生成一条新的渲染通道。参考
Error Code Meaning
AVPlayerItem fails with AVStatusFailed and error code “Cannot Decode”
How many AVPlayers are allowed to be created at the same time?
iOS 究极体测试工具 内存泄漏
MLeaksFinder:精准 iOS 内存泄露检测工具
二
- 错误信息
An instance 0x1700196c0 of class AVPlayerItem was deallocated while key value observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x17045bff0> ( <NSKeyValueObservance 0x1702d30f0: Observer: 0x136fd6930, Key path: status, Options: <New: YES, Old: NO, Prior: NO> Context: 0x0, Property: 0x17465eab0> <NSKeyValueObservance 0x1704c0000: Observer: 0x136fd6930, Key path: loadedTimeRanges, Options: <New: YES, Old: NO, Prior: NO> Context: 0x0, Property: 0x170852ba0> )
原因
提示:在我们项目中这个错误只出现在iOS8系统上,iOS8以上的系统并没有发现相关问题。
出现这个问题是在iOS8断网情况下点击播放视频,AVPlayerItem实例回调Observer显示失败状态后直接崩溃,Bugly提示信息显示当前的AVPlayerItem已经被回收,但是却没有移除相关的通知监听,导致崩溃。但AVPlayer我们是有采用强引用的,因此暂不明确为什么会被系统回收了。
暂时的解决方案是创建一个强指针变量来引用该AVPlayerItem实例,再在合适的时间去手动清除引用。
若有人知道更深层的原因或者更好的解决方法,还请不吝赐教。参考
AVPlayerItem was deallocated while key value observers were still registered
三
- 错误信息
Error Domain=AVFoundationErrorDomain Code=-11800 “这项操作无法完成” UserInfo=0x175271340 {NSUnderlyingError=0x17485bba0 “未能完成操作。(“OSStatus”错误 -12983。)”, NSLocalizedFailureReason=发生未知错误(-12983), NSLocalizedDescription=这项操作无法完成}
- 原因
这个错误网上没有统一明确的解决方法,在此只做个人摘记和总结。
1.内存泄露:内存泄露导致AVPlayer没有被释放。但是并没有找到官方解释内存泄露为什么会导致这个错误产生。
2.AVPlayer移除不完全,导致重复添加。解决方法是完全移除后释放AVPlayer实例再重新添加。详情见以下参考第一条。
3.存储的文件路径NSURL有问题。即使你打印出来没有什么问题。解决办法是重写输出文件的路径NSURL。此种原因限于本地录制再使用,至于播放远程视频貌似没有作用。重写路径参考代码如下:
NSString *documentPath =[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]; NSURL *documentUrl = [NSURL fileURLWithPath:documentPath isDirectory:YES]; self.saveMovieFile = [NSURL URLWithString:@"video.mp4" relativeToURL:documentUrl];
若有人知道更深层的原因或者更好的解决方法,还请不吝赐教。 - 参考
AVPlayer fails with AVPlayerItemStatusFailed (OSStatus error -12983)
[ios]AVPlayerItemStatusFailed (OSStatus 错误-12983) AVPlayer 失败
ios视频保存Error Domain未知错误
iOS视频一直播放失败,视频加载失败
四
- 错误信息
-[AVPlayerItem seekToTime:toleranceBefore:toleranceAfter:completionHandler:] Seeking is not possible to time {INVALID}
- 原因
在我当前的项目中,Bugly反馈这个错误有点并不准确,因为实际上我使用的是方法是:
seekToTime:completionHandler:
根据反馈很容易发现是seek的CMTime结构体是无效的,因此最直接的解决方法是新增过滤,系统提供了CMTIME_IS_VALID(time)与CMTIME_IS_INVALID(time)两个宏可以用来判断。
stackoverflow上建议使用seekToTime:toleranceBefore:toleranceAfter:completionHandler:方法进行更精确的seeking。
若有人知道更深层的原因或者更好的解决方法,还请不吝赐教。 - 参考
AVPlayer seekToTime: backward not working
davidlondono/PlayerView
seekToTime:toleranceBefore:toleranceAfter:completionHandler: