Swift 使用 AVWriter/AVReader 从 .mp4 视频写入零字节文件中提取 .wav 音频的代码
Swift code to use AVWriter/AVReader to extract .wav audio from .mp4 video writing zero byte file
我已经阅读了文档和此处的所有帖子,我已经走到这一步了。
下面的函数应该使用一个 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,而是压缩格式,例如 kAudioFormatMPEG4AAC
。
只是提示,我认为它无论如何都是为了通过压缩格式。
此外,inputAudioSettings
中的 LPCM 未指定 - 为什么不直接通过 audioSettings
?
总而言之,试试这个:
let audioInput = AVAssetWriterInput(mediaType: AVMediaType.audio, outputSettings: audioSettings)
p.s。不要忘记在运行之前删除输出文件,AVAssetWriter
似乎不会覆盖现有文件
我已经阅读了文档和此处的所有帖子,我已经走到这一步了。
下面的函数应该使用一个 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,而是压缩格式,例如 kAudioFormatMPEG4AAC
。
只是提示,我认为它无论如何都是为了通过压缩格式。
此外,inputAudioSettings
中的 LPCM 未指定 - 为什么不直接通过 audioSettings
?
总而言之,试试这个:
let audioInput = AVAssetWriterInput(mediaType: AVMediaType.audio, outputSettings: audioSettings)
p.s。不要忘记在运行之前删除输出文件,AVAssetWriter
似乎不会覆盖现有文件