Skip to content

Instantly share code, notes, and snippets.

@duzvik
Last active December 13, 2016 11:30
Show Gist options
  • Save duzvik/853c0564dde684c1263d0f2a78dfde7e to your computer and use it in GitHub Desktop.
Save duzvik/853c0564dde684c1263d0f2a78dfde7e to your computer and use it in GitHub Desktop.
if let asset = firstAsset {
// 2 - Create AVMutableComposition object. This object will hold your AVMutableCompositionTrack instances.
let cmp = AVMutableComposition()
// 3 - Video track
let track = cmp.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: Int32(kCMPersistentTrackID_Invalid))
guard let sourceVideoTrack = asset.tracks(withMediaType: AVMediaTypeVideo).first else {return}
try! track.insertTimeRange(CMTimeRangeMake(kCMTimeZero, asset.duration), of: sourceVideoTrack, at: kCMTimeZero)
// 3.1 - Create AVMutableVideoCompositionInstruction
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, asset.duration)
// 3.2 - Create an AVMutableVideoCompositionLayerInstruction for the video track and fix the orientation.
let videolayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: track)
let videoAssetTrack = asset.tracks(withMediaType: AVMediaTypeVideo).first
var videoAssetOrientation: UIImageOrientation
var isVideoAssetPortrait = false
let videoTransform = videoAssetTrack!.preferredTransform
if (videoTransform.a == 0 && videoTransform.b == 1.0 && videoTransform.c == -1.0 && videoTransform.d == 0) {
videoAssetOrientation = .right
isVideoAssetPortrait = true
}
if (videoTransform.a == 0 && videoTransform.b == -1.0 && videoTransform.c == 1.0 && videoTransform.d == 0) {
videoAssetOrientation = .left
isVideoAssetPortrait = true
}
if (videoTransform.a == 1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == 1.0) {
videoAssetOrientation = .up
}
if (videoTransform.a == -1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == -1.0) {
videoAssetOrientation = .down
}
videolayerInstruction.setTransform((videoAssetTrack!.preferredTransform), at: kCMTimeZero)
videolayerInstruction.setOpacity(0.0, at: asset.duration)
// 3.3 - Add instructions
instruction.layerInstructions = [videolayerInstruction]
let animComp = AVMutableVideoComposition()
var naturalSize: CGSize
if isVideoAssetPortrait {
naturalSize = CGSize(width: track.naturalSize.height, height: track.naturalSize.width)
} else {
naturalSize = track.naturalSize
}
animComp.renderSize = naturalSize
animComp.instructions = [instruction]
animComp.frameDuration = CMTimeMake(1, 30);
let parentLayer = CALayer()
let videoLayer = CALayer()
let aLayer = CALayer()
aLayer.frame = CGRect(x: 100, y: 100, width: 100, height: 100)
aLayer.bounds = CGRect(x: 0, y: 0, width: 100, height: 100)
aLayer.contents = UIImage(named: "mask.png")?.cgImage
aLayer.opacity = 0.5
aLayer.backgroundColor = UIColor.red.cgColor
parentLayer.frame = CGRect(x: 0, y: 0, width: naturalSize.width, height: naturalSize.height)
videoLayer.frame = CGRect(x: 0, y: 0, width: naturalSize.width, height: naturalSize.height)
parentLayer.backgroundColor = UIColor.blue.cgColor
videoLayer.backgroundColor = UIColor.green.cgColor
parentLayer.addSublayer(videoLayer)
parentLayer.addSublayer(aLayer)
animComp.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer)
// 4 - Get path
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .short
let date = dateFormatter.string(from: Date())
let savePath = (documentDirectory as NSString).appendingPathComponent("mergeVideo-\(date).mov")
let url = URL(fileURLWithPath: savePath)
// 5 - Create Exporter
guard let exporter = AVAssetExportSession(asset: cmp, presetName: AVAssetExportPresetHighestQuality) else { return }
exporter.outputURL = url
exporter.outputFileType = AVFileTypeQuickTimeMovie
exporter.shouldOptimizeForNetworkUse = true
exporter.videoComposition = animComp
// 6 - Perform the Export
exporter.exportAsynchronously() {
DispatchQueue.main.async { _ in
self.exportDidFinish(exporter)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment