I tried a lot of code to add watermark (Image) in my recorded video but still unable to add. My video is in portrait mode.
Reference : https://stackoverflow.com/a/45304222
Issues :
- Video size got changed but water mark not visible to video.
- Video size got zero and blank but water mark not visible to video.
- I set video orientation then video got blank by 30 pixel from right but water mark not visible to video.
Code that I applied:
func setWaterMarkVideoOutput(inputURL: URL) {
//input file
let asset = AVAsset.init(url: inputURL)
let composition = AVMutableComposition.init()
composition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: kCMPersistentTrackID_Invalid)
//input clip
let clipVideoTrack = asset.tracks(withMediaType: AVMediaType.video)[0]
//adding the image layer
let imglogo = UIImage(named: "WatermarkImage")
let watermarkLayer = CALayer()
watermarkLayer.contents = imglogo?.cgImage
watermarkLayer.frame = CGRect(x: 25, y: 25 ,width: 417, height: 103)
watermarkLayer.opacity = 0.86
let videoSize = clipVideoTrack.naturalSize
let parentlayer = CALayer()
let videoLayer = CALayer()
parentlayer.frame = CGRect(x: 0, y: 0, width: videoSize.width, height: videoSize.height)
videoLayer.frame = CGRect(x: 0, y: 0, width: videoSize.width, height: videoSize.height)
parentlayer.addSublayer(videoLayer)
parentlayer.addSublayer(watermarkLayer)
//make it square
let videoComposition = AVMutableVideoComposition()
videoComposition.renderSize = CGSize(width: videoSize.width, height: videoSize.height)
//change it as per your needs.
videoComposition.frameDuration = CMTimeMake(value: 1, timescale: 30)
videoComposition.renderScale = 1.0
//Magic line for adding watermark to the video
videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayers: [videoLayer], in: parentlayer)
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRangeMake(start: CMTime.zero, duration: CMTimeMakeWithSeconds(60, preferredTimescale: 30))
//rotate to potrait
let transformer = AVMutableVideoCompositionLayerInstruction(assetTrack: clipVideoTrack)
let t1 = CGAffineTransform(translationX: clipVideoTrack.naturalSize.height, y: -(clipVideoTrack.naturalSize.width - clipVideoTrack.naturalSize.height) / 2)
let t2: CGAffineTransform = t1.rotated(by: .pi/2)
let finalTransform: CGAffineTransform = t2
transformer.setTransform(finalTransform, at: CMTime.zero)
instruction.layerInstructions = [transformer]
videoComposition.instructions = [instruction]
let documentsPath = NSTemporaryDirectory()
let outputPath = "\(documentsPath)/\(String.uniqueFilename(withPrefix: "NewVideo")).mp4"
let outputURL = URL(fileURLWithPath: outputPath)
let exporter = AVAssetExportSession.init(asset: asset, presetName: AVAssetExportPresetMediumQuality)
exporter?.outputFileType = AVFileType.mov
exporter?.outputURL = outputURL
exporter?.videoComposition = videoComposition
exporter?.exportAsynchronously() {
if exporter?.status == .completed {
print("Export complete")
DispatchQueue.main.async {
print("videoUrl:::", outputURL)
}
return
} else if exporter?.status == .failed {
print("Export failed - \(String(describing: exporter?.error))")
}
return
}
}
Please correct me what I did wrong in this method. Thank you in Advance.