任何一个视频被下载的次数多了会让原视频和下载未完成的视频变模糊吗

阿勒没想到第一篇文章我就标題党了...

不过,我还真没看到目前有哪个公开的实现方案有做的更好的可能是我孤陋寡闻,如果你知道更好的方案一定要留言告诉我,鞠躬..

进入正题这次的主要内容 

  • 缓存下载的实现 

现在市场上各种各样的应用,充满了多媒体信息而声音和视频又是体积最大的文件,如果直接使用 URL 通过 AVPlayer 播放系统并不会做缓存处理,等下次再播又要重新下载对网络状况差的用户来说这就是灾难。若是下载好再播同样偠等待全部下载完成,也是很痛苦

我们最理想的缓存方案是:边播放,边缓存

我在早期加入美拍团队的时候,实际上已经有了边下边播的功能当时选择了使用 HTTPServer,在本地开启一个 http 服务器把需要缓存的请求地址指向本地服务器,并带上真正的 url 地址

早期的美拍都是不到 20s 嘚短视频,后面加长了视频时间但考虑到用户设备容量问题,我们只对短视频做视频缓存一直发展到现在,平台上现在大多数的视频嘟是长视频真正使用到缓存功能的频率已经很低。那么问题就来了HTTPServer 不管我们有没有使用缓存功能,都要在应用打开的时候默默开启這真的是很浪费了。并且我们引入 HTTPServer 库也会增加一些包体积

那么在一段寻觅之下,发现了最适合做边下边播缓存的工具AVAssetResourceLoaderDelegate:一个 iOS 6 就被开放絀来,专门用来处理 AVAsset 加载的工具

我们在这个方法中看看 request 里面的 url 是不是我们支持的,如果能支持就返回 YES!然后就可以开心的一边下视频数據一边塞数据给 AVPlayer 让它显示视频画面。

先不管下载和缓存实现上,可以分为两步:1. 需要知道如何请求数据url 是什么,下载多少数据2. 下載好的数据怎么塞给 AVPlayer

在上面的回调方法中,会得到一个 AVAssetResourceLoadingRequest 对象它里面的属性和方法不多,为了减少干扰我精简了一下这个类的头文件,呮留下我们会用到以及需要解释的属性和方法:

头的 NSURLRequest 对象让下载器去下载这个文件的 Range 范围内的数据。

当 AVPlayer 触发下载时总是会先发起一个 Range 為 0-2 的数据请求,这个请求的作用其实是用来确认视频数据的信息如文件类型、文件数据长度。当下载器发起这个请求收到服务端返回嘚 response

完整实现的主流程是这样的

AVAssetResourceLoaderDelegate 中还有 3 个方法可以针对特殊场景做处理,不过在目前的环境中都用不到所以可以选择不实现这些方法

接管叻视频下载,便可以对视频数据做任何事情比如:缓存、记录下载速度、获得下载进度等等。

AVAsset 在加载视频时经常会在某次数据请求还沒有完成时触发取消下载,然后发起一个新的 LoadingReqeust这个机制是 AVAsset 里的黑盒,具体逻辑无法得知比较像是 AVAsset 的一种重试机制。 作为下载器在收箌取消通知时,需要立刻停止下载由于 DataRequest 的 cancel 操作是异步的,就有可能在 cancel 还未完成时下一个 LoadingRequest 就已经到来,所以还需要需要保证同一个 URL 只能哃时存在一个下载器在下载否则会出现数据混乱的问题。

如果只是单纯的下载视频数据单调递增,缓存处理还是比较容易然而现实昰用户对 player 的 seek 操作给视频的缓存管理带来了巨大的挑战,一旦涉及到用户操作可能性就越多,复杂度也会越高

没有 seek 的情况:网速正常时緩存数据比播放时间走得开,正常播放;网速慢时播放器 loading,直到有足够的数据量进行播放如果网速一直很慢就会播几秒卡一下。

当加叺 seek 后会有三种可能:

  • 视频完全下载好这时 seek 只需读取相应缓存

  • 视频下载一半,用户 seek 到未下载部分LoadingRequest 请求的部分全部都是未下载的数据。这時需要取消正在下载的数据然后从 seek 的点开始下载数据。为了支持 seek 操作下载器就需要支持分片缓存。目前使用的解决方案是下载的视频數据会根据请求的 Range 值把数据存储到文件中对应的偏移值位置,并且每个视频文件都会另外再保存一个与之对应的下载信息文件这个信息文件会记录当前下载了多少数据,总共有多少数据下载了哪些片段的数据等信息,之后的缓存管理会非常依赖这个配置文件

  • 视频被 seek 叻多次,用户 seek 到一个时间点LoadingRequest 请求的部分包含了已下载和未下载的部分。

这种情况是最复杂的!简单的做法是当成上面的情况来处理,铨部都重新下载虽然逻辑简单,但这个方案会下载多次同样的数据不是最最优解。 

我的目标当然是做最优的解决方案但也是复杂高佷多的解决方案。

所有缓存相关的信息都在 VICacheManager 类中目前提供了下载进度通知、修改缓存目录、根据 url 获取缓存地址、根据 url 获取缓存信息、计算缓存大小、清除缓存等功能。详情可看头文件

在下载视频时出现错误无法正常下载是比较容易出现的。我们自己实现了 AVAssetResourceLoaderDelegate 在第一次请求僦抛出错误的话播放器会马上提示错误状态,而如果是已经响应了部分数据再抛错误,AVAssetResourceLoader 会忽略错误而一直处于 loading直到超时。这种情况僦比较尴尬所以 VIResourceLoaderManager 提供了 delegate,如果内部出现错误就会抛出错误,再又外部业务决定是如何处理

注意:同一时间同一个 url 不能有多次下载: 甴于缓存内部实现是对每一个 url 都共用同一个下载配置文件,如果同时有多次对同一个 url 进行下载这个文件下载信息会被同时修改,下载信息会变得混乱 MediaCache 内部做了简单的处理,如果正在下载某 url这时再想尝试下载同样的 url 会直接抛出错误,提示无法开始下载

播到一半声音停叻,视频正常播

比较低概率在美拍上测试时有短视频会出现

弱网下一直loading到超时,但是文件都是已经下载好了

以上问题暂时没有很好的解決方案因为 ResourceLoader 的实现只能做到控制缓存,但 AVPlayer 内的具体实现机制并不清楚在缓存没有问题的情况下出现问题,很难去追根溯源寻找问题的根本原因

另外最大的坑是 AVAssetResourceLoaderDelegate 的内部机制是个沙盒, 因为这个沙盒里面做了很多视频播放处理导致遇到播放时出问题很难排查是什么原因引起,只能不断尝试去找规律....

完整的项目地址:点击阅读原文访问

}

  今天小编给大家分享的是 视頻 设置自动未完成的视频的具体操作,对这个感兴趣的小伙伴们就和小编一起学习下吧以下就是具体的内容。

  1、启动视频点击选择程序界面右上角的【主菜单】按钮。(如图所示)

  2、在【主菜单】下点击选择【设置】选项。(如图所示)

  3、在【设置】界面下点击選择【下载设置】--勾选【自动开始未完成的任务】--【应用】选项完成设置。(如图所示)

  以上就是腾讯视频设置自动下载未完成的视频的具体操作了大家都学会了吗?

}

我要回帖

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信