1

我正在尝试获取本地 m4a 文件并压缩/向下采样该文件(为了制作更小的文件)。

现在,当我尝试附加样本缓冲区时,我遇到了错误。

错误描述:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[AVAssetWriterInput appendSampleBuffer:] Cannot append sample buffer: Input buffer must be in an uncompressed format when outputSettings is not nil'

我尝试将原始音频文件压缩为相同文件格式但比特率较低的代码:

@objc func nextTapped() {
        let audioURL = RecordWhistleViewController.getWhistleURL()
        
        var asset = AVAsset.init(url: audioURL)
        let exportPath = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("out.m4a").path
        print("export PATH IS \(exportPath)")
        
        let exportURL = URL(fileURLWithPath: exportPath)
        
        var readerError: Error? = nil
        var reader: AVAssetReader? = nil
        do {
            reader = try AVAssetReader(asset: asset)
        } catch {
            print("error in reader \(error)")
        }
        
        let track = asset.tracks(withMediaType: .audio)[0]
        let readerOutput = AVAssetReaderTrackOutput(track: track, outputSettings: nil)
        reader?.add(readerOutput)
        
        var writerError: Error? = nil
        var writer: AVAssetWriter? = nil
        do {
            writer = try AVAssetWriter(outputURL: exportURL, fileType: .m4a)
        } catch {
            print("ERROR IN writer \(error)")
        }
        
        var channelLayout = AudioChannelLayout()
        memset(&channelLayout, 0, MemoryLayout<AudioChannelLayout>.size)
        channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo
        
        let outputSettings = [
            AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
            AVSampleRateKey: 12000,
            AVNumberOfChannelsKey: 2,
            AVEncoderBitRateKey: 128000,
            AVChannelLayoutKey: Data(bytes: &channelLayout, count: MemoryLayout<AudioChannelLayout>.size)
            
        ] as [String : Any]
        
        let writerInput = AVAssetWriterInput(mediaType: .audio, outputSettings: outputSettings as? [String: Any])
        writerInput.expectsMediaDataInRealTime = false
        writer?.add(writerInput)
        
        writer?.startWriting()
        writer?.startSession(atSourceTime: .zero)
        
        reader?.startReading()
        let mediaInputQueue = DispatchQueue(label: "mediaInputQueue")
        writerInput.requestMediaDataWhenReady(on: mediaInputQueue) {
            print("Asset writer ready: \(writerInput.isReadyForMoreMediaData)")
            while writerInput.isReadyForMoreMediaData {
                var nextBuffer: CMSampleBuffer?
                nextBuffer = readerOutput.copyNextSampleBuffer()
                if nextBuffer != nil {
                    if let nextBuffer = nextBuffer {
                        print("adding buffer")
                        writerInput.append(nextBuffer)
                    }
                } else {
                    writerInput.markAsFinished()
                    reader?.cancelReading()
                    writer?.finishWriting {
                        print("Asset writer finished writing")
                    }
                    break
                }
            }
        }
        
    }

原始音频有设置:

let settings = [
            AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
            AVSampleRateKey: 12000,
            AVNumberOfChannelsKey: 1,
            AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
        ]

原始文件的 URL 代码:

class func getDocumentsDirectory() -> URL {
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        let documentsDirectory = paths[0]
        return documentsDirectory
    }

编辑

这是错误的完整描述:

assetsWriter_finishBuildingAudioTrackWithSourceFormatDescription 在 /Library/Caches/com.apple.xbs/Sources/EmbeddedCoreMedia_Sim/EmbeddedCoreMedia-2765.6/Prototypes/Export/FigAssetWriter.c:636 处发出 err=-12413 (kFigAssetWriterError_InappropriateSourceFormat) (AssetWriter 只能压缩 LPCM 音频)

由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“*** -[AVAssetWriterInput appendSampleBuffer:] 无法附加样本缓冲区:当 outputSettings 不为 nil 时,输入缓冲区必须为未压缩格式”

4

1 回答 1

0

错误表明资产编写器需要未压缩的样本缓冲区,但AVAssetReaderTrackOutput头文件显示:

outputSettings 的 nil 值将输出配置为以指定轨道存储的原始格式提供样本。

您的文件是一个.m4a文件,因此样本可能会被压缩为 AAC。

kAudioFormatLinearPCM要获得未压缩的线性 PCM,请作为AVFormatIDKeyin传递outputSettings

let readerOutputSettings = [
    AVFormatIDKey: kAudioFormatLinearPCM
]

let readerOutput = AVAssetReaderTrackOutput(track: track, outputSettings: readerOutputSettings)

请注意,您正在对文件进行解码和重新编码或转码。

于 2021-07-02T04:42:00.870 回答