我正在使用 AVAssetwriter 录制视频/音频,并希望能够编写静音样本缓冲区。我在 CoreAudio 方面没有那么有经验,所以我很难想出一个可行的解决方案。
这个想法是在音频设备断开连接时继续录制视频,直到重新连接。问题是,AVFoundation 以某种方式将音频推到前面,因此生成的电影文件大量不同步。
我当前的实现尝试创建一个空/静音 CMSampleBuffer 以放置在没有连接音频设备的段之间。
if (audioOutput == captureOutput && audioWriterInput.readyForMoreMediaData) {
if (needToFillAudioGap) {
CMTime temp = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
CMItemCount numSamples = temp.value - lastAudioDisconnect.value;
OSStatus status;
CMBlockBufferRef bbuf = NULL;
CMSampleBufferRef sbuf = NULL;
int nchans = 2;
size_t buflen = numSamples * nchans * sizeof(float);
NSMutableData* data = [NSMutableData dataWithLength:buflen];
void* samples = [data mutableBytes];
status = CMBlockBufferCreateWithMemoryBlock(
kCFAllocatorDefault,
samples,
buflen,
kCFAllocatorNull,
NULL,
0,
buflen,
0,
&bbuf);
if (status != noErr) {
NSLog(@"CMBlockBufferCreateWithMemoryBlock error: %d", (int)status);
return;
}
CMBlockBufferRef blockBufferContiguous;
status = CMBlockBufferCreateContiguous(kCFAllocatorDefault,
bbuf,
kCFAllocatorNull,
NULL,
0,
buflen,
0,
&blockBufferContiguous);
CFRelease(bbuf);
if(status != noErr)
{
printf("CMBlockBufferCreateContiguous failed with error %d\n", (int)status);
return;
}
status = CMAudioSampleBufferCreateReadyWithPacketDescriptions(kCFAllocatorDefault, blockBufferContiguous, CMSampleBufferGetFormatDescription(sampleBuffer), numSamples, lastAudioDisconnect, NULL, &sbuf);
CFRelease(blockBufferContiguous);
if (status != noErr) {
NSLog(@"CMSampleBufferCreate error: %d", (int)status);
return;
}
BOOL r = [audioWriterInput appendSampleBuffer:sbuf];
if (!r) {
NSLog(@"appendSampleBuffer error: %d", (int)status);
return;
}
CFRelease(sbuf);
NSLog(@"Filling Audio Gap");
needToFillAudioGap = false;
} else {
if ([audioWriterInput appendSampleBuffer:sampleBuffer])
lastAudioDisconnect = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
}
}
顶部的 sampleBuffer 是音频设备重新连接后的第一个 samplebuffer。这让我知道我必须填补多长时间的空白。LastAudioDisconnect 始终保存上次写入的音频样本缓冲区的演示时间戳。
启用 Guard Malloc 后,程序崩溃:CrashIfClientProvidedBogusAudioBufferList
编辑:禁用 Guard Malloc 后,我可以在录制时多次重新连接音频设备,当我停止录制时,间隙没有问题。
那么问题是我在重新连接设备后只有几分钟的时间来停止录制,因为 AVAssetWriter 随机失败,错误代码为 11800 (AVErrorUnknown)。