Skip to content

Instantly share code, notes, and snippets.

@giusecapo
Last active June 30, 2017 10:43
Show Gist options
  • Save giusecapo/d8936e2e34e73109310163a2c9145552 to your computer and use it in GitHub Desktop.
Save giusecapo/d8936e2e34e73109310163a2c9145552 to your computer and use it in GitHub Desktop.
Merge multiple video clips
// Mark: - Merge Videos and export Finalized Video
private func merge(clips: [Clip]){
let composition = AVMutableComposition()
let trackID = kCMPersistentTrackID_Invalid
let videoTrack = composition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: trackID)
//let audioTrack = composition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: trackID)
var totalTime = kCMTimeZero
for clip in clips {
let asset = AVAsset(url: clip.url)
let range = CMTimeRangeMake(kCMTimeZero, asset.duration)
let assetTrack = asset.tracks(withMediaType: AVMediaTypeVideo)[0]
// Rotate portrait 90°
videoTrack.preferredTransform = CGAffineTransform(rotationAngle: .pi/2)
do {
try videoTrack.insertTimeRange(range, of: assetTrack, at: totalTime)
} catch{
print("error: \(error)")
}
totalTime = CMTimeAdd(totalTime, asset.duration)
}
exportMergedVideo(composition: composition, clips: clips)
}
private func exportMergedVideo(composition: AVMutableComposition, clips: [Clip]){
let manager = FileManager.default
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let outputURL = paths[0].appendingPathComponent("export.mov")
//Remove existing file
_ = try? manager.removeItem(at: outputURL)
guard let exportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality) else {return}
exportSession.outputURL = outputURL
exportSession.outputFileType = AVFileTypeMPEG4
self.outputURL = outputURL
exportSession.exportAsynchronously(completionHandler: {
switch exportSession.status {
case .completed:
//self.prepareForPublish()
self.deleteClips(clips: clips)
// To-do: - Save video into Library
case .failed:
print("failed \(String(describing: exportSession.error))")
case .cancelled:
print("cancelled \(String(describing: exportSession.error))")
default: break
}
})
}
// Delete single clips from disk
func deleteClips(clips: [Clip]){
for clip in clips {
clip.deleteFromDisk()
}
print("\(clips.count) clips deleted from disk!")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment