ios – 将音频缓冲区[从文件]添加到“实时”音频缓冲区[记录到文件]

我想做什么:

录制到指定的音频/视频持续时间,其中生成的输出文件将添加来自外部音频文件的预定义背景音乐 – 录制后无需进一步编码/导出.

好像您正在使用iPhone相机应用程序录制视频,并且“相机胶卷”中的所有录制视频都有背景歌曲.结束录制后无法导出或加载,而不是单独的AudioTrack.

我是如何努力实现这一目标的:

通过使用AVCaptureSession,在传递(CMSampleBufferRef)样本缓冲区的委托方法中,我将它们推送到AVAssetWriter以写入文件.由于我不想在输出文件中输入多个音轨,因此无法通过单独的AVAssetWriterInput传递背景音乐,这意味着我必须在录制时将背景音乐添加到录制的每个样本缓冲区以避免录制后必须合并/导出.

背景音乐是​​一种特定的,预定义的音频文件(格式/编解码器:m4a aac),不需要时间编辑,只需在整个录音下添加,从头到尾.录音永远不会比背景音乐文件长.

在开始写入文件之前,我还准备了一个AVAssetReader,读取指定的音频文件.

一些伪代码(排除线程):

-(void)startRecording
{
    /*
        Initialize writer and reader here: [...]
    */

    backgroundAudioTrackOutput = [AVAssetReaderTrackOutput 
                            assetReaderTrackOutputWithTrack:
                                backgroundAudioTrack 
                            outputSettings:nil];

    if([backgroundAudioReader canAddOutput:backgroundAudioTrackOutput])
        [backgroundAudioReader addOutput:backgroundAudioTrackOutput];
    else
        NSLog(@"This doesn't happen");

    [backgroundAudioReader startReading];

    /* Some more code */

    recording = YES;
}
- (void)captureOutput:(AVCaptureOutput *)captureOutput 
             didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
             fromConnection:(AVCaptureConnection *)connection
{
    if(!recording)
        return;

    if(videoConnection)
        [self writeVideoSampleBuffer:sampleBuffer];
    else if(audioConnection)
        [self writeAudioSampleBuffer:sampleBuffer];
}

AVCaptureSession已经在流式传输摄像机视频和麦克风音频,只是等待BOOL录制设置为YES.这不是我正在做的事情,而是一个简短的,某种程度上等同的表示.当委托方法收到Audio类型的CMSampleBufferRef时,我调用自己的方法writeAudioSamplebuffer:sampleBuffer.如果要正常完成,没有我正在尝试的后台跟踪,我只需要输入如下内容:[assetWriterAudioInput appendSampleBuffer:sampleBuffer];而不是调用我的方法.在我的情况下,我需要在写入之前重叠两个缓冲区:

-(void)writeAudioSamplebuffer:(CMSampleBufferRef)recordedSampleBuffer
{
    CMSampleBufferRef backgroundSampleBuffer = 
                     [backgroundAudioTrackOutput copyNextSampleBuffer];

    /* DO MAGIC HERE  */
    CMSampleBufferRef resultSampleBuffer = 
                         [self overlapBuffer:recordedSampleBuffer 
                            withBackgroundBuffer:backgroundSampleBuffer];
    /* END MAGIC HERE */

    [assetWriterAudioInput appendSampleBuffer:resultSampleBuffer];
}

问题:

我必须将增量样本缓冲区从本地文件添加到进入的实时缓冲区.我创建的名为overlapBuffer:withBackgroundBuffer:的方法现在做得不多.我知道如何从CMSampleBufferRef中提取AudioBufferList,AudioBuffer和mData等,但我不确定如何将它们实际添加到一起 – 但是 – 我无法测试不同的方法来做到这一点,因为真正的问题发生了在那之前.在Magic发生之前,我拥有两个CMSampleBufferRefs,一个从麦克风接收,一个从文件读取,这就是问题所在:

从background-music-file接收的样本缓冲区与从录制会话中收到的样本缓冲区不同.这似乎是对[self.backgroundAudioTrackOutput copyNextSampleBuffer]的调用;收到大量样本.我意识到这对某些人来说可能是显而易见的,但我从来没有达到这种媒体技术水平.我现在看到,每次从会话中收到sampleBuffer时调用copyNextSampleBuffer是一厢情愿的想法,但我不知道何时/何时放置它.

据我所知,录制会话在每个样本缓冲区中提供一个音频样本,而文件读取器在每个样本缓冲区中提供多个样本.我可以以某种方式创建一个计数器来计算每个接收到的记录样本/缓冲区,然后使用第一个file-sampleBuffer提取每个样本,直到当前file-sampleBuffer没有更多样本’给’,然后调用[..copyNext ..],并对缓冲区做同样的事情?

由于我完全控制了录音和文件的编解码器,格式等,我希望这样的解决方案不会破坏音频的“对齐”/同步.鉴于两个样本都具有相同的sampleRate,这仍然是一个问题吗?

注意

我甚至不确定这是否可行,但我认为没有直接的原因.
另外值得一提的是,当我尝试使用视频文件而不是音频文件,并尝试不断拉动视频样本缓冲区时,它们完美地对齐.

最佳答案
我不熟悉AVCaptureOutput,因为我的所有声音/音乐会话都是使用AudioToolbox而不是AVFoundation构建的.但是,我猜你应该能够设置录制捕获缓冲区的大小.如果没有,并且您仍然只获得一个样本,我建议您将从捕获输出获得的每个单独数据存储在辅助缓冲区中.当辅助缓冲区达到与文件读取缓冲区相同的大小时,然后调用[self overlapBuffer:auxiliarSampleBuffer withBackgroundBuffer:backgroundSampleBuffer];

我希望这会对你有所帮助.如果没有,我可以提供有关如何使用CoreAudio执行此操作的示例.使用CoreAudio我已经能够从麦克风捕获和文件读取中获得1024个LCPM样本缓冲区.所以重叠是立竿见影的.

转载注明原文:ios – 将音频缓冲区[从文件]添加到“实时”音频缓冲区[记录到文件] - 代码日志