新报道公司面试的时候问了一个问题,怎样可以让列表视频下面的5个视频都先加载5秒?当时对AVplayer的了解不够深刻,也没怎么答上来。
所以查阅资料发现官方AVPlayer是可以边播放边下载的~实现AVAssetResourceLoaderDelegate
方法,可以截获AVPlayer发出的请求,进而自行控制网络数据的请求和接收,也就能够实现网络数据的自由缓存.
这个时候第一感觉就是多创建几个AVPlayer,让他在后面加载其他几个视频,但这个感觉可能比较繁琐吧,没尝试过~
采用了KTVHTTPCache唱吧开源的第三方缓存。在它的基础改造~
加载时机我初定为缓存时长大于播放时长加上20s来请求其他视频链接,当然完善的还很多,我这边主要检测下效果怎么样。比如判断当前网络情况啊,根据具体情况触发预加载时机,优化的地方还是很多的~
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(AVPlayerItem *)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
if ([keyPath isEqualToString:@"status"]) {
switch (self.player.status) {
case AVPlayerStatusUnknown:
NSLog(@"KVO:未知状态,此时不能播放");
break;
case AVPlayerStatusReadyToPlay:
NSLog(@"KVO:准备完毕,可以播放");
[self.nowCell.activityIndicator stopAnimating];
[self.player play];
_playerLayer.frame = self.nowCell.bounds;
[self.nowCell.bgView.layer addSublayer:_playerLayer];
break;
case AVPlayerStatusFailed:
NSLog(@"KVO:加载失败,网络或者服务器出现问题");
break;
default:
break;
}
} else if ([keyPath isEqualToString:@"loadedTimeRanges"]) {
NSArray *array = object.loadedTimeRanges;
CMTimeRange timeRange = [array.firstObject CMTimeRangeValue];
float startSeconds = CMTimeGetSeconds(timeRange.start);
float durationSeconds = CMTimeGetSeconds(timeRange.duration);
NSTimeInterval totalBuffer = startSeconds + durationSeconds;;
NSLog(@"缓存总时长:%0.2f, 总时长: %0.2f, 已播放时间: %0.2f", totalBuffer, CMTimeGetSeconds(object.duration), self.nowTime);
if (totalBuffer > self.nowTime + 20) {
//缓存下面3个视频
[self cacheNextVideo:self.nowIndex];
}
}
}
当然也没有完全加载整个视频,利用range控制加载的范围
for (NSString *url in urlArr) {
NSString * URLString = [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSString * proxyURLString = [KTVHTTPCache proxyURLStringWithOriginalURLString:URLString];
// NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURLSession *session = [NSURLSession sharedSession];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:proxyURLString]];
//设置请求头range
[request setValue:@"bytes" forHTTPHeaderField:@"Accept-Ranges"];
[request setValue:@"bytes=0-3000000" forHTTPHeaderField:@"Range"];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
[task resume];
});
}
由于缓存这些第三方框架都给我们实现了,所以基本上只要请求下需要预加载的链接就可以下载到本地目录了,简单测试下来效果很明显。点击下个视频的加载速度,体验都提升了。
接下来就是该好好看看KTVHTTPCache的源码了~
demo地址
参考文档:
iOS基础之GCDAsyncSocket
读懂「 唱吧KTVHTTPCache 」设计思想
iOS--NSNetService和NSNetServiceBrowser(Bonjour网络编程)
网友评论