Уже ответ, данный @Julio, отлично работает в случае target-c Вот та же база кода для Swift 3.0 :
WATERMARK & Generation SQUARE или CROPPED видео, какInstagram
Получение выходного файла из каталога документов и создание AVURLAsset
//output file
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
let outputPath = documentsURL?.appendingPathComponent("squareVideo.mov")
if FileManager.default.fileExists(atPath: (outputPath?.path)!) {
do {
try FileManager.default.removeItem(atPath: (outputPath?.path)!)
}
catch {
print ("Error deleting file")
}
}
//input file
let asset = AVAsset.init(url: filePath)
print (asset)
let composition = AVMutableComposition.init()
composition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)
//input clip
let clipVideoTrack = asset.tracks(withMediaType: AVMediaTypeVideo)[0]
Создание слоя с изображением водяного знака:
//adding the image layer
let imglogo = UIImage(named: "video_button")
let watermarkLayer = CALayer()
watermarkLayer.contents = imglogo?.cgImage
watermarkLayer.frame = CGRect(x: 5, y: 25 ,width: 57, height: 57)
watermarkLayer.opacity = 0.85
Создайте слой с текстом в качестве водяного знака вместо изображения:
let textLayer = CATextLayer()
textLayer.string = "Nodat"
textLayer.foregroundColor = UIColor.red.cgColor
textLayer.font = UIFont.systemFont(ofSize: 50)
textLayer.alignmentMode = kCAAlignmentCenter
textLayer.bounds = CGRect(x: 5, y: 25, width: 100, height: 20)
Следующий код сортирует слой в правильном порядке:
let videoSize = clipVideoTrack.naturalSize
let parentlayer = CALayer()
let videoLayer = CALayer()
parentlayer.frame = CGRect(x: 0, y: 0, width: videoSize.height, height: videoSize.height)
videoLayer.frame = CGRect(x: 0, y: 0, width: videoSize.height, height: videoSize.height)
parentlayer.addSublayer(videoLayer)
parentlayer.addSublayer(watermarkLayer)
parentlayer.addSublayer(textLayer) //for text layer only
Добавление слоев поверх видео в правильном порядке для водяного знака
let videoSize = clipVideoTrack.naturalSize
let parentlayer = CALayer()
let videoLayer = CALayer()
parentlayer.frame = CGRect(x: 0, y: 0, width: videoSize.height, height: videoSize.height)
videoLayer.frame = CGRect(x: 0, y: 0, width: videoSize.height, height: videoSize.height)
parentlayer.addSublayer(videoLayer)
parentlayer.addSublayer(watermarkLayer)
parentlayer.addSublayer(textLayer) //for text layer only
Обрезка видео в квадратном формате - 300 * 300 вразмер
//make it square
let videoComposition = AVMutableVideoComposition()
videoComposition.renderSize = CGSize(width: 300, height: 300) //change it as per your needs.
videoComposition.frameDuration = CMTimeMake(1, 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(kCMTimeZero, CMTimeMakeWithSeconds(60, 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: kCMTimeZero)
instruction.layerInstructions = [transformer]
videoComposition.instructions = [instruction]
Последний шаг для экспорта видео
let exporter = AVAssetExportSession.init(asset: asset, presetName: AVAssetExportPresetMediumQuality)
exporter?.outputFileType = AVFileTypeQuickTimeMovie
exporter?.outputURL = outputPath
exporter?.videoComposition = videoComposition
exporter?.exportAsynchronously() { handler -> Void in
if exporter?.status == .completed {
print("Export complete")
DispatchQueue.main.async(execute: {
completion(outputPath)
})
return
} else if exporter?.status == .failed {
print("Export failed - \(String(describing: exporter?.error))")
}
completion(nil)
return
}
Будет экспортировано видео в квадратном размере с водяным знаком в виде текста или изображения
Спасибо