2013-03-16 47 views
15

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

答えて

5

NSURLConnectionなどの汎用HTTP接続メカニズムを使用して、自分でデータを要求する必要があります。 NSHTTPURLResponseのヘッダは、あなたのテストに合格した場合は、NSCachesDirectoryにそれを保存し、そのようAVPlayerに、このリソースへのURLをオフに渡す必要があります。

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

AVPlayer *player = [AVPlayer playerWithURL:[NSURL fileURLWithPath:filePath]]; 
//... 
+1

1:

は、私はここに(コメントやドキュメントの多くが付いている)簡単なサンプルプロジェクトを作りました。それを別の側から取り組むために。 'AVPlayer'のHTTP通信を妨げる直接的な方法はありません。 – Till

+0

もう一つの選択肢は非常に複雑ですが、オンデバイスプロキシのラフドラフトを使用しています.HTTP経由でデータを要求するクライアントを構築し、HTTP経由でそのデータを提供するサーバーを構築し、 AVPlayerをHTTP経由でローカルサーバーに接続させます。前述のように、実際には複雑ですが、時には唯一のオプションです。あなたのアプリでネイティブにYouTubeコンテンツを再生しようとしている場合。 – Till

+0

これはありがとう!完璧に動作します! upvoted! – rockstarberlin

-3

完全なコードは、この

#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]; 
    } 
} 
ようになります。
35

AVURLAssetのinitオプションのAVURLAssetHTTPHeaderFieldsKeyを使用すると、リクエストヘッダーを変更できます。例えば

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]; 

注:あなたがこれを使用するのであれば、あなたのアプリは、AppStoreで拒否することができる、私はWebKitの源で、このキーを見つけましたが、これはプライベートオプションキーです。

+2

これはまさに私がやっていることです。誰かがこのキーを使ってAppleが却下するかどうかを誰かが確認できますか? – mixtly87

+0

@ mixtly87その鍵を使ってAppStoreにあなたのアプリをアップロードする際に問題がありましたか? –

+1

@JavierGonzalez全く問題はありません。 – mixtly87

1

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

+0

このアプローチはうまくいくが、私の経験では、AVPlayerにチャンクなどを提供することのオーナーシップを取らなければならない。プレイリストとチャンクリクエストとレスポンスでこれを実行できる唯一の方法は、デバイス上でリバースプロキシを実行することでした。 –

2
でご利用いただけます

私はHLSビデオストリーミングのために正式にこれを行う方法を探していました。再生リストとチャンクリクエストの両方のリクエストとレスポンスの両方で動作するアプローチを探している人にとって、再生リクエストをリバースプロキシ経由で渡すことで、これを見つけることができた唯一の方法はリクエストを傍受することができますヘッダーを追加し、実サーバーに送信し、応答からヘッダーを抽出してからAVPlayerに返します。完全に正しい答えを https://github.com/kevinjameshunt/AVPlayer-HTTP-Headers-Example

関連する問題