提取/记录音频从HLS流(视频),而播放iOS



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

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

我使用mtaudioprocessingtap来处理原始音频数据并将其写入文件。我看了这篇文章。我能够录制远程mp4音频,但它不能与HLS流一起工作。最初,我无法使用AVAssetTrack *audioTrack = [asset tracksWithMediaType:AVMediaTypeAudio][0]从流中提取音轨;

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

-(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回调"准备"one_answers"过程"永远不会被调用。

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

如果有人能帮我解决这个问题,我将非常感激。或者我是否使用了写入方法来记录HLS流?

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

所以要玩HLS,你应该对它们到底是什么有一些了解。请在苹果网站上查看。HLS苹果

以下是我正在遵循的步骤。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文件的链接。

  • 现在下载所有的。ts文件到本地文件夹。
  • 合并这些。ts文件到一个mp4文件和导出。你可以使用这个很棒的C库TS2MP4
  • ,然后您可以删除。ts文件,或者如果需要的话保留它们。

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

    最新更新