Attempting to merge multiple videos with AVMutableComposition, the tracks are gathering correctly in the avassettrack. However, they simply overlap and only the second video is displayed. Also the length of the output is whatever the second video length is.
here is the merge func:
public func mergeCapturedVideos(completion: @escaping (_ completedMovieURL: URL) -> Void) {
let mixComposition = AVMutableComposition()
let movieAssets: [AVAsset] = self.capturedMovieURLs.map({ AVAsset(url: $0) })
var insertTime: CMTime = CMTime.zero
if movieAssets.count == self.capturedMovieURLs.count {
for movieAsset in movieAssets {
do {
if let compositionVideoTrack: AVMutableCompositionTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) {
let tracks: [AVAssetTrack] = movieAsset.tracks(withMediaType: .video)
let assetTrack: AVAssetTrack = tracks[0] as AVAssetTrack
try compositionVideoTrack.insertTimeRange(CMTimeRange(start: .zero, duration: movieAsset.duration), of: assetTrack, at: insertTime)
print("1 \(insertTime)")
insertTime = CMTimeAdd(insertTime, movieAsset.duration)
print("2 \(insertTime)")
}
} catch let error as NSError {
print("Error merging movies: \(error)")
}
print("MIX: \(mixComposition)")
}
let completeMovieURL: URL = self.capturedMovieURLs[0]
if let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHEVC1920x1080WithAlpha) {
exporter.outputURL = completeMovieURL
exporter.outputFileType = .mp4
exporter.exportAsynchronously {
if let url = exporter.outputURL {
completion(url)
} else if let error = exporter.error {
print("Merge exporter error: \(error)")
}
}
}
}
}
This is what the "MIX: " print statement is outputting:
MIX: <AVMutableComposition: 0x2815670a0 tracks = (
"<AVMutableCompositionTrack: 0x281567ea0 trackID = 1, mediaType = vide, editCount = 1>",
"<AVMutableCompositionTrack: 0x281567da0 trackID = 2, mediaType = vide, editCount = 2>"
)>
As you can see, the tracks are being added properly, so it must be a issue with the insertTime var. But that is also printing the expected output:
1 CMTime(value: 0, timescale: 1, flags: __C.CMTimeFlags(rawValue: 1), epoch: 0)
2 CMTime(value: 2121, timescale: 600, flags: __C.CMTimeFlags(rawValue: 1), epoch: 0)
1 CMTime(value: 2121, timescale: 600, flags: __C.CMTimeFlags(rawValue: 1), epoch: 0)
2 CMTime(value: 3560, timescale: 600, flags: __C.CMTimeFlags(rawValue: 1), epoch: 0)
As shown, the insertTime var is properly adding the duration of each track on every loop.
This is leaving me very puzzled, why is the output not a singular movie with each video?