是否可以使用 AVPlayer 缓存 HLS 段



根问题

在iOS中搜索时,我们的视频缓冲了很多。它比我们的网络播放器缓冲得更多,后者将已观看片段的副本保存在临时存储中。

期望的解决方案

在设备的磁盘上本地缓存视频片段。我们可以缓存单个质量并始终重播它。

阻滞 剂

我们找不到在 AVFoundation/AVPlayer 中执行缓存的方法。

我们尝试过什么

使用 AVPlayer 拦截网络请求的 2 种方法。

  1. 符合 AVAssetResourceLoaderDelegate 并手动处理介质的加载

不适用于 HLS。您可以通过实现 AVAssetResourceLoaderDelegate 来加载 m3u8 文件,这允许您通过身份验证或解密响应,但无法加载 .ts 文件。这是我们尝试过的代码:https://gist.github.com/nathanhillyer/84e46152d7c4c88183b6

  1. 实现 NSURLProtocol 以捕获对.ts文件的请求。

AVURLAsset实际上避免了被拦截。不知何故,网络请求只是没有被捕获。(不知道为什么(

让我们从非常好的消息开始 - iOS 10及更高版本 - 开箱即用。很快不再需要黑客攻击。有关 HTTP 实时流中的新增功能的更多详细信息,请参阅以下 WWDC16 会话:https://developer.apple.com/videos/play/wwdc2016/504/

现在回到当前状态 - iOS 9 及更低版本:使用AVPlayer,没有。但是您可以通过本地HTTP服务器缓存HLS片段,并使用AVPlayer播放本地流。

AVPlayer 和 AVAsset 在处理 HLS 播放时不包含必要的信息(例如,它的行为与 MP4 静态文件不同(。

TL;DR - 您需要使用 HTTP 请求来获取段并使用本地 HTTP 服务器为它们提供服务。

一些公司,包括我工作的那家公司,正在使用这种策略。

使用

连接以您想要的质量下载片段,重建清单并将其全部扁平化为一个目录和一个质量,然后使用应用程序内的本地 http 服务器将其提供给 AVPlayer(AVPlayer 只能播放通过 HTTP 提供的 HLS 流 - 不能来自文件资产(。

存在一些极端情况,例如,如果要在一次运行中播放和下载,请进行缓冲,正确重建 m3u8 清单,以及使用磁盘读取进行不同的 AVPlayer 状态。

我从第一手资料中发现了这一点,既有这样的系统生产了 5 年,也有 App Store 中使用相同的解决方案的其他视频产品——总共为许多用户提供服务。

这也是我们为安卓找到的最佳解决方案。

实际上,我们可以让AVPlayer播放来自网络的视频,但是如果您想缓存下载的数据以在本地播放,那么使用AVPlayer现在似乎是不可能的。

幸运的是,有一个很棒的 API 是 AVURLAsset 中的 resourceLoader 对象,您可以向 AVPlayer 提供对远程音频文件的受控访问。这就像本地HTTP代理一样工作,但没有所有的麻烦。

您可以在 https://gist.github.com/anonymous/83a93746d1ea52e9d23f

从 iOS 10 开始,您可以使用AVFoundation在用户可以访问快速、可靠的网络时将 HLS 电影下载并存储在用户的设备上,并在以后没有网络连接的情况下观看。

AVAssetDownloadURLSession

这个 wwdc2016/504/会议讨论了Offline HLS .它是关于使用 AVAssetDownloadURLSession 下载和持久化资产的, 是 URLSession 的一个子类,这里用于管理AVAssetDownloadTasks。此会话中提到的 API 在 iOS10 之后可用。

AVAggregateAssetDownloadTask

WWDC2017/504 会话在 iOS11 中AVAggregateAssetDownloadTask引入。

一个 AVAssetDownloadTask,用于在单个下载任务的保护伞下为单个 AVAsset 下载多个 AVMediaSselection。

Apple 提供了一个使用 AVFoundation 播放和Persist HTTP Live Streams 的示例项目。演示文档。演示项目使用AVAggregateAssetDownloadTask

AVAssetDownloadStorageManager

/

wwdc2017/504 还引入了新的 API AVAssetDownloadStorageManager 来管理自动清除下载AVAssets的策略。

  • 有效期
  • 优先级(重要,默认值(
// Get the singleton
let storageManager = AVAssetDownloadStorageManager.shared()
// Set the policy
let newPolicy = AVMutableAssetDownloadStorageManagementPolicy() 
newPolicy.expirationDate = myExpiryDate
newPolicy.priority = .important 
storageManager.setStorageManagementPolicy(newPolicy, forURL: myDownloadStorageURL)
  • 使用 HTTP 实时流式处理

关于NSURLProtocol :据我了解,它会发出自己的请求,因此您的自定义标签/字段/标记将被删除。

我以另一种方式做到了:将分段请求重定向到某个自定义 url 方案,只需在协议的 canInitWithRequest 方法中检查该方案。

这样它就可以正常工作。(花了一周时间弄清楚整个HLS处理的事情...

相关内容

  • 没有找到相关文章

最新更新