web-dev-qa-db-ja.com

AVPlayerのリクエストにカスタムヘッダーフィールドを追加

AVPlayerを使用しているときに、httpリクエストを含むヘッダーをオーディオファイルに送信することは可能ですか?要求されているファイルへのアクセスを制限するために、サーバーが受信したときにヘッダーのコンテンツを検査できる必要があります。

23
user732538

NSURLConnectionなどの一般的なHTTP接続メカニズムを介して自分でデータをリクエストする必要があります。 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]];
//...
9
Jacob Relkin

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のソースで見つかりましたが、これはPrivateオプションキーであるため、これを使用すると、アプリがAppStoreによって拒否される可能性があります。

57
naituw

私はHLSビデオストリーミングのためにこれを公式に行う方法を探して何週間も費やしました。プレイリストとチャンクリクエストのリクエストとレスポンスの両方で機能するアプローチを探している人にとって、それが機能することを見つけることができた唯一の方法は、リクエストをインターセプトできるリバースプロキシを介して再生リクエストを渡すことでした。 、ヘッダーを追加して実サーバーに送信し、応答からヘッダーを抽出してからAVPlayerに返します。

ここで簡単なサンプルプロジェクト(コメントとドキュメントがたくさんあります)を作成しました: https://github.com/kevinjameshunt/AVPlayer-HTTP-Headers-Example

4

Swiftで回答すると、AVURLAssetHTTPHeaderFieldsKeyオプションは魅力のように機能します。

 let headers: HTTPHeaders = [
    "custome_header": "custome value"
 ]
 let asset = AVURLAsset(url: URL, options: ["AVURLAssetHTTPHeaderFieldsKey": headers])
 let playerItem = AVPlayerItem(asset: asset)
 player = AVPlayer(playerItem: item)
2
minhhq

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 で入手できます。

2