我正在使用AVFoundation框架进行实时流媒体播放。现在我有一个播放列表如下
#EXT-X-VERSION:4
#EXT-X-ALLOW-CACHE:NO
#EXT-X-MEDIA-SEQUENCE:8148007
#EXT-X-TARGETDURATION:6
#EXT-X-PROGRAM-DATE-TIME:1972-04-14T08:51:01.497Z
我认为AVPlayer请求获取此播放列表。我可以使用AVFoundation中的类来提取EXT-X-TARGETDURATION和EXT-X-PROGRAM-DATE-TIME吗。如果没有,还有其他方法吗?感谢
#EXT-X-PROGRAM-DATE-TIME
可通过AVPlayerItem
的currentDate
属性获得。它不直接报告标记的日期,而是报告当前播放位置之前最后一个标记的日期以及此后的任何播放间隔。
#EXT-X-TARGETDURATION
不能直接使用。您必须自己加载播放列表,或者在加载过程中插入自己。我在AVAssetResourceLoader
和AVAssetResourceLoaderDelegate
方面取得了成功。您可以将URL方案重写为加载程序无法识别的内容(除了http或https之外的任何内容),并代表玩家执行加载。
我不认为AVFoundation可以访问所有这些标签。但是,当我需要调试流时,我会使用自定义的NSURLProtocol来拦截所有流量。我认为有时最好查看原始播放列表和HTTP响应,因为AVPlayer没有给出好的错误消息(例如"操作无法完成")
关于NSURL协议的好教程可以在这里找到:https://www.raywenderlich.com/59982/nsurlprotocol-tutorial
首先让url加载系统知道您可以通过调用[NSURLProtocol registerClass:/* your class */]
并覆盖+(BOOL)canInitWithRequest:
来处理HLS请求
+(BOOL)canInitWithRequest:(NSURLRequest *)request {
BOOL handled = [[NSURLProtocol propertyForKey:@"handled" inRequest:request] boolValue];
return [request.URL.pathExtension isEqualToString:@"m3u8"] && !handled;
}
然后在您的自定义URLProtocol 中覆盖-(void)startLoading
-(void)startLoading {
newRequest = [self.request mutableCopy];
[NSURLProtocol setProperty:@YES forKey:@"handled" inRequest:newRequest];
NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:newRequest
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
/* Inspect response body(playlist) and error */
NSString *responseBody = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
/* Return data and control to AVPlayer*/
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
[self.client URLProtocol:self didLoadData:data];
[self.client URLProtocolDidFinishLoading:self];
}];
[task resume];
}