VideoNet 0.9.7

VideoNet 0.9.7

mengbingchuan维护。



VideoNet 0.9.7

  • mengbingchuan

VideoCache

使用Swift实现的VideoCache

起因

直接使用AVPlayer播放视频,在用户切换4G时,只能销毁AVPlayer,在用户点击允许播放之后,重新创建,用户体验比较差。因此考虑如何接管AVPlayer的数据加载,在用户切换到4G环境时,只是暂停下载,缓存的数据仍然可用,也无需销毁AVPlayer,体验会更流畅。

选择

查阅了AVPlayer的文档,官方提供了处理数据加载的很好方案。对比了网上各种方案后,觉得官方方案比较简洁。接下来进行尝试。

基本步骤

步骤比较简单,分为如下三步:一、对要播放的URL进行处理,将schema修改为自定义形式。这样,AVPlayer就会将这个URL的请求转交给我们。二、自定义一个类,实现AVAssetResourceLoaderDelegate协议,重点实现这个协议中的两个方法。optional public func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Booloptional public func resourceLoader(_ resourceLoader: AVAssetResourceLoader, didCancel loadingRequest: AVAssetResourceLoadingRequest)。三、将资源代理设置给AVURLAsseturlAsset.resourceLoader.setDelegate(delegate, queue: .main)

具体实现

三个步骤中,一和三比较简单,下面详细说明步骤二。其中包含三个关键的点。

关键点1:在播放前,AVPlayer会通过func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool这个函数询问是否等待加载数据,并将请求转交给我们。我们将返回true,并将请求添加到请求队列中,然后启动下载。当数据返回时,我们调用loadingRequestdataRequest.respond(with: data)方法,将数据添加到request中。当request所需的数据全部提供后,我们通过loadingRequest.finishLoading()request表示,数据已完全加载好,AVPlayer接着可以拿数据进行播放。

关键点2:其中第一次的数据加载,仅请求前两个字节,然后根据返回信息,填充AVAssetResourceLoadingRequestcontentInformationRequest,以告知AVPlayer视频的大小、是否支持byteRange以及视频格式。

关键点3:func resourceLoader(_ resourceLoader: AVAssetResourceLoader, didCancel loadingRequest: AVAssetResourceLoadingRequest) 在进行seek操作时,这个方法会频繁调用,告知之前的请求已被取消,因为seek之后需要下载选中的片段,因此之前片段的下载需要被停止。此时我们需要取消之前的数据请求,否则会浪费用户流量。