ios - 使用 AVAssetExportSession 合并音频
问题描述
我想合并两个音频文件而没有太多的开销时间。下面的代码成功地合并了音频,但花费的时间太长(超过 30 秒超过几分钟的音频),我想知道是否有任何方法可以加快这个过程。我在几个地方阅读过AVAssetExportPresetPassthrough
,但我似乎无法让该预设适用于任何文件类型。我能够开始工作的唯一设置是使用AVAssetExportPresetAppleM4A
和导出为.m4a
创建 AVAssetExportSession 的代码
if (audioHasBeenRecorded) {
// Merge recordings
let composition = AVMutableComposition()
let compositionAudioTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid)
guard let start = recorder.timeStart else { return }
compositionAudioTrack?.insert(originalRecording: FileManagerHelper.recordingLocalURL(secondRecording: false), insertedRecording: FileManagerHelper.recordingLocalURL(secondRecording: true), startTime: CMTime(seconds: start, preferredTimescale: 1000000))
if let assetExport = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A) {
print(assetExport.supportedFileTypes)
assetExport.outputFileType = AVFileType.m4a
assetExport.outputURL = FileManagerHelper.recordingLocalURL(secondRecording: false)
do { // Delete old audio
try FileManager.default.removeItem(at: FileManagerHelper.recordingLocalURL(secondRecording: false))
try FileManager.default.removeItem(at: FileManagerHelper.recordingLocalURL(secondRecording: true))
} catch { log(error.localizedDescription, msgType: .error) }
assetExport.exportAsynchronously(completionHandler: {
if let error = assetExport.error {
log(error, msgType: .error)
} else {
log("Successfully merged recordings!", msgType: .error)
self.idea.numberOfPoints = self.audioVisualizer.count
self.idea.save()
self.setupPlayer() // Prepare to play the recorded audio file
self.seekTo(TimeInterval((recorder.timeStart ?? 0) + (recorder.timeEnd ?? 0)))
DispatchQueue.main.async { [ weak self ] in
guard let self = self else { return }
self.audioVisualizer.visualize(self.idea)
}
}
})
}
}
插入代码:
extension AVMutableCompositionTrack {
func insert(originalRecording: URL, insertedRecording: URL, startTime: CMTime) {
let originalAsset = AVURLAsset(url: originalRecording)
let insertedAsset = AVURLAsset(url: insertedRecording)
let range1 = CMTimeRangeMake(start: CMTime.zero, duration: startTime)
let range2 = CMTimeRangeMake(start: CMTime.zero, duration: insertedAsset.duration)
let range3 = CMTimeRangeMake(start: startTime + insertedAsset.duration, duration: originalAsset.duration - startTime)
if let originalTrack = originalAsset.tracks(withMediaType: AVMediaType.audio).first,
let insertedTrack = insertedAsset.tracks(withMediaType: AVMediaType.audio).first {
try? insertTimeRange(range1, of: originalTrack, at: CMTime.zero)
try? insertTimeRange(range2, of: insertedTrack, at: startTime)
try? insertTimeRange(range3, of: originalTrack, at: startTime + insertedAsset.duration)
}
}
}
解决方案
推荐阅读
- node.js - 如果用户使用 Passport OAuth2 (Swoop) 和 Node/Express 输入无效电子邮件,我该如何重定向?
- ruby-on-rails - 无法写入未知属性“user_id”
- bouncycastle - 如何通过使用 BouncyCastle 的 client-maven-plugin 构建原生映像
- android - Kotlin:CountDownTimer onTick 被 onClick 中断
- javascript - 从http api获取json数据并只显示一个值?
- continuous-integration - 如何在 YAML 中正确引用 JSON(带变量)
- c# - 使用替换循环正则表达式
- r - 使用 tidyr 对分组数据进行长到宽转换
- spring-data-jpa - 在 Spring Data Controller 中使用 Spring Data 样式 HAL
- python - PyCharm 并不总是在新数字中绘图