2013-03-16 19 views

Odpowiedz

5

Będziesz musiał zażądać danych samodzielnie za pośrednictwem ogólnego mechanizmu połączenia HTTP, takiego jak NSURLConnection. Jeśli nagłówki w NSHTTPURLResponse „s zdać egzamin, to należy zapisać go do NSCachesDirectory i zdać się adres URL do tego zasobu do AVPlayer tak:

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 za całkowicie prawidłową odpowiedź. Aby rozwiązać ten problem z innej strony; nie masz bezpośredniego sposobu na zakłócanie komunikacji HTTP z "AVPlayer". – Till

+0

Inną opcją, ale NAPRAWDĘ skomplikowaną, byłoby użycie na urządzeniu proxy - wersja robocza: zbuduj klienta, który żąda danych przez HTTP (na twoim urządzeniu), zbuduj serwer, który oferuje te dane przez HTTP (na twoim urządzeniu), pozwól AVPlayer połączyć się z lokalnym serwerem za pośrednictwem HTTP. Jak wspomniano, bardzo skomplikowane, ale czasami jedyną opcją - np. jeśli próbujesz odtwarzać treści z YouTube natywnie w swojej aplikacji. – Till

+0

dzięki za to! działa idealnie! przegłosowane! – rockstarberlin

-3

pełny kod mógłby wyglądać następująco

#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

Możesz użyć opcji inicjowania AVURLAssetHTTPHeaderFieldsKey z AVURLAsset, aby zmodyfikować nagłówki żądań.

Na przykład:

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

Uwaga: znalazłem ten kluczyk źródeł WebKit, ale jest to klucz prywatny opcja, więc aplikacja może odrzucić przez AppStore jeśli to wykorzystać.

+2

To jest dokładnie to, co robię. Czy ktoś może zweryfikować, czy aplikacja zostanie odrzucona przez Apple w związku z użyciem tego klucza? – mixtly87

+0

@ mixtly87 czy wystąpił problem z przesłaniem aplikacji do sklepu AppStore za pomocą tego klucza? –

+1

@JavierGonzalez Brak problemów. – mixtly87

1

Rozważ użycie AVURLAsset. Dla AVURLAsset można skonfigurować delegata resourceLoader. Wewnątrz metody delegatów możesz ręcznie wysłać żądanie, określając niezbędne nagłówki.

Zaleta tego podejścia polega na tym, że masz pełną kontrolę nad ładowaniem danych.

Musisz użyć własnego schematu URL w celu uczynienia tej pracy Solution (http i https nie wywoła metodę delegata!):

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

Pełny przykład kodu jest dostępny na https://developer.apple.com/library/content/samplecode/sc1791/Introduction/Intro.html

+0

To podejście zadziała, ale w moim doświadczeniu musisz przejąć na własność dostarczanie kawałków, itp. Do AVPlayera. Jedynym sposobem, w jaki mogłem to zrobić dla list odtwarzania ORAZ porcji żądań i odpowiedzi było uruchomienie odwrotnego proxy na urządzeniu. –

2

Spędziłem tygodnie szukając sposobu, aby zrobić to oficjalnie dla streamingu wideo HLS. Dla każdego, kto szuka podejścia, które będzie działać zarówno dla żądań, jak i odpowiedzi dla list odtwarzania i żądań kawałków, jedynym sposobem, jaki udało mi się znaleźć, było przekazanie żądania odtwarzania przez odwrotne proxy, dzięki czemu można przechwycić żądanie. , dodaj nagłówki, wyślij je do prawdziwego serwera, a następnie wyodrębnij nagłówki z odpowiedzi przed zwróceniem jej do odtwarzacza AVPlayer.

Zrobiłem prosty przykład projekt (z dużą ilością komentarzy i dokumentacją) tutaj: https://github.com/kevinjameshunt/AVPlayer-HTTP-Headers-Example

Powiązane problemy