Extrahieren / Aufnehmen von Audio aus dem HLS-Stream (Video) während der Wiedergabe von iOS

Ich spiele HLS-Streams mit AVPlayer ab. Außerdem muss ich diese Streams aufzeichnen, wenn der Benutzer die Aufnahmetaste drückt. Der von mir verwendete Ansatz besteht darin, Audio und Video getrennt aufzunehmen und diese Dateien am Ende zusammenzuführen, um das endgültige Video zu erstellen. Und es ist erfolgreich mit Remote-MP4-Dateien.

Aber jetzt für die HLS-Dateien (.m3u8) kann ich das Video mit AVAssetWriter aufnehmen, habe jedoch Probleme mit der Audioaufnahme.

Ich verwende MTAudioProccessingTap, um die Audio-Rohdaten zu verarbeiten und in eine Datei zu schreiben. Ich folgteDie artikel. Ich kann ferngesteuertes mp4-Audio aufnehmen, aber es funktioniert nicht mit HLS-Streams. Anfangs war es mir nicht möglich, die Audiospuren mit AVAssetTrack * audioTrack = [asset tracksWithMediaType: AVMediaTypeAudio] [0] aus dem Stream zu extrahieren;

Aber ich konnte die AudioTracks mit KVO extrahieren, um MTAudioProcessingTap zu initialisieren.

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
AVPlayer *player = (AVPlayer*) object;

if (player.status == AVPlayerStatusReadyToPlay)
{
    NSLog(@"Ready to play");
    self.previousAudioTrackID = 0;


        __weak typeof (self) weakself = self;

        timeObserverForTrack = [player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(1, 100) queue:nil usingBlock:^(CMTime time)
                {

                    @try {

                            for(AVPlayerItemTrack* track in [weakself.avPlayer.currentItem tracks]) {
                                if([track.assetTrack.mediaType isEqualToString:AVMediaTypeAudio])
                                    weakself.currentAudioPlayerItemTrack = track;

                            }

                            AVAssetTrack* audioAssetTrack = weakself.currentAudioPlayerItemTrack.assetTrack;


                            weakself.currentAudioTrackID = audioAssetTrack.trackID;

                            if(weakself.previousAudioTrackID != weakself.currentAudioTrackID) {

                                NSLog(@":::::::::::::::::::::::::: Audio track changed : %d",weakself.currentAudioTrackID);
                                weakself.previousAudioTrackID = weakself.currentAudioTrackID;
                                weakself.audioTrack = audioAssetTrack;
                                /// Use this audio track to initialize MTAudioProcessingTap
                            }
                        }
                        @catch (NSException *exception) {
                            NSLog(@"Exception Trap ::::: Audio tracks not found!");
                        }

                }];


    }
}  

Ich verfolge auch die Track-ID, um zu überprüfen, ob der Track geändert wurde.

So initialisiere ich das MTAudioProcessingTap.

-(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);
    NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain
                                         code:err
                                     userInfo:nil];
    NSLog(@"Error: %@", [error description]);;
    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];
_audioPlayer.currentItem.audioMix = audioMix;
}

Aber jetzt werden mit dieser Audiospur MTAudioProcessingTap-Rückrufe "Prepare" und "Process" niemals aufgerufen.

Ist das Problem mit dem AudioTrack, den ich über KVO erhalte?

Now Ich würde mich sehr freuen, wenn mir jemand dabei helfen kann. Oder kann ich sagen, ob ich die Schreibmethode verwende, um HLS-Streams aufzuzeichnen?

Antworten auf die Frage(4)

Ihre Antwort auf die Frage