AVAssetWriter在iPhone 14 Pro的AVAudioSession videoChat模式下失效求助
我开发了一款视频会议应用,为实现回声消除,将AVAudioSession配置为videoChat模式,代码如下:
let options: AVAudioSession.CategoryOptions = [.mixWithOthers , .defaultToSpeaker, .allowBluetooth] try session.setCategory(.playAndRecord, mode: .videoChat, options: options)
同时使用AVAssetWriter API对音频样本进行本地录制,配置代码如下:
let audioAssetWriter = try AVAssetWriter(outputURL: fileURL, fileType: .m4a) let settings: [String: Any] = [ AVFormatIDKey: Int(kAudioFormatMPEG4AAC), AVSampleRateKey: Int(audioParameters.samplingRate), AVEncoderBitRateKey: Int(audioParameters.bitrate), AVNumberOfChannelsKey: Int(audioParameters.channels), AVEncoderAudioQualityKey: AVAudioQuality.max.rawValue ] let assetWriterAudioInput = AVAssetWriterInput(mediaType: .audio, outputSettings: settings) assetWriterAudioInput.expectsMediaDataInRealTime = true audioAssetWriter.add(assetWriterAudioInput)
发现在iPhone 14 Pro设备上,assetWriterAudioInput.append()执行失败,但在iPhone 13及更早设备上一切正常。
可能的原因与解决方案
1. 音频格式参数不匹配
iPhone 14 Pro的音频硬件在videoChat模式下,输出的音频格式(采样率、通道数等)可能和你硬编码的配置不一致,导致append时格式不兼容。
解决方法:
从当前激活的音频会话获取实际的音频参数,替换硬编码值:
guard let inputNode = audioEngine.inputNode else { return } let inputFormat = inputNode.inputFormat(forBus: 0) let settings: [String: Any] = [ AVFormatIDKey: Int(kAudioFormatMPEG4AAC), AVSampleRateKey: inputFormat.sampleRate, AVEncoderBitRateKey: Int(audioParameters.bitrate), AVNumberOfChannelsKey: inputFormat.channelCount, AVEncoderAudioQualityKey: AVAudioQuality.max.rawValue ]
2. videoChat模式的特殊限制
.videoChat模式是针对实时通话优化的,iPhone 14 Pro可能对该模式下的音频捕获数据流做了特殊处理,导致AVAssetWriter无法正常写入。
解决方法:
录制时临时切换到.record模式,完成后切回videoChat:
// 开始录制前切换会话 try session.setCategory(.record, mode: .default, options: .allowBluetooth) // 确保会话激活 try session.setActive(true) // 执行录制逻辑... // 录制完成后切回原配置 try session.setCategory(.playAndRecord, mode: .videoChat, options: [.mixWithOthers , .defaultToSpeaker, .allowBluetooth]) try session.setActive(true)
注意切换会话时要处理可能的中断,确保状态切换成功后再操作。
3. 实时写入的同步问题
iPhone 14 Pro的系统调度更严格,expectsMediaDataInRealTime = true时,若写入时机或速率不匹配会导致失败。
解决方法:
写入前先检查状态,确保可以写入:
if audioAssetWriter.status == .writing && assetWriterAudioInput.isReadyForMoreMediaData { let success = assetWriterAudioInput.append(sampleBuffer) if !success { print("写入失败:\(audioAssetWriter.error?.localizedDescription ?? "未知错误")") } }
同时务必捕获AVAssetWriter的错误信息,根据具体错误码(比如AVErrorInvalidSampleBuffer、AVErrorMediaDataRequiresReconfiguration)针对性排查。
4. iOS版本适配问题
iPhone 14 Pro通常搭载较新的iOS版本,AVAssetWriter的部分行为可能有变化。
解决方法:
检查是否需要设置assetWriterAudioInput.mediaTimeScale,确保音频样本的时间戳和会话时间线同步;也可以尝试使用AVAssetWriterInput的requestMediaDataWhenReady(on:queue:using:)方法替代直接调用append,让系统调度写入时机。
内容的提问来源于stack exchange,提问作者Adeel Abbas

