Swift:将视频与AVAssetExportSession()背靠背合并
我有一个视频记录数组存储为AVURLSATE,我想将视频合并成一个剪辑,以便它们在视频之间没有时间进行背靠背播放。下面是我希望做的,但它只显示了第一个视频。注意:我希望视频能够背靠背播放,并且每个视频之间没有空格。例如,如果在手机未录制时,recording1和recording2之间存在实时性,则输出不应显示此信息 谢谢你的帮助Swift:将视频与AVAssetExportSession()背靠背合并,swift,xcode,video-processing,avassetwriter,avassetexportsession,Swift,Xcode,Video Processing,Avassetwriter,Avassetexportsession,我有一个视频记录数组存储为AVURLSATE,我想将视频合并成一个剪辑,以便它们在视频之间没有时间进行背靠背播放。下面是我希望做的,但它只显示了第一个视频。注意:我希望视频能够背靠背播放,并且每个视频之间没有空格。例如,如果在手机未录制时,recording1和recording2之间存在实时性,则输出不应显示此信息 谢谢你的帮助 func mergeVideos(handler: @escaping (_ asset: AVAssetExportSession)->()) { l
func mergeVideos(handler: @escaping (_ asset: AVAssetExportSession)->()) {
let mixComposition = AVMutableComposition()
var videoTime = CMTime.zero
for video in self.recordings {
let tracks = video.tracks(withMediaType: .video)
let videoTrack = tracks[0]
let videoTimeRange = CMTimeRangeMake(start: .zero, duration: video.duration)
guard let compositionVideoTrack: AVMutableCompositionTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else { return }
do {
try compositionVideoTrack.insertTimeRange(videoTimeRange, of: videoTrack, at: videoTime)
videoTime = CMTimeAdd(videoTime, video.duration)
} catch {
print("An error occurred")
return
}
}
guard let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .short
let date = dateFormatter.string(from: Date())
let url = documentDirectory.appendingPathComponent("mergeVideo-\(date).mov")
guard let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality) else { return }
exporter.outputURL = url
exporter.outputFileType = AVFileType.mov
exporter.shouldOptimizeForNetworkUse = true
handler(exporter)
}
解决方案是将AVMutableCompositionTrack移到for循环之外。下面是我更新的合并视频(带音频)的功能。希望这对别人有帮助
var recordings = [AVURLAsset]()
func mergeVideos(handler: @escaping (_ asset: AVAssetExportSession)->()) {
let videoComposition = AVMutableComposition()
var lastTime: CMTime = .zero
guard let videoCompositionTrack = videoComposition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else { return }
guard let audioCompositionTrack = videoComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else { return }
for video in self.recordings {
//add audio/video
do {
try videoCompositionTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: video.duration), of: video.tracks(withMediaType: .video)[0], at: lastTime)
try audioCompositionTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: video.duration), of: video.tracks(withMediaType: .audio)[0], at: lastTime)
} catch {
print("Failed to insert audio or video track")
return
}
//update time
lastTime = CMTimeAdd(lastTime, video.duration)
}
//create url
guard let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .short
let date = dateFormatter.string(from: Date())
let url = documentDirectory.appendingPathComponent("mergeVideo-\(date).mov")
//export
guard let exporter = AVAssetExportSession(asset: videoComposition, presetName: AVAssetExportPresetHighestQuality) else { return }
exporter.outputURL = url
exporter.outputFileType = AVFileType.mp4
exporter.shouldOptimizeForNetworkUse = true
handler(exporter)
}