Enviar encabezados con la request de AVPlayer en iOS

¿Es posible enviar encabezados con una request http a un file de audio cuando se usa AVPlayer? Necesito poder inspeccionar el contenido del encabezado cuando lo recibe el server para restringir el acceso al file que se solicita.

Tendrá que solicitar los datos usted mismo a través de un mecanismo de connection HTTP genérico como NSURLConnection . Si los NSHTTPURLResponse de NSHTTPURLResponse pasan su testing, entonces debería savelo en NSCachesDirectory y pasar la URL de este recurso al AVPlayer la AVPlayer manera:

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

Puede usar AVURLAssetHTTPHeaderFieldsKey de la opción init de AVURLAsset para modificar los encabezados de request.

Por ejemplo:

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

Nota: Encontré esta key en las fonts de WebKit, pero esta es una key de opción privada , por lo que su aplicación puede rechazarla en AppStore si la utiliza.

Pasé semanas buscando una manera de hacer esto oficialmente para la transmisión de video HLS. Para cualquier persona que esté buscando un enfoque que funcione tanto para las requestes como para las respuestas de la list de reproducción y las requestes de fragment, la única manera que pude encontrar fue que pasó la request de reproducción a través de un proxy inverso, con el que puede interceptar la request , agregue encabezados, envíelo al server real y luego extraiga los encabezados de la respuesta antes de devolverlo al AVPlayer.

Hice un proyecto de ejemplo simple (con muchos comentarios y documentation) aquí: https://github.com/kevinjameshunt/AVPlayer-HTTP-Headers-Example

Considere usar AVURLAsset . Para AVURLAsset puede configurar un delegado resourceLoader. Dentro del método delegado, puede emitir una request manualmente y especificar los encabezados necesarios.

El beneficio de este enfoque es que tiene un control total sobre la carga de datos.

Debe utilizar un esquema de url personalizado para que esta solución funcione (¡http y https no activarán el método de delegado!):

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

El ejemplo de código completo está disponible en https://developer.apple.com/library/content/samplecode/sc1791/Introduction/Intro.html

el código completo podría verse así

  #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 occunetworking while trying to download sound. Please try again"] delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; alertView.tag = 1; [alertView show]; } }