在AVPlayer的请求中添加自定义标头字段

使用AVPlayer时,是否可以将带有http请求的标头发送到音频文件? 我需要能够在服务器接收时检查标头的内容,以限制对所请求文件的访问。

您需要通过通用HTTP连接机制(如NSURLConnection请求数据。 如果NSHTTPURLResponse的标头通过了您的测试,那么您应该将其保存到NSCachesDirectory并将此资源的URL传递给AVPlayer如下所示:

 NSData *data = //your downloaded data. NSString *filePath = //generate random path under NSCachesDirectory [data writeToFile:filePath atomically:YES]; AVPlayer *player = [AVPlayer playerWithURL:[NSURL fileURLWithPath:filePath]]; //... 

您可以使用AVURLAssetHTTPHeaderFieldsKey的init选项的AVURLAsset来修改请求标头。

例如:

 NSMutableDictionary * headers = [NSMutableDictionary dictionary]; [headers setObject:@"Your UA" forKey:@"User-Agent"]; AVURLAsset * asset = [AVURLAsset URLAssetWithURL:URL options:@{@"AVURLAssetHTTPHeaderFieldsKey" : headers}]; AVPlayerItem * item = [AVPlayerItem playerItemWithAsset:asset]; self.player = [[AVPlayer alloc] initWithPlayerItem:item]; 

注意:我在WebKit的源代码中找到了此密钥,但这是一个私有选项密钥,因此如果您使用此应用程序,您的应用程序可能会被AppStore拒绝。

我花了几周的时间为HLSvideo流正式寻找方法。 对于任何寻找适用于播放列表和块请求的请求和响应的方法的人来说,我能够找到的唯一方法是通过反向代理传递回放请求,使用它可以拦截请求,添加标头,将其发送到真实服务器,然后从响应中提取标头,然后再将其返回到AVPlayer。

我在这里做了一个简单的示例项目(包含大量注释和文档): https : //github.com/kevinjameshunt/AVPlayer-HTTP-Headers-Example

考虑使用AVURLAsset 。 对于AVURLAsset您可以设置resourceLoader委托。 在委托方法中,您可以手动发出请求以指定必要的标头。

这种方法的好处是您可以完全控制数据加载。

您必须使用自定义URL方案才能使此解决方案正常工作(http和https不会触发委托方法!):

 -(void) play { NSURL * url = [URL URLWithString:@"mycustomscheme://tungsten.aaplimg.com/VOD/bipbop_adv_fmp4_example/master.m3u8"]; AVURLAsset * asset = [AVURLAsset URLAssetWithURL: options:nil]; [asset.resourceLoader setDelegate:self queue:dispatch_queue_create("TGLiveStreamController loader", nil)]; AVPlayerItem * playerItem = [AVPlayerItem playerItemWithAsset:asset]; // Use player item ... ... } #pragma mark - AVAssetResourceLoaderDelegate - (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest { dispatch_async(resourceLoader.delegateQueue, ^{ NSURL * url = [URL URLWithString:@"https://tungsten.aaplimg.com/VOD/bipbop_adv_fmp4_example/master.m3u8"]; NSMutableURLRequest *request = [loadingRequest.request mutableCopy]; request.URL = url; // Add header [request setValue:@"Foo" forHTTPHeaderField:@"Bar"]; NSURLResponse *response = nil; NSError *firstError = nil; // Issue request NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&firstError]; [loadingRequest.dataRequest respondWithData:data]; if (firstError) { [loadingRequest finishLoadingWithError:firstError]; } else { [loadingRequest finishLoading]; } }); return YES; } 

有关完整代码示例,请访问https://developer.apple.com/library/content/samplecode/sc1791/Introduction/Intro.html

完整的代码可能看起来像这样

  #pragma Mark Sound Stuff - (void)playSound:(NSString *)filePath { AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:[NSURL fileURLWithPath:filePath]]; [playerItem addObserver:self forKeyPath:@"status" options:0 context:0]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(itemDidFinishPlaying) name:AVPlayerItemDidPlayToEndTimeNotification object:playerItem]; self.audioPlayer = [[AVPlayer alloc] initWithPlayerItem:playerItem]; [self.audioPlayer play]; } - (void)initSoundPrelisten { //NSLog(@"begin: %s", __FUNCTION__); self.activityIndicator.hidden = NO; [self.activityIndicator startAnimating]; // verification delegate : register dataProtocol = [[StoreConnection alloc] init]; [dataProtocol setDelegate:self]; [dataProtocol requestDataFromServer:[NSString stringWithFormat:@"sound/%@/audio/sample", [self.sound objectForKey:@"globalId"]]]; } - (void)dataSuccessful:(BOOL)success successData:(NSMutableData *)data; { NSLog(@"%s", __FUNCTION__); if (success) { //NSLog(@"sound data: %@", data); NSString *cacheDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSString *filePath = [cacheDirectory stringByAppendingPathComponent:@"sample.mp3"]; //NSLog(@"filePath: %@", filePath); [data writeToFile:filePath atomically:YES]; [self playSound:filePath]; } else { UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Store Error" message:[NSString stringWithFormat:@"An Error occured while trying to download sound. Please try again"] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; alertView.tag = 1; [alertView show]; } }