我有几个音频剪辑,我用AVAudioRecorder录制了一段视频。使用AVMutableComposition,我希望在录制音频时将音频资产与视频合并。例如,视频是1分钟长,我录制了3个音频剪辑在5-10秒,20-25秒,和30-35秒。音频剪辑应该在这些特定的时间框架内与视频合并。当最后的视频播放时,音频将在这些时间帧上播放。
模型:
class AudioModel {
var audioUrl: URL?
var startTime: Double?
var endTime: Double?
}混合:
let mixComposition = AVMutableComposition()
guard let videoCompositionTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else { return }
guard let audioFromVideoCompositionTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else { return }
guard let audioModelCompositionTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else { return }
let videoAsset = AVURLAsset(url: videoURL)
guard let videoTrack = videoAsset.tracks(withMediaType: .video).first else { return }
for audioModel in audioModels {
let audioAsset = AVURLAsset(url: audioModel.url!)
let startTime = CMTime(seconds: audioModel.startTime!, preferredTimescale: 1000)
do {
try videoCompositionTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: videoAsset.duration), of: videoTrack, at: .zero)
if let audioTrackFromAudioModel = audioAsset.tracks(withMediaType: .audio).first {
try audioModelCompositionTrack.insertTimeRange(CMTimeRangeMake(start: startTime, duration: audioAsset.duration),
of: audioTrackFromAudioModel, at: .zero)
}
if let audioFromVideoTrack = videoAsset.tracks(withMediaType: .audio).first {
try audioFromVideoCompositionTrack.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: videoAsset.duration),
of: audioFromVideoTrack, at: .zero)
}
} catch {
}
}
let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)
// ... I know what to do from here发布于 2022-03-20 12:42:46
您的方法是正确的,但是您混淆了用于insertTimeRange的两个参数,并且多次从视频轨道中添加视频和音频。
insertTimeRange中的第一个参数是指原始音频资产中的timeRange,而不是组合;因此,假设对于要添加整个剪辑的每个音频剪辑,时间范围应该总是从.zero开始,而不是在startTime。at:参数不应该是.zero,而应该是"startTime“--在要添加音频的组合中的时间。
关于您的视频轨道和audioFromVideoTrack,我不会将它们作为循环的一部分添加,而是在循环之前添加它们。否则,您将多次添加它们(每个音频项一次),而不仅仅是一次,这可能导致不必要的行为或导出会话完全失败。
我编辑了您的代码,但没有进行实际测试,所以请稍加考虑。
guard let videoCompositionTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else { return }
guard let audioFromVideoCompositionTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else { return }
guard let audioModelCompositionTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else { return }
let videoAsset = AVURLAsset(url: videoURL)
guard let videoTrack = videoAsset.tracks(withMediaType: .video).first else { return }
do {
try videoCompositionTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: videoAsset.duration), of: videoTrack, at: .zero)
if let audioFromVideoTrack = videoAsset.tracks(withMediaType: .audio).first {
try audioFromVideoCompositionTrack.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: videoAsset.duration), of: audioFromVideoTrack, at: .zero)
}
} catch {
}
for audioModel in audioModels {
let audioAsset = AVURLAsset(url: audioModel.url!)
let startTime = CMTime(seconds: audioModel.startTime!, preferredTimescale: 1000)
do {
if let audioTrackFromAudioModel = audioAsset.tracks(withMediaType: .audio).first {
try audioModelCompositionTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: audioAsset.duration), of: audioTrackFromAudioModel, at: startTime)
}
} catch {
}
}
let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)
// ... I know what to do from herehttps://stackoverflow.com/questions/71540228
复制相似问题