2015-03-13 15 views
24

Questa domanda sembra essere stata posta alcune volte negli ultimi anni, ma nessuno ha una risposta in proposito. Sto cercando di elaborare i dati PCM da HLS e devo usare AVPlayer.Ottenere dati PCM di HLS da AVPlayer

questo post rubinetti i file locali https://chritto.wordpress.com/2013/01/07/processing-avplayers-audio-with-mtaudioprocessingtap/

e questo rubinetto lavoro con i file remoti, ma non con i file .m3u8 HLS. http://venodesigns.net/2014/01/08/recording-live-audio-streams-on-ios/

posso giocare prime due tracce nella playlist, ma non avvia il callback necessarie per ottenere il PCM, quando il file è locale o remoto (non streaming) posso ancora ottenere il PCM, ma è la HLS non funziona e ho bisogno di lavorare HLS

qui è il mio codice

//avplayer tap try 
- (void)viewDidLoad { 
    [super viewDidLoad]; 

    NSURL*testUrl= [NSURL URLWithString:@"http://playlists.ihrhls.com/c5/1469/playlist.m3u8"]; 

    AVPlayerItem *item = [AVPlayerItem playerItemWithURL:testUrl]; 
    self.player = [AVPlayer playerWithPlayerItem:item]; 

    // Watch the status property - when this is good to go, we can access the 
    // underlying AVAssetTrack we need. 
    [item addObserver:self forKeyPath:@"status" options:0 context:nil]; 

} 

-(void)observeValueForKeyPath:(NSString *)keyPath 
ofObject:(id)object 
change:(NSDictionary *)change 
context:(void *)context 
{ 
    if(![keyPath isEqualToString:@"status"]) 
     return; 

    AVPlayerItem *item = (AVPlayerItem *)object; 
    if(item.status != AVPlayerItemStatusReadyToPlay) 
     return; 

    NSArray *tracks = [self.player.currentItem tracks]; 
    for(AVPlayerItemTrack *track in tracks) { 
     if([track.assetTrack.mediaType isEqualToString:AVMediaTypeAudio]) { 
      NSLog(@"GOT DAT FUCKER"); 
      [self beginRecordingAudioFromTrack:track.assetTrack]; 
      [self.player play]; 
     } 
    } 
} 

- (void)beginRecordingAudioFromTrack:(AVAssetTrack *)audioTrack 
{ 
    // Configure an MTAudioProcessingTap to handle things. 
    MTAudioProcessingTapRef tap; 
    MTAudioProcessingTapCallbacks callbacks; 
    callbacks.version = kMTAudioProcessingTapCallbacksVersion_0; 
    callbacks.clientInfo = (__bridge void *)(self); 
    callbacks.init = init; 
    callbacks.prepare = prepare; 
    callbacks.process = process; 
    callbacks.unprepare = unprepare; 
    callbacks.finalize = finalize; 

    OSStatus err = MTAudioProcessingTapCreate(
               kCFAllocatorDefault, 
               &callbacks, 
               kMTAudioProcessingTapCreationFlag_PostEffects, 
               &tap 
              ); 

    if(err) { 
     NSLog(@"Unable to create the Audio Processing Tap %d", (int)err); 
     return; 
    } 

    // Create an AudioMix and assign it to our currently playing "item", which 
    // is just the stream itself. 
    AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix]; 
    AVMutableAudioMixInputParameters *inputParams = [AVMutableAudioMixInputParameters 
                audioMixInputParametersWithTrack:audioTrack]; 

    inputParams.audioTapProcessor = tap; 
    audioMix.inputParameters = @[inputParams]; 
    self.player.currentItem.audioMix = audioMix; 
} 

void process(MTAudioProcessingTapRef tap, CMItemCount numberFrames, 
      MTAudioProcessingTapFlags flags, AudioBufferList *bufferListInOut, 
      CMItemCount *numberFramesOut, MTAudioProcessingTapFlags *flagsOut) 
{ 
    OSStatus err = MTAudioProcessingTapGetSourceAudio(tap, numberFrames, bufferListInOut, 
                 flagsOut, NULL, numberFramesOut); 
    if (err) NSLog(@"Error from GetSourceAudio: %d", (int)err); 

    NSLog(@"Process"); 

} 

void init(MTAudioProcessingTapRef tap, void *clientInfo, void **tapStorageOut) 
{ 
    NSLog(@"Initialising the Audio Tap Processor"); 
    *tapStorageOut = clientInfo; 
} 

void finalize(MTAudioProcessingTapRef tap) 
{ 
    NSLog(@"Finalizing the Audio Tap Processor"); 
} 

void prepare(MTAudioProcessingTapRef tap, CMItemCount maxFrames, const AudioStreamBasicDescription *processingFormat) 
{ 
    NSLog(@"Preparing the Audio Tap Processor"); 
} 

void unprepare(MTAudioProcessingTapRef tap) 
{ 
    NSLog(@"Unpreparing the Audio Tap Processor"); 
} 

void init si chiama void prepare e process deve essere chiamato pure.

come posso fare questo?

+0

Hai avuto successo con questo? Sto lottando con lo stesso problema. – danielbuechele

+0

@danielbuechele sfortunatamente nessuna fortuna, abbiamo dovuto affrontare il problema con un'angolazione diversa, abbiamo proxy la connessione in modo da poter alimentare i file '.m4a' nel nostro codec per analizzare il PCM, quindi inviare i pezzi m4a a un giocatore. E 'stato davvero hacky però. –

+0

Anche se non viene data una risposta, vorrei fare riferimento a una mia domanda risalente a oltre 4 anni fa, che è strettamente correlata. C'è qualcuno che dice che in realtà ci è riuscito, ma lo ha tenuto segreto, come l'ha fatto :( https://stackoverflow.com/questions/19403584/avplayer-hls-live-stream-level-meter-display-fft-data –

risposta

-3

ho consigliato di usare Novocaine

audio Veramente veloce in iOS e Mac OS X utilizzando Audio Units è difficile, e vi lascerà cicatrici e sanguinosa. Ciò che prima richiedeva giorni ora può essere fatto con poche righe di codice.

+0

Qualsiasi esempio di utilizzo? – Robert

+0

Dopo alcune indagini, la novocaina non ha un modo semplice per, ad esempio, ottenere i dati grezzi da un url m3u8 remoto, quindi non è sicuramente una risposta alla domanda dell'OP. –

+1

Novocaine non è una soluzione per la domanda fatta. Alla mia ricerca sull'argomento non esiste un metodo noto per estrarre i campioni PCM usati da AVPlayer durante la riproduzione di HLS. –

Problemi correlati