AVPlayer+AVAssetResourceLoader边下边播缓存时间过长


使用AVPlayer + AVAssetResourceLoader这种方式进行视频边下边播的时候,遇到部分视频需要缓冲很长时间才会播放,不能秒播的原因?

这个时候可以检查一下视频地址是不是经过了多次302重定向,多次重定向后,AVAssetResourceLoader的分片下载可能就会失败。如果视频地址确实是经过了重定向,那就是拦截所有重定向地址取到最终的视频地址,当然这只是投机的处理方式,基于很好的网络条件都会有一定程度的延迟,并不能做到完全秒播,最好的方式还是优化视频源地址,尽量减少代理重定向,或者采用其它的方案对视频进行小部分预加载。

Demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#import <Foundation/Foundation.h>

@interface TYSVPlayRedirectTool : NSObject
- (instancetype)initWithUrlString:(NSString *)urlString;
- (void)handleStartRedirectAsync:(void(^)(NSString *redirectUrl))result;
@end


#import "TYSVPlayRedirectTool.h"

@interface TYSVPlayRedirectTool () <NSURLSessionDelegate>
@property (nonatomic, copy) void(^handleResult)(NSString *url);
@property (nonatomic, strong) NSString *originUrlString;
@property (nonatomic, strong) NSString *redirectUrlString;
@end

@implementation TYSVPlayRedirectTool

- (instancetype)initWithUrlString:(NSString *)urlString {
self = [super init];
if (self) {
self.originUrlString = urlString;
}
return self;
}

- (void)handleStartRedirectAsync:(void (^)(NSString *))result {
self.handleResult = result;

if (self.originUrlString.length == 0) {
if (self.handleResult) {
self.handleResult(self.redirectUrlString);
}
return;
}

NSURL *url = [NSURL URLWithString:self.originUrlString];
NSMutableURLRequest *quest = [NSMutableURLRequest requestWithURL:url];
quest.HTTPMethod = @"GET";
// 这里投机,设置一下数据范围,不然最后一次请求可能完全GET回视频的所有数据
[quest addValue:@"bytes=0-0" forHTTPHeaderField:@"Range"];
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig
delegate:self
delegateQueue:[NSOperationQueue currentQueue]];

TYWeakify(self, weakSelf);
NSURLSessionDataTask *task =
[session dataTaskWithRequest:quest
completionHandler:^(NSData * _Nullable data,
NSURLResponse * _Nullable response,
NSError * _Nullable error) {
if (weakSelf.redirectUrlString.length) {

} else {
weakSelf.redirectUrlString = weakSelf.originUrlString;
}

NSLog(@"self.url:%@", weakSelf.redirectUrlString);
NSLog(@"data.length:%ld", data.length);

if (weakSelf.handleResult) {
weakSelf.handleResult(weakSelf.redirectUrlString);
}
}];

[task resume];
}

// 重定向的代理方法
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
willPerformHTTPRedirection:(NSHTTPURLResponse *)response
newRequest:(NSURLRequest *)request
completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler {
self.redirectUrlString = response.allHeaderFields[@"Location"];
completionHandler(request); // 这个如果为nil则表示拦截跳转。
}
@end

Usage:

1
2
3
4
TYSVPlayRedirectTool *tool = [[TYSVPlayRedirectTool alloc] initWithUrlString:postData.videoData.videoUrl];
[tool handleStartRedirectAsync:^(NSString *redirectUrl) {
// 拿到最终视频源地址
}];
0%