You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iPhone 16 Pro Max上AVFoundation音频压缩失败问题求助

问题:AVFoundation压缩iPhone 16 Pro Max视频时音频压缩异常

在使用AVFoundation压缩iPhone 16 Pro Max录制的视频时,音频压缩环节出现异常。调用AVAssetWriterInput的appendSampleBuffer方法后,写入器状态变为失败,输出错误信息如下:

关键代码

self.audioSettings = @{
  AVFormatIDKey: @(kAudioFormatMPEG4AAC),
  AVNumberOfChannelsKey: @2,
  AVSampleRateKey: @44100,
  AVEncoderBitRateKey: @128000,
};

[self.audioInput requestMediaDataWhenReadyOnQueue:self.inputQueue usingBlock:^ {
  while (input.isReadyForMoreMediaData) {
    CMSampleBufferRef sampleBuffer = [output copyNextSampleBuffer];
    if (sampleBuffer) {
        if ([input appendSampleBuffer:sampleBuffer]) {
          // Something went wrong here!
        }
    }
  }
}];

错误信息

Error Domain=AVFoundationErrorDomain Code=-11800 "This operation cannot be completed" UserInfo={
  NSLocalizedFailureReason=An unknown error occurred(-12780), 
  NSLocalizedDescription=This operation cannot be completed, 
  NSUnderlyingError=0x3023db8a0 {
    Error Domain=NSOSStatusErrorDomain Code=-12780 "(null)"
  }
}

成因分析

  • iPhone 16 Pro Max录制的原生音频格式大概率是**kAudioFormatAppleLossless(ALAC)**或高规格PCM,你硬编码的音频参数(44.1kHz、双声道)和原始音频的实际参数不匹配,编码器无法兼容处理。
  • 错误码-12780对应AVErrorInvalidSampleBuffer,说明传入的CMSampleBufferRef不符合AVAssetWriterInput的预期:要么是采样率、声道数、编码格式不匹配,要么是样本缓冲区的时间戳、配置信息存在异常。
  • 代码未处理sampleBuffer为空的场景,且写入失败后没有及时终止写入流程并释放资源,导致写入器陷入异常状态。

修复方案

1. 匹配原始音频参数

不要硬编码音频参数,先获取原始视频音频轨道的实际参数,再对应设置编码参数:

// 获取原始音频轨道
AVAssetTrack *audioTrack = [[asset tracksWithMediaType:AVMediaTypeAudio] firstObject];
// 获取音频格式描述
NSDictionary *audioFormatDict = [audioTrack formatDescriptions].firstObject;
CMFormatDescriptionRef formatDesc = (__bridge CMFormatDescriptionRef)audioFormatDict;
const AudioStreamBasicDescription *asbd = CMAudioFormatDescriptionGetStreamBasicDescription(formatDesc);

// 基于原始参数生成编码设置
self.audioSettings = @{
    AVFormatIDKey: @(kAudioFormatMPEG4AAC),
    AVNumberOfChannelsKey: @(asbd->mChannelsPerFrame),
    AVSampleRateKey: @(asbd->mSampleRate),
    AVEncoderBitRateKey: @128000,
};

2. 处理音频格式转换

如果原始音频是ALAC等非PCM格式,需先转换为编码器支持的格式。可以在创建AVAssetReaderTrackOutput时指定输出格式:

AudioStreamBasicDescription outputASBD = {0};
outputASBD.mFormatID = kAudioFormatLinearPCM;
// 匹配原始采样率
outputASBD.mSampleRate = asbd->mSampleRate;
outputASBD.mChannelsPerFrame = asbd->mChannelsPerFrame;
outputASBD.mBitsPerChannel = 16;
outputASBD.mBytesPerPacket = outputASBD.mChannelsPerFrame * 2;
outputASBD.mBytesPerFrame = outputASBD.mChannelsPerFrame * 2;
outputASBD.mFramesPerPacket = 1;
outputASBD.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;

CMFormatDescriptionRef outputFormatDesc = CMAudioFormatDescriptionCreate(kCFAllocatorDefault, &outputASBD, 0, NULL, NULL);
AVAssetReaderTrackOutput *audioOutput = [[AVAssetReaderTrackOutput alloc] initWithTrack:audioTrack outputSettings:(__bridge NSDictionary *)outputFormatDesc];
CFRelease(outputFormatDesc);

3. 完善错误处理逻辑

写入失败时及时获取错误信息,终止写入流程并释放资源:

if (sampleBuffer) {
    if (![input appendSampleBuffer:sampleBuffer]) {
        NSError *writeError = self.assetWriter.error;
        NSLog(@"音频写入失败:%@", writeError.localizedDescription);
        // 终止写入
        [self.assetWriter finishWritingWithCompletionHandler:^{
            // 处理后续清理逻辑
        }];
        break;
    }
    // 释放样本缓冲区
    CFRelease(sampleBuffer);
} else {
    // 无更多样本,结束输入
    [input markAsFinished];
    break;
}

4. 检查时间戳同步

确保音频样本的时间戳和视频样本在同一时间轴上,避免时间戳不连续或超出写入器时间范围:

if (sampleBuffer) {
    CMTime presentationTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
    // 可添加时间戳合法性检查
    if (CMTimeCompare(presentationTime, kCMTimeInvalid) == 0) {
        NSLog(@"无效的音频时间戳");
        CFRelease(sampleBuffer);
        continue;
    }
    // 执行写入操作
}

内容的提问来源于stack exchange,提问作者Mokyz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 09:05:09