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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 22:38:11