I have a 30 seconds video clip (1280*720, size around 3MB, *.MP4) and a logo image(4KB, JPG). I've managed to add the watermark and exported video using the following code, but the problem is:
- The exported video is around 20MB, could we make the video size less than 5MB while remain 1280*720 resolution or similar quality?
- The export process takes around 20 seconds, is it possible to make it faster?
- If I set
AVAssetExportSession
toAVAssetExportPresetMediumQuality
, it indeed becomes faster but the video quality isn't good enough
My goal is to make the whole process(add watermark and export) under 5-8 seconds while remain the pretty much same video quality and size? Is it possible? Thanks in advance.
func merge(videoPath: URL, withForegroundImage foregroundImage: UIImage, completion: @escaping (URL?) -> Void) {
let videoUrlAsset = AVURLAsset(url: videoPath, options: nil)
let mutableComposition = AVMutableComposition()
let videoAssetTrack = videoUrlAsset.tracks(withMediaType: AVMediaType.video).first!
let videoCompositionTrack = mutableComposition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: kCMPersistentTrackID_Invalid)
videoCompositionTrack?.preferredTransform = videoAssetTrack.preferredTransform
try! videoCompositionTrack?.insertTimeRange(CMTimeRange(start:CMTime.zero, duration:videoAssetTrack.timeRange.duration), of: videoAssetTrack, at: CMTime.zero)
addAudioTrack(composition: mutableComposition, videoUrl: videoPath)
let videoSize: CGSize = (videoCompositionTrack?.naturalSize)!
let frame = CGRect(x: 0.0, y: 0.0, width: videoSize.width, height: videoSize.height)
let imageLayer = CALayer()
imageLayer.contents = foregroundImage.cgImage
imageLayer.frame = CGRect(x: 40, y: 20, width:50, height:50)
let videoLayer = CALayer()
videoLayer.frame = frame
let animationLayer = CALayer()
animationLayer.frame = frame
animationLayer.addSublayer(videoLayer)
animationLayer.addSublayer(imageLayer)
let videoComposition = AVMutableVideoComposition(propertiesOf: (videoCompositionTrack?.asset!)!)
videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: animationLayer)
let documentDirectory = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.cachesDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first!
let documentDirectoryUrl = URL(fileURLWithPath: documentDirectory)
let destinationFilePath = documentDirectoryUrl.appendingPathComponent("result.mp4")
do {
if FileManager.default.fileExists(atPath: destinationFilePath.path) {
try FileManager.default.removeItem(at: destinationFilePath)
print("removed")
}
} catch {
print(error)
}
let exportSession = AVAssetExportSession(asset: mutableComposition, presetName: AVAssetExportPreset1280x720)!
exportSession.videoComposition = videoComposition
exportSession.outputURL = destinationFilePath
exportSession.outputFileType = .mp4
exportSession.exportAsynchronously { [weak exportSession] in
if let strongExportSession = exportSession {
print("exported")
completion(strongExportSession.outputURL!)
}
}
}
private func addAudioTrack(composition: AVMutableComposition, videoUrl: URL) {
let videoUrlAsset = AVURLAsset(url: videoUrl, options: nil)
let audioTracks = videoUrlAsset.tracks(withMediaType: AVMediaType.audio)
let compositionAudioTrack:AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: CMPersistentTrackID())!
for audioTrack in audioTracks {
try! compositionAudioTrack.insertTimeRange(audioTrack.timeRange, of: audioTrack, at: CMTime.zero)
}
}