修改采样率时AVSampleRateKey引发崩溃,该如何解决?
AVAudioFile设置非44100采样率导致崩溃的问题分析与解决
在使用AVFoundation处理离线音频渲染时,通过AVSampleRateKey指定采样率时,若设置为44100以外的值(如示例中的48000),可能会引发崩溃。以下是问题复现的代码:
func manualAudioRender(effect: Effect) throws { prepareAudioEngine(forEffect: effect) audioPlayerNode.scheduleFile(avAudioFile, at: nil) try audioEngine.enableManualRenderingMode(.offline, format: avAudioFile.processingFormat, maximumFrameCount: maxNumberOfFrames) try audioEngine.start() audioPlayerNode.play() let outputFile: AVAudioFile let url = try PersistenceManager.shared.urlForEffect(named: effect.name) var recordSettings = avAudioFile.fileFormat.settings print("------>>>>. \(recordSettings)") recordSettings[AVSampleRateKey] = 48000.0 print("------>>>>. \(recordSettings)") // var bitRate = audioBitrate // var sampleRate = 44100.0 // var channels = 1 // // let settings: [String: AnyObject] = [ // AVFormatIDKey : NSNumber(value: Int32(kAudioFormatAppleLossless) as Int32), // AVEncoderAudioQualityKey: AVAudioQuality.max.rawValue as AnyObject, // AVEncoderBitRateKey: bitRate as AnyObject, // AVNumberOfChannelsKey: channels as AnyObject, // AVSampleRateKey: sampleRate as AnyObject // ] outputFile = try AVAudioFile(forWriting: url, settings: recordSettings) let buffer = AVAudioPCMBuffer(pcmFormat: audioEngine.manualRenderingFormat, frameCapacity: audioEngine.manualRenderingMaximumFrameCount)! // 根据效果速率调整文件长度 let outputFileLength = Int64(Double(avAudioFile.length) / effect.rate) while audioEngine.manualRenderingSampleTime < outputFileLength { let framesToRender = min(buffer.frameCapacity, AVAudioFrameCount(outputFileLength - audioEngine.manualRenderingSampleTime)) let status = try audioEngine.renderOffline(framesToRender, to: buffer) switch status { case .success: try outputFile.write(from: buffer) case .error: print("离线渲染音频出错") return default: break } } audioPlayerNode.stop() audioEngine.stop() audioEngine.disableManualRenderingMode() }
问题核心原因
- 格式不匹配:音频引擎手动渲染使用的是输入文件的
processingFormat,但输出文件强制修改了采样率,导致渲染生成的PCM buffer格式与输出文件要求的格式不兼容,写入时触发崩溃。 - 设置复用冲突:直接修改输入文件的
fileFormat.settings并替换采样率,可能保留了原格式中与新采样率不兼容的参数(比如特定编码格式对采样率的限制)。
解决方法
1. 统一渲染与输出格式
创建与目标采样率匹配的音频格式,将其作为手动渲染模式的格式参数,确保渲染后的buffer格式与输出文件一致。
2. 显式构建兼容的输出设置
避免复用输入文件的设置,重新构建完整的输出设置字典,确保所有参数与目标采样率兼容。
修改后的完整代码如下:
func manualAudioRender(effect: Effect) throws { prepareAudioEngine(forEffect: effect) audioPlayerNode.scheduleFile(avAudioFile, at: nil) // 定义目标采样率 let targetSampleRate = 48000.0 // 创建与目标采样率匹配的音频格式 guard let targetFormat = AVAudioFormat( commonFormat: avAudioFile.processingFormat.commonFormat, sampleRate: targetSampleRate, channels: avAudioFile.processingFormat.channelCount, interleaved: avAudioFile.processingFormat.isInterleaved ) else { throw NSError(domain: "AudioProcessingError", code: -1, userInfo: [NSLocalizedDescriptionKey: "无法创建符合要求的目标音频格式"]) } // 使用目标格式启用离线渲染模式 try audioEngine.enableManualRenderingMode(.offline, format: targetFormat, maximumFrameCount: maxNumberOfFrames) try audioEngine.start() audioPlayerNode.play() let url = try PersistenceManager.shared.urlForEffect(named: effect.name) // 显式构建输出文件设置,确保参数兼容 let outputSettings: [String: Any] = [ AVFormatIDKey: Int32(kAudioFormatAppleLossless), AVSampleRateKey: targetSampleRate, AVNumberOfChannelsKey: targetFormat.channelCount, AVEncoderAudioQualityKey: AVAudioQuality.max.rawValue ] let outputFile = try AVAudioFile(forWriting: url, settings: outputSettings) let buffer = AVAudioPCMBuffer(pcmFormat: targetFormat, frameCapacity: audioEngine.manualRenderingMaximumFrameCount)! // 根据效果速率调整输出文件长度 let outputFileLength = Int64(Double(avAudioFile.length) / effect.rate) while audioEngine.manualRenderingSampleTime < outputFileLength { let framesToRender = min(buffer.frameCapacity, AVAudioFrameCount(outputFileLength - audioEngine.manualRenderingSampleTime)) let status = try audioEngine.renderOffline(framesToRender, to: buffer) switch status { case .success: try outputFile.write(from: buffer) case .error: print("离线渲染音频出错") return default: break } } audioPlayerNode.stop() audioEngine.stop() audioEngine.disableManualRenderingMode() }
内容的提问来源于stack exchange,提问作者Rezwan
相关产品推荐
相关产品推荐

