在播放iOS时从HLS流(video)中提取/录制音频

我正在使用AVPlayer播放HLS流。 我还需要在用户按下记录按钮时记录这些流。 我正在使用的方法是分别录制音频和video,然后在最后合并这些文件以制作最终video。 并且它对远程mp4文件很成功。

但是现在对于HLS(.m3u8)文件,我能够使用AVAssetWriter录制video,但是录音有问题。

我正在使用MTAudioProccessingTap处理原始音频数据并将其写入文件。 我跟着这篇文章。 我能够录制远程mp4音频但不能使用HLS流。 最初我无法使用AVAssetTrack * audioTrack = [asset tracksWithMediaType:AVMediaTypeAudio] [0]从流中提取音轨。

但我能够使用KVO提取audioTracks来初始化MTAudioProcessingTap。

-(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!"); } }]; } } 

我还跟踪trackID以检查曲目是否已更改。

这是我初始化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; } 

但现在有了这个音频轨道MTAudioProcessingTap回调“准备”和“进程”永远不会被调用。

我是通过KVO获得audioTrack的问题吗?

现在我真的很感激,如果有人可以帮助我。 或者可以告诉我是否使用写入方法来记录HLS流?

我找到了解决方案,并在我的应用程序中使用它。 想早点发布,但没有时间。

因此,要使用HLS,您应该知道它们究竟是什么。 为此,请在Apple网站上查看。 HLS Apple

以下是我要遵循的步骤。 1.首先获取m3u8并解析它。 您可以使用这个有用的套件M3U8Kit解析它。 使用此工具包,您可以获得M3U8MediaPlaylist或M3U8MasterPlaylist(如果它是主播放列表)如果您获得主播放列表,您也可以解析它以获得M3U8MediaPlaylist

 (void) parseM3u8 { NSString *plainString = [self.url m3u8PlanString]; BOOL isMasterPlaylist = [plainString 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]; NSString *URI = StreamInfo.URI; NSRange range = [URI rangeOfString:@"dailymotion.com"]; NSString *baseURLString = [URI substringToIndex:(range.location+range.length)]; baseURL = [NSURL URLWithString:baseURLString]; plainString = [[NSURL URLWithString:URI] m3u8PlanString]; } M3U8MediaPlaylist *mediaPlaylist = [[M3U8MediaPlaylist alloc] initWithContent:plainString 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]; NSString *segmentURI = segmentInfo.URI; NSURL *mediaURL = [baseURL URLByAppendingPathComponent:segmentURI]; [segmentUrls addObject:mediaURL]; if(!self.segmentDuration) self.segmentDuration = segmentInfo.duration; } self.segmentFilesURLs = segmentUrls; } 

您可以看到,您将从m3u8获取指向.ts文件的链接。

  1. 现在将所有.ts文件下载到本地文件夹中。
  2. 将这些.ts文件合并到一个mp4文件和导出。 你可以使用这个精彩的C库TS2MP4来做到这一点

然后你可以删除.ts文件或在需要时保留它们。

这不是一个好方法,你可以做的是解析M3U8链接。然后尝试下载段文件(.ts)。 如果您可以获取这些文件,则可以合并它们以生成mp4文件。