AVFoundation转换MP3到AAC音频时发生错误。

huangapple go评论56阅读模式
英文:

Error convertig mp3 to aac audio with AVFoundation

问题

抱歉,但由于您的请求,我只会提供代码的翻译部分,不会提供其他内容或回答问题。以下是您提供的代码的翻译:

我正在尝试将mp3音频转换为aac音频,但我遇到了以下错误:

```Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '*** -[AVAssetReaderTrackOutput copyNextSampleBuffer] cannot copy next sample buffer before adding this output to an instance of AVAssetReader (using -addOutput:) and calling -startReading on that asset reader'```

当使用以下代码时:

```swift
let asset = AVAsset(url: tmpURL)

let assetReader = try AVAssetReader(asset: asset)

if let audioTrack = try await asset.loadTracks(withMediaType: .audio).first {
    let assetReaderOutput = AVAssetReaderTrackOutput(track: audioTrack,
                                                     outputSettings: [
                                                        AVFormatIDKey: Int(kAudioFormatLinearPCM)
                                                     ])
    
    assetReader.add(assetReaderOutput)
    assetReader.startReading()
    
    let assetWriter = try AVAssetWriter(outputURL: outputURL, fileType: .m4a)
    let outputSettings: [String: Any] = [
        AVFormatIDKey: kAudioFormatMPEG4AAC,
        AVSampleRateKey: 44100,
        AVEncoderBitRateKey: 256000,
        AVNumberOfChannelsKey: 2
    ]
    let assetWriterInput = AVAssetWriterInput(mediaType: AVMediaType.audio,
                                              outputSettings: outputSettings)
    assetWriter.add(assetWriterInput)
    
    assetWriter.startWriting()
    assetWriter.startSession(atSourceTime: .zero)
    
    let processingQueue = DispatchQueue(label: "processingQueue")
    
    assetWriterInput.requestMediaDataWhenReady(on: processingQueue) {
        while assetWriterInput isReadyForMoreMediaData {
            guard let nextBuffer = assetReaderOutput.copyNextSampleBuffer() else {
                assetWriterInput.markAsFinished()
                assetWriter.finishWriting(completionHandler: {
                    if assetWriter.status == .completed {
                        print("文件成功转换")
                    } else {
                        print("文件转换失败,错误信息:\(assetWriter.error?.localizedDescription ?? \"未知错误\")")
                    }
                })
                break
            }
            assetWriterInput.append(nextBuffer)
        }
    }
}

希望这有助于您解决问题。如果您有任何其他问题,请随时提出。

英文:

I am trying to convert a mp3-audio to aac-audio and I am getting the error

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '*** -[AVAssetReaderTrackOutput copyNextSampleBuffer] cannot copy next sample buffer before adding this output to an instance of AVAssetReader (using -addOutput:) and calling -startReading on that asset reader'

when using this code:

let asset = AVAsset(url: tmpURL)
			
let assetReader = try AVAssetReader(asset: asset)
			
if let audioTrack = try await asset.loadTracks(withMediaType: .audio).first {
	let assetReaderOutput = AVAssetReaderTrackOutput(track: audioTrack,
													 outputSettings: [
														AVFormatIDKey: Int(kAudioFormatLinearPCM)
													 ])
				
	assetReader.add(assetReaderOutput)
	assetReader.startReading()
				
	let assetWriter = try AVAssetWriter(outputURL: outputURL, fileType: .m4a)
	let outputSettings: [String: Any] = [
		AVFormatIDKey: kAudioFormatMPEG4AAC,
		AVSampleRateKey: 44100,
		AVEncoderBitRateKey: 256000,
		AVNumberOfChannelsKey: 2
	]
	let assetWriterInput = AVAssetWriterInput(mediaType: AVMediaType.audio,
														  outputSettings: outputSettings)
	assetWriter.add(assetWriterInput)
				
	assetWriter.startWriting()
	assetWriter.startSession(atSourceTime: .zero)
				
				
	let processingQueue = DispatchQueue(label: "processingQueue")
				
	assetWriterInput.requestMediaDataWhenReady(on: processingQueue) {
		while assetWriterInput.isReadyForMoreMediaData {
			guard let nextBuffer = assetReaderOutput.copyNextSampleBuffer() else {
				assetWriterInput.markAsFinished()
				assetWriter.finishWriting(completionHandler: {
					if assetWriter.status == .completed {
						print("File converted successfully")
					} else {
						print("File conversion failed with error: \(assetWriter.error?.localizedDescription ?? "unknown error")")
					}
				})
				break
			}
			assetWriterInput.append(nextBuffer)
		}
	}
}

I don't understand that, because I am actually adding the output to a reader and then I start assetReader.startReading(). What am I doing wrong?

答案1

得分: 1

你的 assetReader 超出了作用域。我猜想 AVAssetReaderOutput 没有指向其 AVAssetReader 的后向指针。所以如果你在追加缓冲后加一个“结构性打印”,你的代码就能工作了,因为这样扩展了 AVAssetReader 的作用域:

assetWriterInput.append(nextBuffer)
print("structural print \(assetReader)")

AVAssetWriter 不同,它的生命周期由其 startWritingfinishWriting 方法明显表示,AVAssetReader 只有 startReading 方法,没有 finishReading 方法,这样很容易管理其作用域。API 设计很难。你应该将你的 AVAssetReaderAVAssetReaderOutput 捆绑在一起,放在一个类或结构体中,并附上一个注释,警告不要重构对象,以避免将来出现这种情况。

英文:

Your assetReader is going out of scope. I guess the AVAssetReaderOutput has no back pointer to its AVAssetReader. So your code works if you add a "structural print" after appending the buffer, because this extends the AVAssetReader scope:

assetWriterInput.append(nextBuffer)
print("structural print \(assetReader)")

Unlike AVAssetWriter, whose lifetime is made obvious by its startWriting and finishWriting methods, AVAssetReader has a startReading but no finishReading method, making it easy to mismanage its scope. API design is hard. You should probably bundle your AVAssetReader and AVAssetReaderOutput together in a class or struct along with a comment warning against refactoring the object to avoid this situation in the future.

huangapple
  • 本文由 发表于 2023年2月27日 16:54:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/75578403.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定