根问题
在iOS中搜索时,我们的视频会缓冲很多。它比我们的网络播放器缓存了更多,它将已经监视的片段的副本保存在临时存储器中。
所需解决方案
在设备的磁盘上本地缓存视频片段。我们可以通过缓存单一质量并且始终重播它。
阻断剂
我们无法找到在AVFoundation / AVPlayer中执行缓存的方法。
我们尝试过什么
使用AVPlayer拦截网络请求的两种方法。
不适用于HLS。您可以通过实现AVAssetResourceLoaderDelegate来加载m3u8文件,它允许您通过身份验证或解密响应,但无法加载.ts文件。 这是我们尝试的代码: https://gist.github.com/nathanhillyer/84e46152d7c4c88183b6
.ts
个文件的请求。AVURLAsset实际上避免被截获。不知何故,网络请求不会被捕获。 (不知道为什么)
答案 0 :(得分:10)
让我们从真正的好消息开始 - iOS 10及更高版本 - 开箱即用。 不再需要黑客入侵。有关更多详细信息,请参阅以下WWDC16会话,了解HTTP Live Streaming中的新功能: 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只能播放HLS通过HTTP提供的流 - 而不是来自文件资产的流。)
有一些边缘情况,例如,如果您想在一次运行中播放和下载,正确重建m3u8清单以及使用磁盘读取的不同AVPlayer状态,则进行缓冲。
我从第一手知识中发现了这一点,他们都有这样一个生产5年的系统和App Store中使用相同解决方案的其他视频产品 - 总共服务于许多用户。
这也是我们为Android找到的最佳解决方案。
答案 1 :(得分:2)
实际上,我们可以让AVPlayer从网络播放视频,但是如果你想缓存下载的数据以便在本地播放,那么AVPlayer现在似乎是不可能的。
幸运的是,有一个很棒的API是AVURLAsset中的resourceLoader对象,您可以通过它对AVPlayer提供对远程音频文件的受控访问。这类似于本地HTTP代理,但没有任何麻烦。
上找到更多详情答案 2 :(得分:0)
关于NSURLProtocol
:
据我了解,它会自行提出请求,因此您的自定义标记/字段/标记将被删除。
我已采用其他方式:将段请求重定向到某个自定义网址方案,只需在协议的canInitWithRequest
方法中检查方案。
这种方式很好用。 (花了一个星期来计算整个hls处理的东西......)
答案 3 :(得分:0)
从iOS 10开始,您可以使用AVFoundation
在用户的设备可以访问快速,可靠的网络时在他们的设备上下载和存储HLS电影,然后在没有网络连接的情况下观看它们。
此wwdc2016/504/ session谈论Offline HLS
。它是关于使用AVAssetDownloadURLSession
(它是URLSession
的子类,AVAssetDownloadTasks
)下载和持久存储资产的,这里用于管理AVAggregateAssetDownloadTask
。此会话中提到的API在iOS10之后可用。
wwdc2017/504 session在iOS11中引入了AVFoundation
。
一个AVAssetDownloadTask,用于在单个下载任务的保护下为单个AVAsset下载多个AVMediaSelection。
Apple提供了一个示例项目,用于使用Persist
播放和AVAggregateAssetDownloadTask
HTTP Live Streams。 Demo doc。该演示项目使用AVAssetDownloadStorageManager
/wwdc2017/504还引入了新的API 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)
的策略。
{{1}}