Envoyer les en-têtes avec la requête AVPlayer dans iOS

Est-il possible d'envoyer des en-têtes avec une requête http à un file audio lors de l'utilisation d'AVPlayer? Je dois être en mesure d'inspecter le contenu de l'en-tête lorsqu'il est reçu par le server afin de restreindre l'access au file demandé.

Vous devrez vous-même requestr datatables via un mécanisme de connection HTTP générique tel que NSURLConnection . Si les en- NSHTTPURLResponse de NSHTTPURLResponse réussissent votre test, vous devez l'save dans NSCachesDirectory et transmettre l'URL de cette ressource à l' AVPlayer comme ceci:

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

Vous pouvez utiliser l'option init de AVURLAssetHTTPHeaderFieldsKey of AVURLAsset pour modifier les en-têtes de requête.

Par exemple:

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

Remarque: J'ai trouvé cette key dans les sources de WebKit, mais il s'agit d'une key d'option privée . Votre application peut donc être rejetée par l'AppStore si vous l'utilisez.

J'ai passé des semaines à chercher un moyen de le faire officiellement pour le streaming video HLS. Pour tous ceux qui searchnt une approche qui fonctionnerait à la fois pour les requêtes et les réponses pour les lists de lecture et les requêtes de bloc, la seule façon de find le résultat est de passer la requête de lecture via un proxy inverse, ce qui vous permet d'intercepter la requête , ajoutez des en-têtes, envoyez-les au server réel, puis extrayez les en-têtes de la réponse avant de les renvoyer à l'AVPlayer.

J'ai fait un exemple de projet simple (avec beaucoup de commentaires et de documentation) ici: https://github.com/kevinjameshunt/AVPlayer-HTTP-Headers-Example

Envisagez d'utiliser AVURLAsset . Pour AVURLAsset vous pouvez configurer un délégué resourceLoader. Dans la méthode déléguée, vous pouvez émettre une request manuellement en spécifiant les en-têtes nécessaires.

L'avantage de cette approche est que vous avez un contrôle total sur le chargement des données.

Vous devez utiliser un schéma d'URL personnalisé pour que cette solution fonctionne (http et https ne triggersront pas la méthode déléguée!):

 -(void) play { NSURL * url = [URL URLWithSsortingng:@"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 URLWithSsortingng:@"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; } 

L'exemple de code complet est disponible sur https://developer.apple.com/library/content/samplecode/sc1791/Introduction/Intro.html

le code complet pourrait ressembler à ceci

  #pragma Mark Sound Stuff - (void)playSound:(NSSsortingng *)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)initSoundPrelistn { //NSLog(@"begin: %s", __FUNCTION__); self.activityIndicator.hidden = NO; [self.activityIndicator startAnimating]; // verification delegate : register dataProtocol = [[StoreConnection alloc] init]; [dataProtocol setDelegate:self]; [dataProtocol requestDataFromServer:[NSSsortingng ssortingngWithFormat:@"sound/%@/audio/sample", [self.sound objectForKey:@"globalId"]]]; } - (void)dataSuccessful:(BOOL)success successData:(NSMutableData *)data; { NSLog(@"%s", __FUNCTION__); if (success) { //NSLog(@"sound data: %@", data); NSSsortingng *cacheDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSSsortingng *filePath = [cacheDirectory ssortingngByAppendingPathComponent:@"sample.mp3"]; //NSLog(@"filePath: %@", filePath); [data writeToFile:filePath atomically:YES]; [self playSound:filePath]; } else { UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Store Error" message:[NSSsortingng ssortingngWithFormat:@"An Error occured while trying to download sound. Please try again"] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; alertView.tag = 1; [alertView show]; } }