Skip to content

Instantly share code, notes, and snippets.

@TheSwiftyCoder
Created August 7, 2017 11:45
Show Gist options
  • Save TheSwiftyCoder/70c25ef1da406124297884176179f354 to your computer and use it in GitHub Desktop.
Save TheSwiftyCoder/70c25ef1da406124297884176179f354 to your computer and use it in GitHub Desktop.
Allows a UIImage to be placed full width and height of a video in Swift 3
func processVideoWithWatermark(video: AVURLAsset, watermark: UIImage, completion: @escaping (Bool) -> Void) {
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
let outputPath = documentsURL?.appendingPathComponent("dfyVideo_\(Date().timeStamp).mov") // Needs random time
if FileManager.default.fileExists(atPath: video.url.absoluteString) {
do {
try FileManager.default.removeItem(atPath: video.url.absoluteString)
}
catch {
print ("Error deleting file")
}
}
// File to composit
let asset = AVAsset.init(url: video.url)
let composition = AVMutableComposition.init()
composition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)
let clipVideoTrack = asset.tracks(withMediaType: AVMediaTypeVideo)[0]
// Rotate to potrait
let transformer = AVMutableVideoCompositionLayerInstruction(assetTrack: clipVideoTrack)
var videoAssetOrientation_: UIImageOrientation = .up
var isVideoAssetPortrait_: Bool = false
let videoTransform:CGAffineTransform = clipVideoTrack.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
}
transformer.setTransform(clipVideoTrack.preferredTransform, at: kCMTimeZero)
var naturalSize = CGSize()
if isVideoAssetPortrait_ {
naturalSize = CGSize(width: clipVideoTrack.naturalSize.height, height: clipVideoTrack.naturalSize.width)
} else {
naturalSize = clipVideoTrack.naturalSize
}
var renderWidth: CGFloat!
var renderHeight: CGFloat!
renderWidth = naturalSize.width
renderHeight = naturalSize.height
let parentlayer = CALayer()
let videoLayer = CALayer()
let watermarkLayer = CALayer()
watermarkLayer.contents = watermark.cgImage
watermarkLayer.opacity = 1.0
parentlayer.frame = CGRect(x: 0, y: 0, width: renderWidth, height: renderHeight)
videoLayer.frame = CGRect(x: 0, y: 0, width: renderWidth, height: renderHeight)
watermarkLayer.frame = CGRect(x: 0, y: 0 ,width: renderWidth, height: renderHeight)
parentlayer.addSublayer(videoLayer)
parentlayer.addSublayer(watermarkLayer)
let videoComposition = AVMutableVideoComposition()
videoComposition.renderSize = CGSize(width: renderWidth, height: renderHeight)
videoComposition.frameDuration = CMTimeMake(1, 30)
videoComposition.renderScale = 1.0
// Add watermark to video
videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayers: [videoLayer], in: parentlayer)
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(60, 30))
instruction.layerInstructions = [transformer]
videoComposition.instructions = [instruction]
let exporter = AVAssetExportSession.init(asset: asset, presetName: AVAssetExportPresetHighestQuality)
exporter?.outputFileType = AVFileTypeQuickTimeMovie
exporter?.outputURL = outputPath
exporter?.videoComposition = videoComposition
exporter?.exportAsynchronously() { handler -> Void in
if exporter?.status == .completed {
DispatchQueue.main.async(execute: {
self.saveVideoToUserLibrary(fileURL: outputPath!, savingCompletion: { (success, error) in
if success == true {
completion(true)
} else {
print("Saving error: \(error)")
completion(false)
}
})
})
return
} else if exporter?.status == .failed {
print("Export failed - \(String(describing: exporter?.error))")
}
completion(false)
return
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment