英文:
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
不同,它的生命周期由其 startWriting
和 finishWriting
方法明显表示,AVAssetReader
只有 startReading
方法,没有 finishReading
方法,这样很容易管理其作用域。API 设计很难。你应该将你的 AVAssetReader
和 AVAssetReaderOutput
捆绑在一起,放在一个类或结构体中,并附上一个注释,警告不要重构对象,以避免将来出现这种情况。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论