是否可以使用 AVPlayer 缓存 HLS 片段?
Is it possible to cache HLS segments with AVPlayer?
根本问题
我们的视频在 iOS 中搜索时缓冲很多。它比我们的网络播放器缓冲更多,后者将已观看片段的副本保存在临时存储中。
期望的解决方案
在设备磁盘上本地缓存视频片段。我们可以缓存单一质量并始终重播它。
拦截器
我们找不到在 AVFoundation/AVPlayer 内执行缓存的方法。
我们的尝试
2 种使用 AVPlayer 拦截网络请求的方法。
- 符合 AVAssetResourceLoaderDelegate 并手动处理媒体加载
不适用于 HLS。您可以通过实现 AVAssetResourceLoaderDelegate 来加载 m3u8 文件,它允许您通过身份验证或解密响应,但是无法加载 .ts 文件。
这是我们尝试的代码:
https://gist.github.com/nathanhillyer/84e46152d7c4c88183b6
- 实施 NSURLProtocol 以捕获对
.ts
个文件的请求。
AVURLAsset实际上避免了被拦截。不知何故,网络请求没有被捕获。 (不知道为什么)
实际上,我们可以让AVPlayer从网络播放视频,但是如果你想缓存下载的数据在本地播放,用AVPlayer现在似乎是不可能的。
幸运的是,有一个很棒的 API 是 AVURLAsset 中的 resourceLoader 对象,它可以为 AVPlayer 提供对远程音频文件的受控访问。这就像本地 HTTP 代理一样工作,但没有所有麻烦。
上找到更多详细信息
让我们从真正的好消息开始 - iOS 10 及以上 - 开箱即用。
很快就不需要黑客了。可以在以下 WWDC16 session 中找到有关 HTTP 直播流中的新功能的更多详细信息:
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 中的其他视频产品也使用相同的解决方案 - 总共为许多用户提供服务。
这也是我们为 android 找到的最佳解决方案。
关于NSURLProtocol
:
据我了解,它会提出自己的要求,因此您的自定义 tags/fields/marks 将被删除。
我采用了其他方式:将分段请求重定向到某些自定义 url 方案,然后仅在协议的 canInitWithRequest
方法中检查该方案。
这样就可以了。 (花了一周的时间来弄清楚整个 hls 处理的事情...)
从 iOS10 开始,您可以使用 AVFoundation
在用户设备上下载和存储 HLS 电影,同时他们可以访问快速、可靠的网络,并在以后没有网络时观看它们连接。
AVAssetDownloadURLSession
这个wwdc2016/504/ session讲的是Offline HLS
。它是关于使用 AVAssetDownloadURLSession
下载和持久化资产,它是 URLSession
的子类,这里用于管理 AVAssetDownloadTasks
。本期提到的API在iOS10后可用。
AVAggregateAssetDownloadTask
wwdc2017/504 session 在 iOS11.
中引入了 AVAggregateAssetDownloadTask
An AVAssetDownloadTask used for downloading multiple AVMediaSelections for a single AVAsset, under the umbrella of a single download task.
Apple 提供了一个使用 AVFoundation
播放和 Persist
HTTP 直播流的示例项目。 Demo doc。演示项目使用 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)
根本问题
我们的视频在 iOS 中搜索时缓冲很多。它比我们的网络播放器缓冲更多,后者将已观看片段的副本保存在临时存储中。
期望的解决方案
在设备磁盘上本地缓存视频片段。我们可以缓存单一质量并始终重播它。
拦截器
我们找不到在 AVFoundation/AVPlayer 内执行缓存的方法。
我们的尝试
2 种使用 AVPlayer 拦截网络请求的方法。
- 符合 AVAssetResourceLoaderDelegate 并手动处理媒体加载
不适用于 HLS。您可以通过实现 AVAssetResourceLoaderDelegate 来加载 m3u8 文件,它允许您通过身份验证或解密响应,但是无法加载 .ts 文件。 这是我们尝试的代码: https://gist.github.com/nathanhillyer/84e46152d7c4c88183b6
- 实施 NSURLProtocol 以捕获对
.ts
个文件的请求。
AVURLAsset实际上避免了被拦截。不知何故,网络请求没有被捕获。 (不知道为什么)
实际上,我们可以让AVPlayer从网络播放视频,但是如果你想缓存下载的数据在本地播放,用AVPlayer现在似乎是不可能的。
幸运的是,有一个很棒的 API 是 AVURLAsset 中的 resourceLoader 对象,它可以为 AVPlayer 提供对远程音频文件的受控访问。这就像本地 HTTP 代理一样工作,但没有所有麻烦。
上找到更多详细信息让我们从真正的好消息开始 - iOS 10 及以上 - 开箱即用。 很快就不需要黑客了。可以在以下 WWDC16 session 中找到有关 HTTP 直播流中的新功能的更多详细信息: 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 中的其他视频产品也使用相同的解决方案 - 总共为许多用户提供服务。
这也是我们为 android 找到的最佳解决方案。
关于NSURLProtocol
:
据我了解,它会提出自己的要求,因此您的自定义 tags/fields/marks 将被删除。
我采用了其他方式:将分段请求重定向到某些自定义 url 方案,然后仅在协议的 canInitWithRequest
方法中检查该方案。
这样就可以了。 (花了一周的时间来弄清楚整个 hls 处理的事情...)
从 iOS10 开始,您可以使用 AVFoundation
在用户设备上下载和存储 HLS 电影,同时他们可以访问快速、可靠的网络,并在以后没有网络时观看它们连接。
AVAssetDownloadURLSession
这个wwdc2016/504/ session讲的是Offline HLS
。它是关于使用 AVAssetDownloadURLSession
下载和持久化资产,它是 URLSession
的子类,这里用于管理 AVAssetDownloadTasks
。本期提到的API在iOS10后可用。
AVAggregateAssetDownloadTask
wwdc2017/504 session 在 iOS11.
中引入了AVAggregateAssetDownloadTask
An AVAssetDownloadTask used for downloading multiple AVMediaSelections for a single AVAsset, under the umbrella of a single download task.
Apple 提供了一个使用 AVFoundation
播放和 Persist
HTTP 直播流的示例项目。 Demo doc。演示项目使用 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)