使用AVWriter/AVReader从.mp4视频写入零字节文件中提取.wav音频的Swift代码

使用AVWriter/AVReader从.mp4视频写入零字节文件中提取.wav音频的Swift代码,swift,avfoundation,Swift,Avfoundation,我已经浏览了这里的文档和所有帖子,我已经走了这么远 下面的函数应该使用AVAsset并写出一个.wav文件。但是,写入的文件的字节数为零。我甚至不确定我能不能检查一下作者在每一步都写了些什么 我错过了什么 static func writeAudioTrackToUrl(asset: AVAsset, _ url: URL) throws { // initialize asset reader, writer let assetReader = try AVAssetR

我已经浏览了这里的文档和所有帖子,我已经走了这么远

下面的函数应该使用AVAsset并写出一个.wav文件。但是,写入的文件的字节数为零。我甚至不确定我能不能检查一下作者在每一步都写了些什么

我错过了什么

    static func writeAudioTrackToUrl(asset: AVAsset, _ url: URL) throws {
    // initialize asset reader, writer
    let assetReader = try AVAssetReader(asset: asset)
    let assetWriter = try AVAssetWriter(outputURL: URL(fileURLWithPath: "/tmp/audiowav.wav"), fileType: .wav)
    
    // get audio track
    let audioTrack = asset.tracks(withMediaType: AVMediaType.audio).first!
    
    // configure output audio settings
    let audioSettings: [String : Any] = [
        AVFormatIDKey: kAudioFormatLinearPCM,
        AVSampleRateKey: 22050.0,
        AVNumberOfChannelsKey: 1,
        AVLinearPCMBitDepthKey: 16,
        AVLinearPCMIsFloatKey: false,
        AVLinearPCMIsBigEndianKey: false,
        AVLinearPCMIsNonInterleaved: false
    ]
    let assetReaderAudioOutput = AVAssetReaderTrackOutput(track: audioTrack, outputSettings: audioSettings)
    
    if assetReader.canAdd(assetReaderAudioOutput) {
        assetReader.add(assetReaderAudioOutput)
    } else {
        fatalError("could not add audio output reader")
    }
    
    let inputAudioSettings: [String:Any] = [AVFormatIDKey : kAudioFormatLinearPCM]
    let audioInput = AVAssetWriterInput(mediaType: AVMediaType.audio, outputSettings: inputAudioSettings, sourceFormatHint: (audioTrack.formatDescriptions[0] as! CMFormatDescription))
    
    let audioInputQueue = DispatchQueue(label: "audioQueue")
    assetWriter.add(audioInput)
    
    assetWriter.startWriting()
    assetReader.startReading()
    assetWriter.startSession(atSourceTime: CMTime.zero)
    
    audioInput.requestMediaDataWhenReady(on: audioInputQueue) {
        while (audioInput.isReadyForMoreMediaData) {
            let sample = assetReaderAudioOutput.copyNextSampleBuffer()
            if (sample != nil) {
                audioInput.append(sample!)
            } else {
                audioInput.markAsFinished()
                DispatchQueue.main.async {
                    assetWriter.finishWriting {
                        assetReader.cancelReading()
                    }
                }
                break
            }
        }
    }
}

这里的问题是,您将输入音频转换为
audioSettings
所述的LPCM格式,但随后将
audioTrack.formatDescriptions[0]
sourceFormatHint
提供给
AVAssetWriterInput

这是一个问题,因为音频曲目格式描述不是LPCM,而是压缩格式,如
kaudioformmpeg4aac

只需给出提示,我认为这是为了传递压缩格式

此外,
输入音频设置
中的LPCM未指定-为什么不直接通过
音频设置

总之,请尝试以下方法:

let audioInput = AVAssetWriterInput(mediaType: AVMediaType.audio, outputSettings: audioSettings)

p、 在运行之前不要忘记删除输出文件,
AVAssetWriter
似乎不会覆盖现有文件

谢谢您的回答和解释!那很有魅力!