2013-03-16 8 views
15

Ist es möglich, Header mit einer HTTP-Anfrage an eine Audiodatei senden, wenn Sie AVPlayer verwenden? Ich muss in der Lage sein, den Inhalt des Headers zu überprüfen, wenn er vom Server empfangen wird, um den Zugriff auf die angeforderte Datei zu beschränken.Senden Header mit AVPlayer Anfrage in iOS

Antwort

5

Sie müssen die Daten über einen generischen HTTP-Verbindungsmechanismus wie z. B. NSURLConnection anfordern. Wenn die NSHTTPURLResponse ‚s Header Ihr Test zu bestehen, dann sollten Sie es in die NSCachesDirectory speichern und die URL zu dieser Ressource an den AVPlayer wie so abgehen:

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 für völlig richtige Antwort. Um es von einer anderen Seite anzugehen; Sie haben keine direkte Möglichkeit, die HTTP-Kommunikation von 'AVPlayer' zu stören. – Till

+0

Eine andere Option, aber WIRKLICH kompliziert, wäre ein On-Device-Proxy - Grobentwurf: Erstellen Sie einen Client, der Daten über HTTP (auf Ihrem Gerät) anfordert, erstellen Sie einen Server, der diese Daten über HTTP (auf Ihrem Gerät) anbietet, Lassen Sie den AVPlayer über HTTP mit Ihrem lokalen Server verbinden. Wie gesagt, wirklich kompliziert, aber manchmal die einzige Option - z. wenn du YouTube-Inhalte nativ in deiner App wiedergeben möchtest. – Till

+0

danke dafür! funktioniert perfekt! aufgewertet! – rockstarberlin

-3

den vollständigen Code könnte wie folgt aussehen

#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

Sie können die Init-Option AVURLAssetHTTPHeaderFieldsKey von AVURLAsset verwenden, um Anforderungsheader zu ändern.

Zum Beispiel:

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

Hinweis: Ich habe diesen Schlüssel in Quellen von WebKit gefunden, aber das ist eine Privat Optionstaste, so dass Ihre App von App Store ablehnen können, wenn Sie diese verwenden.

+2

Genau das mache ich. Kann jemand überprüfen, ob die App von Apple zur Verwendung dieses Schlüssels abgelehnt wird? – mixtly87

+0

@ mixly87 Haben Sie Probleme beim Hochladen Ihrer App in den AppStore mit diesem Schlüssel? –

+1

@JavierGonzalez Keine Probleme. – mixtly87

1

Verwenden Sie AVURLAsset. Für AVURLAsset können Sie einen ResourceLoader-Delegaten einrichten. Innerhalb der Delegate-Methode können Sie eine Anfrage manuell eingeben und notwendige Header angeben.

Der Vorteil dieses Ansatzes besteht darin, dass Sie die Daten vollständig laden können.

Sie haben eine eigene URL-Schema verwenden, um diese Lösung arbeiten zu lassen (http und https nicht die delegierte Methode auslösen!):

-(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; 
} 

Vollcodebeispiel bei https://developer.apple.com/library/content/samplecode/sc1791/Introduction/Intro.html verfügbar ist

+0

Dieser Ansatz funktioniert, aber Sie müssen die Verantwortung dafür übernehmen, dem AVPlayer nach meiner Erfahrung Stücke usw. zur Verfügung zu stellen. Die einzige Möglichkeit, dies für Wiedergabelisten UND Chunk-Anfragen und -Antworten zu tun, war die Ausführung eines Reverse-Proxy auf dem Gerät. –

2

Ich habe Wochen damit verbracht, nach einer Möglichkeit zu suchen, dies offiziell für HLS-Video-Streaming zu tun. Für alle, die nach einem Ansatz suchten, der sowohl für Anfragen als auch für Antworten auf die Playlist- und Chunk-Anfragen funktionierte, konnte ich die Abspielanforderung nur über einen Reverse Proxy abfragen, mit dem Sie die Anfrage abfangen können Fügen Sie Header hinzu, senden Sie sie an den echten Server und extrahieren Sie dann die Header aus der Antwort, bevor Sie sie an den AVPlayer zurücksenden.

Ich habe ein einfaches Beispiel-Projekt (mit vielen Kommentaren und Dokumentation) hier: https://github.com/kevinjameshunt/AVPlayer-HTTP-Headers-Example