我有一个AVMutableComposition
,它只包含要导出到.wav音频文件的音频。
我发现导出音频的最简单的解决方案是使用AVAssetExportSession
,如下面这个简化的示例所示:
let composition = AVMutableComposition()
// add tracks...
let exportSession = AVAssetExportSession(asset: composition,
presetName: AVAssetExportPresetAppleM4A)!
exportSession.outputFileType = .m4a
exportSession.outputURL = someOutUrl
exportSession.exportAsynchronously {
// done
}
但它只适用于.m4a
这个post提到,为了导出到其他格式,我们必须使用AVAssetReader
和AVAssetWriter
,但遗憾的是,它没有进一步详细介绍。
我试着去实现它,但却被困在了这个过程中。
这就是我到目前为止(再次简化)的内容:
let composition = AVMutableComposition()
let outputSettings: [String : Any] = [
AVFormatIDKey: kAudioFormatLinearPCM,
AVLinearPCMIsBigEndianKey: false,
AVLinearPCMIsFloatKey: false,
AVLinearPCMBitDepthKey: 32,
AVLinearPCMIsNonInterleaved: false,
AVSampleRateKey: 44100.0,
AVChannelLayoutKey: NSData(),
]
let assetWriter = try! AVAssetWriter(outputURL: someOutUrl, fileType: .wav)
let input = AVAssetWriterInput(mediaType: .audio, outputSettings: outputSettings)
assetWriter.add(input)
assetWriter.startWriting()
assetWriter.startSession(atSourceTime: CMTime.zero)
input.requestMediaDataWhenReady(on: .main) {
// as I understand, I need to bring in data from my
// AVMutableComposition here...
let sampleBuffer: CMSampleBuffer = ???
input.append(sampleBuffer)
}
assetWriter.finishWriting {
// done
}
归根结底是我的问题:
您能提供一个将音频从AVMutableComposition导出到wav文件的工作示例吗?
发布于 2021-10-28 21:31:10
经过进一步的研究,我想出了以下的解决方案。
缺少的是AVAssetReader的用法。
(简化代码)
// composition
let composition = AVMutableComposition()
// add stuff to composition
// reader
guard let assetReader = try? AVAssetReader(asset: composition) else { return }
assetReader.timeRange = CMTimeRange(start: .zero, duration: CMTime(value: composition.duration.value, timescale: composition.duration.timescale))
let assetReaderAudioMixOutput = AVAssetReaderAudioMixOutput(audioTracks: composition.tracks(withMediaType: .audio), audioSettings: nil)
assetReader.add(assetReaderAudioMixOutput)
guard assetReader.startReading() else { return }
// writer
let outputSettings: [String : Any] = [
AVFormatIDKey: kAudioFormatLinearPCM,
AVLinearPCMIsBigEndianKey: false,
AVLinearPCMIsFloatKey: false,
AVLinearPCMBitDepthKey: 32,
AVLinearPCMIsNonInterleaved: false,
AVSampleRateKey: 44100.0,
AVChannelLayoutKey: NSData(),
]
guard let assetWriter = try? AVAssetWriter(outputURL: someOutUrl, fileType: .wav) else { return }
let writerInput = AVAssetWriterInput(mediaType: .audio, outputSettings: outputSettings)
assetWriter.add(writerInput)
guard assetWriter.startWriting() else { return }
assetWriter.startSession(atSourceTime: CMTime.zero)
let queue = DispatchQueue(label: "my.queue.id")
writerInput.requestMediaDataWhenReady(on: queue) {
// capture assetReader in my block to prevent it being released
let readerOutput = assetReader.outputs.first!
while writerInput.isReadyForMoreMediaData {
if let nextSampleBuffer = readerOutput.copyNextSampleBuffer() {
writerInput.append(nextSampleBuffer)
} else {
writerInput.markAsFinished()
assetWriter.endSession(atSourceTime: composition.duration)
assetWriter.finishWriting() {
DispatchQueue.main.async {
// done, call my completion
}
}
break;
}
}
}
发布于 2021-10-11 23:18:26
正如您提到的,您正在成功地创建.m4a,为什么不将.m4a文件转换为.wav文件,只需在代码中添加一行代码
我只需将文件的扩展名更改为.wav,并删除.m4a文件,就可以工作了。
func getDirectory() -> URL {
let path = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentDirectory = path[0]
return documentDirectory
}
let date = Date().timeIntervalSince1970
fileName = getDirectory().appendingPathComponent("\(date).m4a")
wavFileName = getDirectory().appendingPathComponent("\(date).wav")
try! FileManager.default.copyItem(at: fileName, to: wavFileName)
try! FileManager.default.removeItem(at: fileName)
我甚至播放了.wav文件,它运行得很好。
audioPlayer = try! AVAudioPlayer(contentsOf: wavFileName)
audioPlayer.play()
请参阅上面的示例,此扩展替换是否会导致应用程序中的任何负载或时间?
https://stackoverflow.com/questions/69531635
复制相似问题