今天項目遇到一個給視頻添加水印的需求,廢話不多挽绩,直接上代碼
1膛壹、直接調(diào)方法即可,inputURL:原視頻路徑唉堪,outputURL:添加水印后的輸出路徑模聋,watermarkText:水印內(nèi)容
func ht_addWatermarkToVideo(inputURL: URL, outputURL: URL, watermarkText: String, completion: @escaping (URL?, Error?) -> Void) {
let asset = AVURLAsset(url: inputURL)
let composition = AVMutableComposition()
guard let videoTrack = asset.tracks(withMediaType: .video).first else {
completion(nil, NSError(domain: "com.example", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to load video track"]))
return
}
let compositionVideoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
do {
try compositionVideoTrack?.insertTimeRange(CMTimeRange(start: .zero, duration: asset.duration), of: videoTrack, at: .zero)
} catch {
completion(nil, error)
return
}
let videoSize = videoTrack.naturalSize
let watermarkLayer = CATextLayer()
watermarkLayer.string = watermarkText
watermarkLayer.foregroundColor = UIColor.black.cgColor
watermarkLayer.font = UIFont.boldSystemFont(ofSize: 80).fontName as CFTypeRef
watermarkLayer.fontSize = 80
watermarkLayer.alignmentMode = .center
watermarkLayer.bounds = CGRect(x: 0, y: 0, width: KScreenWidth, height: 100)
watermarkLayer.position = CGPoint(x: videoSize.width/2, y: videoSize.height/2)
let videoLayer = CALayer()
videoLayer.frame = CGRect(origin: .zero, size: videoSize)
videoLayer.addSublayer(watermarkLayer)
let videoComposition = AVMutableVideoComposition()
videoComposition.renderSize = videoSize
videoComposition.frameDuration = CMTimeMake(value: 1, timescale: 30)
videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: videoLayer)
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRange(start: .zero, duration: composition.duration)
let layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: compositionVideoTrack!)
instruction.layerInstructions = [layerInstruction]
videoComposition.instructions = [instruction]
guard let exportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality) else {
completion(nil, NSError(domain: "com.example", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to create AVAssetExportSession"]))
return
}
exportSession.videoComposition = videoComposition
exportSession.outputURL = outputURL
exportSession.outputFileType = .mp4
exportSession.shouldOptimizeForNetworkUse = true
exportSession.exportAsynchronously {
switch exportSession.status {
case .completed:
completion(outputURL, nil)
case .failed:
completion(nil, exportSession.error)
case .cancelled:
completion(nil, NSError(domain: "com.example", code: 0, userInfo: [NSLocalizedDescriptionKey: "Export cancelled"]))
default:
break
}
}
}
2、使用方法
let path = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("Ding Move\(String(arc4random_uniform(100) + 1)).mp4")
let inputVideoURL = model.url
let outputVideoURL = path
let watermarkText = "Ding Movie"
ht_addWatermarkToVideo(inputURL: inputVideoURL, outputURL: outputVideoURL, watermarkText: watermarkText) { (outputURL, error) in
if let error = error {
DispatchQueue.main.async {
HTClassWSProgressHud.hideHud()
}
print("Failed to add watermark: \(error.localizedDescription)")
} else {
print("Watermark added successfully. Output video URL: \(outputURL?.path ?? "")")
//保存到相冊
HTClassPhotoTools.saveVideoToAlbum(videoURL: outputVideoURL) { isSuccess in
DispatchQueue.main.async {
HTClassWSProgressHud.hideHud()
HTClassToastHUD.show(isSuccess ? "Saved album successfully" : "Failed to save the album, please try again")
}
}
}
}