过去一年一直在搞视频相关的产品,可遇见的未来估计也是。下面是我总结的一些内容以备忘,会不定期更新。同时有不对的地方,以及如果有更好的补充,欢迎在下方留言。
备忘
- 想知道 AVPlayer 是否在播放中,最简单的方法是判断 rate 是否为0(注意同时 error 为 nil)。但是最精确的方法是判断 timeControlStatus 的值。
- 接上一条,在弱网情况下,我注意到在视频刚开始播放的时候,无论是 timeControlStatus 还是 rate 都告诉你视频在播放了。但是实际上这种时候,我曾经碰到连续好几秒都没有开始播放。不过在开始播放之后,timeControlStatus 和 rate 都能正确反映视频是否正在播放。
- AVPlayer 可以播放音频和视频,可以是网络的也可以是本地的,AVAudioPlayer 只能播放本地音频。
- AVPlayer 播放的文件如果传 URL 的话,需要注意该 URL 需要带指定文件类型的扩展名。比如说如果是 mp3 文件,这个 URL 就要带上 “.mp3” 的后缀,不然 AVPlayer 会播放失败,error 信息提示说不支持当前的文件类型。
- AVPlayer 默认情况下会加载足够多的数据才开始播放,如果你希望它尽早开始播放的话,需要设置 automaticallyWaitsToMinimizeStalling 为 true
- 记得持有 addPeriodicTimeObserver 返回的 token,在不需要的时候 使用
removeTimeObserver 这个 token。 - GitHub 上大部分的关于视频播放的框架其实就是基于 AVFoundation(主要是 AVPlayer)的 UI 框架。所以如果你们公司准备长期搞一个视频相关的项目,没必要使用这些框架,自己自定义就好了。一个原因是熟悉 AVFoundation,另一个原因是大部分情况下产品经理和设计师对 UI 作出很多改动。而且简单的自定义一点不难。
- 关于 AVPlayer 最经常需要的操作可能就是缓存视频,这需要一些代码,不过基本上就是一些样本代码。
- 手动加载视频最常见的操作是将视频地址的 scheme 修改成任意不是 http 或者 https 的值。然后将该修改过的地址传给 AVURLAsset,同时设置 AVURLAsset 的 resourceLoader 的代理。在代理里面手动发起网络请求加载视频数据。这样 AVFoundation 在解析到它不支持的 scheme 时候会代理给你设置的 delegate。
- 接上一条,虽然这种方式可以手动加载视频,但实际上要加载的具体视频的片段是 AVFoundation 在代理给你的 request 里面已经设置好了的。所以这个层面来说,灵活性不是很好。但是这种方式其实是使用人数最多的。大部分 GitHub 上的视频框架就是这么做的。可以参考一下。
- 还有一种手动加载视频的方式是本地起一个服务器,不过这个我暂时没有尝试过。
- AVPlayer 默认的 seek 精度不是很高,不过 seek 的时候可以设置。
- 我曾经碰到一个问题 AVPlayerItem 的 cancelPendingSeeks 和相应的 AVAsset 的 cancelLoading 都不能阻止它继续加载,所以用了
player.replaceCurrentItem(with: nil)
这种方式,情况好一些了,但是不能彻底解决问题。可能是我姿势不对?我能确认的是我的代码没有引用循环和延迟释放的问题。