Extraire / Enregistrer l'audio du stream HLS (video) pendant la lecture d'iOS

Je joue des streams HLS en utilisant AVPlayer. Et j'ai également besoin d'save ces stream lorsque l'user appuie sur le button d'logging. L'approche que j'utilise est d'save séparément l'audio et la video puis à la fin de merge ces files pour faire la video finale. Et il est réussi avec les files mp4 à distance.

Mais maintenant pour les files HLS (.m3u8), je suis capable d'save la video en utilisant AVAssetWriter mais j'ai des problèmes avec l'logging audio.

J'utilise MTAudioProccessingTap pour traiter datatables audio brutes et les écrire dans un file. J'ai suivi cet article. Je suis capable d'save l'audio mp4 à distance, mais ne fonctionne pas avec les stream HLS. Au départ, je ne pouvais pas extraire les pistes audio du stream en utilisant AVAssetTrack * audioTrack = [asset tracksWithMediaType: AVMediaTypeAudio] [0];

Mais j'ai été capable d'extraire les audioTracks en utilisant KVO pour initialiser le MTAudioProcessingTap.

-(void)observeValueForKeyPath:(NSSsortingng *)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 isEqualToSsortingng: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!"); } }]; } } 

Je suis également suivi de trackID pour vérifier si la piste est modifiée.

C'est ainsi que j'initialise 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; } 

Mais maintenant, avec cette piste audio MTAudioProcessingTap callbacks "Préparer" et "Process" ne sont jamais appelés.

Est-ce que le problème avec l'audioTrack que je traverse KVO?

Maintenant j'apprécierais vraiment si quelqu'un peut m'aider avec ceci. Ou pouvez-vous dire que j'utilise l'approche d'écriture pour save les stream HLS?

J'ai trouvé une solution pour cela et l'utiliser dans mon application. Je voulais l'afficher plus tôt, mais je n'ai pas eu le time.

Donc, pour jouer avec HLS, vous devriez avoir une certaine connaissance de ce qu'ils sont exactement. Pour cela, veuillez le voir ici sur le site Web d'Apple. Apple HLS

Voici les étapes que je suis. 1. Obtenez d'abord le m3u8 et l'parsingr. Vous pouvez l'parsingr en utilisant ce kit utile M3U8Kit . En utilisant ce kit vous pouvez get la M3U8MediaPlaylist ou la M3U8MasterPlaylist (si c'est une playlist principale) si vous obtenez la playlist principale, vous pouvez aussi l'parsingr pour get M3U8MediaPlaylist

 (void) parseM3u8 { NSSsortingng *plainSsortingng = [self.url m3u8PlanSsortingng]; BOOL isMasterPlaylist = [plainSsortingng isMasterPlaylist]; NSError *error; NSURL *baseURL; if(isMasterPlaylist) { M3U8MasterPlaylist *masterList = [[M3U8MasterPlaylist alloc] initWithContentOfURL:self.url error:&error]; self.masterPlaylist = masterList; M3U8ExtXStreamInfList *xStreamInfList = masterList.xStreamList; M3U8ExtXStreamInf *StreamInfo = [xStreamInfList extXStreamInfAtIndex:0]; NSSsortingng *URI = StreamInfo.URI; NSRange range = [URI rangeOfSsortingng:@"dailymotion.com"]; NSSsortingng *baseURLSsortingng = [URI subssortingngToIndex:(range.location+range.length)]; baseURL = [NSURL URLWithSsortingng:baseURLSsortingng]; plainSsortingng = [[NSURL URLWithSsortingng:URI] m3u8PlanSsortingng]; } M3U8MediaPlaylist *mediaPlaylist = [[M3U8MediaPlaylist alloc] initWithContent:plainSsortingng baseURL:baseURL]; self.mediaPlaylist = mediaPlaylist; M3U8SegmentInfoList *segmentInfoList = mediaPlaylist.segmentList; NSMutableArray *segmentUrls = [[NSMutableArray alloc] init]; for (int i = 0; i < segmentInfoList.count; i++) { M3U8SegmentInfo *segmentInfo = [segmentInfoList segmentInfoAtIndex:i]; NSSsortingng *segmentURI = segmentInfo.URI; NSURL *mediaURL = [baseURL URLByAppendingPathComponent:segmentURI]; [segmentUrls addObject:mediaURL]; if(!self.segmentDuration) self.segmentDuration = segmentInfo.duration; } self.segmentFilesURLs = segmentUrls; } 

Vous pouvez voir que vous obtiendrez les liens vers les files .ts à partir du m3u8.

  1. Téléchargez maintenant tout le file .ts dans un dossier local.
  2. Fusionnez ces files .ts dans un file mp4 et Exporter. Vous pouvez le faire en utilisant cette merveilleuse bibliothèque C TS2MP4

et vous pouvez ensuite supprimer les files .ts ou les conserver si vous en avez besoin.

Ce n'est pas une bonne approche que vous pouvez faire est d'parsingr le lien M3U8. Ensuite, essayez de download des files segment (. Si vous pouvez get ces files, vous pouvez les merge pour générer le file mp4.