推广

iOS 视频边下边播(缓存,预加载)

iseeyu2年前 (2024-02-21)推广122

image.png

具体实现

1.给AVURLAsset设置资源加载代理

AVPlayer在执行播放的时候,就回去这个delegate,是能能够播放这个asset。于是就可以进行自定义的一些操作

AVURLAsset *asset = [AVURLAsset URLAssetWithURL:assetURL options:nil];
//设置代理
[asset.resourceLoader setDelegate:self queue:dispatch_get_main_queue()];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset];

2.资源下载及数据填充

找一个对象实现 AVAssetResourceLoaderDelegate 这个协议的方法

//在加载URLAsset资源时回调
- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest;

在加载资源的代理方法中看看 request 里面的 url 是不是我们支持的,如果能支持就返回 YES!然后就可以一边下视频数据,一边塞数据给 AVPlayer 让它显示视频画面。数据交互流程图如下:

image.png

下载视频数据

在上面的回调方法中,得到了一个AVAssetResourceLoadingRequest对象,它的主要属性和方法:

@interface AVAssetResourceLoadingRequest : NSObject 
 
 @property (nonatomic, readonly) NSURLRequest *request;
 
 @property (nonatomic, readonly, nullable) AVAssetResourceLoadingContentInformationRequest *contentInformationRequest;
 
 @property (nonatomic, readonly, nullable) AVAssetResourceLoadingDataRequest *dataRequest ;
 
 - (void)finishLoading;
 
 - (void)finishLoadingWithError:(nullable NSError *)error;
 
 @end 

在 AVAssetResourceLoadingRequest 里面,request 代表原始的请求。dataRequest是数据请求,包含数据起始偏移量,数据长度等信息。
AVPlayer 是会触发分片下载的策略,需要从dataRequest 中得到请求范围的信息。
有了请求地址和请求范围,我们就可以重新创建一个设置了请求 Range 头的 NSURLRequest 对象,让下载器去下载这个文件的 Range 范围内的数据。

塞数据给AVPLayer

当 AVPlayer 触发下载时,总是会先发起一个 Range 为 0-2 的数据请求,这个请求的作用其实是用来确认视频数据的信息,如文件类型、文件数据长度。当下载器发起这个请求,收到服务端返回的 response 后,我们要把视频的信息填充到 AVAssetResourceLoadingRequest 的 contentInformationRequest 属性中,告知下载的视频格式以及视频长度。

获取完视频信息后,AVAssetResourceLoader 会继续发起之后的数据片段的请求,下载到的数据就可以塞给 AVAssetResourceLoadingRequest 里的 dataRequest 。 dataRequest 调动下面的方法接收下载的数据,这个方法可以调用多次,接收增量连续的 data 数据。与此同时对下载数据进行本地缓存。

 - (void)respondWithData:(NSData *)data;

当 AVAssetResourceLoadingRequest 要求的所有数据都下载完毕,调用 – (void)finishLoading 完成下载。如果本次请求失败,可以直接调用 – (void)finishLoadingWithError:(NSError *)error; 结束下载。

AVAssetResourceLoadingRequest 在 – (void)finishLoading 的时候,会根据 contentInformationRequest 中的信息,去判断接下去要怎么处理。例如:下载 AVURLAsset 中 URL 指向的文件,获取到的文件的 contentType 是系统不支持的类型,这个 AVURLAsset 将无法正常播放。

下载重试
//在取消加载资源后回调
- (void)resourceLoader:(AVAssetResourceLoader *)resourceLoader didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest;

AVAssetResourceLoader 在执行加载的时候,会时不时的触发取消下载,在这个回调里面,需要取消当前正在进行中的下载任务。然后重新发起加载请求的策略。如果下载了部分,那么重新发起的下载请求会从还没有下载的部分开始。

3.缓存

根据上面的 AVAssetResourceLoaderDelegate 的实现机制,当 AVAsset 需要加载数据时会通过 delegate 告诉外部,外部接管整个视频下载过程。
当我们接管了视频下载,便可以对视频数据做任何事情。比如:缓存、记录下载速度、获得下载进度等等。

实现一个下载器,用 URLSession 开启一个 DataTask 请求数据,把接收到的数据塞给 DataRequest 并写入本地磁盘。

分片下载

在每次的loadingRequest中,都包含着本次加载请求的dataRequest,他是一个AVAssetResourceLoadingDataRequest对象,看下他的属性:

@interface AVAssetResourceLoadingDataRequest : NSObject

@property (nonatomic, readonly) long long requestedOffset;
@property (nonatomic, readonly) NSInteger requestedLength;

- (void)respondWithData:(NSData *)data;

@end

根据dataRequest中的信息,在创建下载数据的 URLRequest 时需要设置 HTTPHeader 的 Range 值

NSString *range = [NSString stringWithFormat:@"bytes=%lld-%lld", fromOffset, (fromOffset + length -1)];
[request setValue:range forHTTPHeaderField:@"Range"];
取消下载

AVAsset 在加载视频时,经常会在某次数据请求还没有完成时触发取消下载,然后发起一个新的 LoadingReqeust。所以在接到取消下载的代理回调时,需要立刻停止当前正在进行中的下载。由于 DataRequest 的 cancel 操作是异步的,就有可能在 cancel 还未完成时,下一个 LoadingRequest 就已经到来,所以还需要需要保证同一个 URL 同时只存在一个下载器在下载,否则会出现数据混乱的问题。

分片缓存

由于AVAsset请求资源数据的时候,不是完整的视频数据,但是为了方便数据管理和魂村读取,对于同一个视频URL的数据我们应该缓存到同一个文件中,根据range将下载到的数据拼接完整即可。
对于更复杂的场景,比如用户seek操作,还要处理播放进度和已缓存数据以及还未缓存的远程数据之间的协调。(我们的业务暂时不涉及到此场景,具体的处理方案可参考:VIMediaCache文档)

4.预加载

在当前视频播放时,开启下载任务,提前将后面的视频资源下载并缓存到本地。需要切换视频时,根据loadingRequest的url判断本地是否已经缓存了这个视频的数据,根据range从本地读取数据填充到dataRequest中。如果本地没有缓存,从上面第2步,走边下边播逻辑。

不足与展望

现在的预加载处理方式是,提前下载后续几条视频完整的视频数据,因此预加载的任务量大,耗时长。切换视频时,可能预加载的任务还没有完成就被提前终止,然后又开始新的预加载。
最好的处理方式是,预加载的视频,只下载开头的一部分数据缓存,到播放这条视频的时候再边下边播剩余的数据。这里就涉及到这样一个场景,如下图示:

image.png

对于这次的loadingRequest,我们需要从本地缓存中读取一段数据,再从远端下载一部分数据,最后将两部分数据合并填充给dataRequest。

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://www.0291.com.cn/post/57610.html

相关文章

我来教你鞋包线上推广,鞋包网上推广平台。

我来教你鞋包线上推广,鞋包网上推广平台。

在企业进行网络营销的过程中,要想更好的运营网站,成功的实现更多的营销目的,有效的推广方式和策略是不可或缺的。网络推广为产品的宣传和销售提供了更为便利的条件。网络推广并非一蹴而就的过程,需要运营人员的长期积累和一些技巧,本文中让我们一起了解一下网络推广都有哪些技巧及网络推广平台。 推广,鞋包网上...

简单说说什么叫思维

简单说说什么叫思维

(thinking )是指一个人形成想法或思想的意识活动的形式与过程。众所周知,思维是人的基本意识活动,每个人都会思维,但思维的深度与广度不一样。有些思维简单,有些思维复杂;有些思维有结果(形成了想法或思想),有些思维没有结果;有些思维是理性的,有些则是非理性的等。...

关于企业网站建设的几个建议和观点。

关于企业网站建设的几个建议和观点。

关于网站建设,根据上海网站建设公司—点瑞云网站建设多年的的建站经验,整理了一下,为将做网站和做了网站的朋友提供参考。 1、定位明确 网站的定位非常重要,要综合考虑所开发网站的客户群体是否丰富,网络应用是否普遍,竞争环境是否激烈,并符不符合自己拥有的现实资源。 2、做专做透 做专:网站内容...

个人网站推广应该如何进行。

个人网站推广应该如何进行。

在刚刚进入 SEO 这个行业的时候,咱们都很苍莽,心中有许多疑问: ①怎样运用百度推广个人网站 ②个人网站怎样推广 ③自己一个人就可以把网站推广的很好吗 ​个人网站推广的 3 个小战略! 那么,怎样运用百度推广个人网站? 1、把专题内容拾掇成电子书 咱们知道最好的推广实际上是运用内...

用什么方法判定网站内容与图片更利于搜索引擎优化。

用什么方法判定网站内容与图片更利于搜索引擎优化。

很多人做优化,只停留在文字的原始方面,对图片的原始程度不够重视,只找一张放在上面,其实对网站的权重提升没有帮助。原始图片可以得到更多的关注和价值认可。无论是优化网站内容还是网站图片,搜索引擎都更容易用原创的东西爱上你的网站。建立一个属于你的原创网站,让搜索引擎更喜欢你。 图像大小主要是指图像的整体...

摩根大通:大宗商品价格或将再涨40%

摩根大通:大宗商品价格或将再涨40%

摩根大通近日发布的一份报告显示,在全球通胀不断加剧的情况下,大宗商品价格可能会在现在基础上再上涨30%到40%。由于俄乌冲突持续,大宗商品价格目前处于多年来的高点。从原油到小麦等商品的价格飙升,进一步刺激全球通货膨胀。...

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片