使用 AudioConverter 将 PCM 转换为 AAC 并使用 AVAssetWriter 写入 .mp4 文件时音频失真

Posted

技术标签:

【中文标题】使用 AudioConverter 将 PCM 转换为 AAC 并使用 AVAssetWriter 写入 .mp4 文件时音频失真【英文标题】:Distorted audio when converting PCM to AAC using AudioConverter and writing to .mp4 file using AVAssetWriter 【发布时间】:2020-01-19 14:01:00 【问题描述】:

我正在尝试压缩来自 AVCaptureSession 的输入并将其保存到 .mp4 文件中。我已成功转换并保存视频,但音频有问题。

我已经到了使用https://github.com/nevyn/LBMediaToolkit 转换音频的地步。我可以将转换后的 CMSampleBuffer 保存为 .mp4,但是当我在 iPhone 上播放它时,音频听起来会失真。

奇怪的是,音频在 QuickTime 中播放时也听起来失真,但在通过网络浏览器播放时听起来不错。点击here下载示例文件。

我认为我将正确的格式传递给转换器:

let asbd = AudiostreamBasicDescription(
    mSampleRate: 44_100,
    mFormatID: kAudioFormatMPEG4AAC,
    mFormatFlags: UInt32(MPEG4ObjectID.AAC_LC.rawValue),
    mBytesPerPacket: 0,
    mFramesPerPacket: 1024,
    mBytesPerFrame: 0,
    mChannelsPerFrame: 2,
    mBitsPerChannel: 0,
    mReserved: 0)

return LBAudioConverter(convertingTo: asbd)

我不确定这是否是音频转换或写入文件的问题。这是一个仅包含音频的示例项目的链接:https://github.com/gaperlinski/AudioConversion(按照 README.MD 中的说明重现问题)

是否有什么明显的错误导致音频听起来失真?

【问题讨论】:

【参考方案1】:

原来罪魁祸首是以下代码:

UInt32 cookieSize = 0;
char cookie[cookieSize];

AudioConverterGetPropertyInfo(_converter, kAudioConverterCompressionMagicCookie, &cookieSize, NULL);
AudioConverterGetProperty(_converter, kAudioConverterCompressionMagicCookie, &cookieSize, cookie);

CMAudioFormatDescriptionRef audioFormat;
const OSStatus formatCreationError = CMAudioFormatDescriptionCreate(
    kCFAllocatorDefault,
    &_toFormat,
    0, NULL, // layout
    cookieSize, cookie, // cookie
    NULL, // extensions
    &audioFormat);
if(formatCreationError != noErr) 
    NSLog(@"Failed to convert a buffer because format creation failed: %d", (int)formatCreationError);
    continue;

我注意到,当我为 CMSampleBuffer 创建格式描述时,我应该只将 magicCookie 添加到 第一个样本缓冲区,或者甚至应该在没有数据。

如果我这样做,音频不会失真,并且 mp4 文件容器中只有一个 esds atom。

【讨论】:

以上是关于使用 AudioConverter 将 PCM 转换为 AAC 并使用 AVAssetWriter 写入 .mp4 文件时音频失真的主要内容,如果未能解决你的问题,请参考以下文章

使用 AudioConverter 更改采样率

使用带有 C# 的 MediaTranscoder 将 PCM 音频转码为 MP3

使用 AudioConverter Swift 将 .m4a 文件转换为 .aiff

音视频开发8. 使用ffmpeg 将pcm转码aac实践(C++)

音视频开发8. 使用ffmpeg 将pcm转码aac实践(C++)

2.基于FFMPEG将PCM转为AAC