Я пытаюсь объединить два видео, чтобы второе видео было поверх другого видео. Мое второе видео имеет прозрачный фон, поэтому мой желаемый результат выглядит следующим образом:
Однако я не вижу второго видео в своем результате
Вот мой код:
func merge(video firstAsset: AVAsset, withSecondVideo secondAsset: AVAsset, completion: @escaping (_ mergedVideoURL: URL?, _ error: Error?) -> Void) {
let mixComposition = AVMutableComposition()
let firstTrack = mixComposition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: kCMPersistentTrackID_Invalid)
let secondTrack = mixComposition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: kCMPersistentTrackID_Invalid)
let audioTrack = mixComposition.addMutableTrack(withMediaType: AVMediaType.audio , preferredTrackID: kCMPersistentTrackID_Invalid)
guard let firstMediaTrack = firstAsset.tracks(withMediaType: AVMediaType.video).first else { return }
guard let secondMediaTrack = secondAsset.tracks(withMediaType: AVMediaType.video).first else { return }
guard let audioAsset = secondAsset.tracks(withMediaType: AVMediaType.audio).first else { return }
do {
try firstTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: firstAsset.duration), of: firstMediaTrack, at: CMTime.zero)
try secondTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: firstAsset.duration), of: secondMediaTrack, at: CMTime.zero)
try audioTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: firstAsset.duration), of: audioAsset, at: CMTime.zero)
} catch (let error) {
print(error)
}
let width = max(firstMediaTrack.naturalSize.width, secondMediaTrack.naturalSize.width)
let height = max(firstMediaTrack.naturalSize.height, secondMediaTrack.naturalSize.height)
let videoComposition = AVMutableVideoComposition()
videoComposition.renderSize = CGSize(width: width, height: height)
videoComposition.frameDuration = firstMediaTrack.minFrameDuration
let firstLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: firstMediaTrack)
firstLayerInstruction.setTransform(firstMediaTrack.preferredTransform, at: CMTime.zero)
let secondlayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: secondMediaTrack)
secondlayerInstruction.setTransform(secondMediaTrack.preferredTransform, at: CMTime.zero)
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRangeMake(start: CMTime.zero, duration: firstAsset.duration)
instruction.layerInstructions = [firstLayerInstruction, secondlayerInstruction]
videoComposition.instructions = [instruction]
let outputUrl = URL(fileURLWithPath: ((FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last)?.path)!).appendingPathComponent("\(UUID().uuidString)-mergedVideo.mp4").path
exportCompositedVideo(compiledVideo: mixComposition, toURL: URL(fileURLWithPath: outputUrl), withVideoComposition: videoComposition) { (output) in
DispatchQueue.main.async(execute: {() -> Void in
completion(output,nil)
})
}
}
func exportCompositedVideo(compiledVideo: AVMutableComposition, toURL outputUrl: URL, withVideoComposition videoComposition: AVMutableVideoComposition, completion: @escaping (_ mergedVideoURL: URL?) -> Void) {
guard let exporter = AVAssetExportSession(asset: compiledVideo, presetName: AVAssetExportPresetHighestQuality) else { return }
exporter.outputURL = outputUrl
exporter.videoComposition = videoComposition
exporter.outputFileType = AVFileType.mp4
exporter.shouldOptimizeForNetworkUse = true
exporter.exportAsynchronously(completionHandler: {
switch exporter.status {
case .completed:
PHPhotoLibrary.shared().performChanges({PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: exporter.outputURL!)
}) { saved, error in
if saved {
print("save of potentially looped video succesful")
}
}
completion(exporter.outputURL)
case .exporting:
let progress = exporter.progress
print(" Progress "\(progress)")
case .failed:
print("Error: \(exporter.error)")
print("Description: \(exporter.description)")
default: break
}
})
}
Я пробовал несколько решений, но результат всегда один и тот же