動画の合成方法を調べていたらこちら(AVFoundationで動画の加工合成処理)で紹介されている方法がわかりやすかったのでSwiftで書き直しました。
func capture(_ captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAt outputFileURL: URL!, fromConnections connections: [Any]!, error: Error!) {
// 動画URLからアセットを生成
let videoAsset: AVURLAsset = AVURLAsset(url: outputFileURL, options: nil)
// ベースとなる動画のコンポジション作成
let mixComposition : AVMutableComposition = AVMutableComposition()
let compositionVideoTrack: AVMutableCompositionTrack = mixComposition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)
// アセットからトラックを取得
let videoTrack: AVAssetTrack = videoAsset.tracks(withMediaType: AVMediaTypeVideo)[0]
// コンポジションの設定
try! compositionVideoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: videoTrack, at: kCMTimeZero)
compositionVideoTrack.preferredTransform = videoAsset.tracks(withMediaType: AVMediaTypeVideo)[0].preferredTransform
// ロゴのCALayerの作成
let logoImage: UIImage = UIImage(named: "logo.png")!
let logoLayer: CALayer = CALayer()
logoLayer.contents = logoImage.cgImage
logoLayer.frame = CGRect(x: 5, y: 25, width: 57, height: 57)
logoLayer.opacity = 0.9
// 動画のサイズを取得
let videoSize: CGSize = videoTrack.naturalSize
// 親レイヤーを作成
let parentLayer: CALayer = CALayer()
let videoLayer: CALayer = 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(logoLayer)
// 合成用コンポジション作成
let videoComp: AVMutableVideoComposition = AVMutableVideoComposition()
videoComp.renderSize = videoSize
videoComp.frameDuration = CMTimeMake(1, 30)
videoComp.animationTool = AVVideoCompositionCoreAnimationTool.init(postProcessingAsVideoLayer: videoLayer, in: parentLayer)
// インストラクション作成
let instruction: AVMutableVideoCompositionInstruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRangeMake(kCMTimeZero, mixComposition.duration)
let layerInstruction: AVMutableVideoCompositionLayerInstruction = AVMutableVideoCompositionLayerInstruction.init(assetTrack: videoTrack)
instruction.layerInstructions = [layerInstruction]
// インストラクションを合成用コンポジションに設定
videoComp.instructions = [instruction]
// 動画のコンポジションをベースにAVAssetExportを生成
let _assetExport = AVAssetExportSession.init(asset: mixComposition, presetName: AVAssetExportPresetMediumQuality)
// 合成用コンポジションを設定
_assetExport?.videoComposition = videoComp
// エクスポートファイルの設定
let videoName: String = "test.mov"
let _exportPath: String = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let exportPath: String = _exportPath + "/" + videoName
let exportUrl: URL = URL(fileURLWithPath: exportPath)
_assetExport?.outputFileType = AVFileTypeQuickTimeMovie
_assetExport?.outputURL = exportUrl
_assetExport?.shouldOptimizeForNetworkUse = true
// ファイルが存在している場合は削除
if FileManager.default.fileExists(atPath: exportPath) {
try! FileManager.default.removeItem(atPath: exportPath)
}
// エクスポート実行
_assetExport?.exportAsynchronously(completionHandler: {() -> Void in
// 端末に保存
let library: ALAssetLibrary = ALAssetsLibrary()
if library.videoAtPathIs(compatibleWithSavedPhotosAlbum: exportUrl) {
library.writeVideoAtPath(toSavedPhotosAlbum: self.delegate.exportUrl, completionBlock: nil)
}
})
}