如何在Swift中将AAC编码的octet-stream转换为WAV文件?
解决原始ADTS AAC转WAV的Swift实现方案
你的问题核心在于原始ADTS格式的AAC文件无法直接被AVAudioFile识别——虽然主流播放器能自动解析ADTS头,但AVFoundation的AVAudioFile对无容器的原始AAC流支持有限。以下是基于AVAssetReader和AVAssetWriter的可靠转码实现:
核心实现代码
import AVFoundation func convertADTSAACtoWAV(inputURL: URL, outputURL: URL) async throws { // 加载输入音频资源 let asset = AVAsset(url: inputURL) // 获取音频轨道 guard let audioTrack = asset.tracks(withMediaType: .audio).first else { throw NSError(domain: "ConversionError", code: 1, userInfo: [NSLocalizedDescriptionKey: "输入文件中未找到音频轨道"]) } // 配置读取器输出格式:指定为WAV兼容的Linear PCM格式 let pcmOutputSettings: [String: Any] = [ AVFormatIDKey: kAudioFormatLinearPCM, AVSampleRateKey: 48000, // 匹配你的文件采样率 AVNumberOfChannelsKey: 2, // 双声道 AVLinearPCMBitDepthKey: 16, AVLinearPCMIsBigEndianKey: false, AVLinearPCMIsFloatKey: false ] // 创建资源读取器及输出 guard let reader = try? AVAssetReader(asset: asset), let readerOutput = AVAssetReaderTrackOutput(track: audioTrack, outputSettings: pcmOutputSettings) else { throw NSError(domain: "ConversionError", code: 2, userInfo: [NSLocalizedDescriptionKey: "无法创建AVAssetReader或输出对象"]) } reader.add(readerOutput) // 创建资源写入器及输入 guard let writer = try? AVAssetWriter(outputURL: outputURL, fileType: .wav), let sourceFormatHint = readerOutput.formatDescriptions.first as? CMFormatDescription, let writerInput = AVAssetWriterInput(mediaType: .audio, outputSettings: nil, sourceFormatHint: sourceFormatHint) else { throw NSError(domain: "ConversionError", code: 3, userInfo: [NSLocalizedDescriptionKey: "无法创建AVAssetWriter或输入对象"]) } writerInput.expectsMediaDataInRealTime = false writer.add(writerInput) // 启动转码流程 reader.startReading() writer.startWriting() writer.startSession(atSourceTime: .zero) // 异步处理音频缓冲区 let dispatchQueue = DispatchQueue(label: "com.audio.conversion.queue") await withCheckedThrowingContinuation { continuation in writerInput.requestMediaDataWhenReady(on: dispatchQueue) { while writerInput.isReadyForMoreMediaData { guard let sampleBuffer = readerOutput.copyNextSampleBuffer() else { writerInput.markAsFinished() writer.finishWriting { if writer.status == .completed { continuation.resume() } else { continuation.resume(throwing: writer.error ?? NSError(domain: "ConversionError", code: 4, userInfo: [NSLocalizedDescriptionKey: "转码写入失败"])) } } return } writerInput.append(sampleBuffer) } } } } // 使用示例 do { let inputURL = URL(fileURLWithPath: "/你的文件路径/recording.aac") let outputURL = URL(fileURLWithPath: "/输出路径/output.wav") try await convertADTSAACtoWAV(inputURL: inputURL, outputURL: outputURL) print("转码完成!") } catch { print("转码失败:\(error.localizedDescription)") }
关键说明
- 为什么不用
AVAudioFile?AVAudioFile依赖完整的文件容器结构,而你的原始ADTS AAC仅包含裸音频帧和ADTS头,缺少容器元数据,导致初始化失败。 AVAssetReader/Writer的优势:
这两个是AVFoundation的底层媒体处理组件,能直接解析ADTS格式的AAC流,并将解码后的PCM数据写入WAV容器。- 格式匹配:
代码中PCM参数完全匹配你的文件信息(48000采样率、双声道),确保转码后音频质量一致。
注意事项
- 权限:在iOS/macOS应用中,需确保拥有文件读取和写入权限(如iOS需配置文件访问相关权限描述,macOS需申请文件访问权限)。
- 文件路径:使用时替换示例中的输入输出路径为实际路径。
内容的提问来源于stack exchange,提问作者John Carraher
相关产品推荐
相关产品推荐

