Я пытаюсь объединить несколько видео с помощью AVFoundation. Он отлично работает, когда я добавляю только два видео. Но когда я пытаюсь добавить 3 видео, вторая видеодорожка пуста, но общая продолжительность экспортируемых видео правильная.
Вот мой пример кода:
Код для добавления видео:
func addVideo(videoAsset: AVAsset, isLast: Bool = false)
{
// Add video track
guard let videoTrack = self.mixComposition.addMutableTrack(
withMediaType: .video,
preferredTrackID: Int32(kCMPersistentTrackID_Invalid))
else { return }
do
{
try videoTrack.insertTimeRange(
CMTimeRangeMake(start: .zero, duration: videoAsset.duration),
of: videoAsset.tracks(withMediaType: .video)[0],
at: totalVideoTrackDuration)
// Add instruction for this track
// video helper fixes the video orientation
let instruction = VideoHelper.videoCompositionInstruction(videoTrack, asset: videoAsset)
if !isLast
{
// hide this clip when its done rendering
instruction.setOpacity(0.0, at: videoAsset.duration)
}
// add to layer instruction
self.instructions.append(instruction)
// get the sum of all added track durations
self.totalVideoTrackDuration = CMTimeAdd(self.totalVideoTrackDuration, videoAsset.duration)
}
catch
{
print("Failed to load track")
return
}
}
Вот код для экспорта видео:
func export()
{
// 6
let mainInstruction = AVMutableVideoCompositionInstruction()
// set time range
mainInstruction.timeRange = CMTimeRangeMake(
start: .zero,
duration: self.totalVideoTrackDuration
)
mainInstruction.layerInstructions = self.instructions
let mainComposition = AVMutableVideoComposition()
mainComposition.instructions = [mainInstruction]
mainComposition.frameDuration = CMTimeMake(value: 1, timescale: self.timeScale)
mainComposition.renderSize = self.videoSize
guard let documentDirectory = FileManager.default.urls(
for: .documentDirectory,
in: .userDomainMask).first
else { return }
// file name
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .short
let date = Date().format(format: "mm-dd-yy-HH-mm-ss")!
let url = documentDirectory.appendingPathComponent("mergeVideo-\(date).mov")
guard let exporter = AVAssetExportSession(
asset: self.mixComposition,
presetName: AVAssetExportPresetHighestQuality)
else { return }
exporter.outputURL = url
exporter.outputFileType = AVFileType.mov
exporter.shouldOptimizeForNetworkUse = true
exporter.videoComposition = mainComposition
exporter.exportAsynchronously {
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.
creationRequestForAssetFromVideo(
atFileURL: exporter.outputURL!)
}){
saved, error in
if saved
{
print("Export successful")
}
else
{
print("video erro: \(error)")
}
}
}
}
Вот как я вызываю функцию addVideo
:
// 4-second video
self.addVideo(videoAsset: asset1)
// 3-second video
self.addVideo(videoAsset: asset2)
// 4-second video
self.addVideo(videoAsset: asset3, isLast: true)
// export
self.export()
// the total duration of the exported video is 11 seconds. But the middle part, is blank.