I am creating two layers for a video and attempting to show my very own URL with a video on every separate layer. What am I doing improper? I’ve solely the primary video displayed within the remaining consequence on the video layer and on the overlay layer.
Challenge: Within the remaining output video, I solely see the video from the primary URL (videoURL) on each the video layer and the overlay layer. The overlay layer doesn’t show the video from overlayVideoURL as anticipated.
What I’ve Tried:
I checked the CALayer frames and confirmed that they’re set accurately.
Verified that AVVideoCompositionCoreAnimationTool is used accurately.
Confirmed that AVMutableComposition has each tracks inserted.
Questions:
Is there a mistake in how I’m organising the video layers?
How can I make sure that every layer shows its respective video accurately?
Extra Particulars:
The movies are accurately loaded and inserted into the AVMutableComposition.
The ultimate composition solely shows the video from videoURL on each layers.
func makeVideo(videoURL: URL, overlayVideoURL: URL, forName identify: String, onComplete: @escaping (URL?) -> Void) {
let asset = AVURLAsset(url: videoURL)
let overlayAsset = AVURLAsset(url: overlayVideoURL)
let composition = AVMutableComposition()
guard
let compositionTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid),
let assetTrack = asset.tracks(withMediaType: .video).first,
let overlayCompositionTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid),
let overlayAssetTrack = overlayAsset.tracks(withMediaType: .video).first
else {
print("One thing is improper with the belongings.")
onComplete(nil)
return
}
do {
let timeRange = CMTimeRange(begin: .zero, period: asset.period)
attempt compositionTrack.insertTimeRange(timeRange, of: assetTrack, at: .zero)
attempt overlayCompositionTrack.insertTimeRange(timeRange, of: overlayAssetTrack, at: .zero)
} catch {
print(error)
onComplete(nil)
return
}
let videoInfo = orientation(from: assetTrack.preferredTransform)
let videoSize = videoInfo.isPortrait ? CGSize(width: assetTrack.naturalSize.top, top: assetTrack.naturalSize.width) : assetTrack.naturalSize
let videoComposition = AVMutableVideoComposition()
videoComposition.renderSize = videoSize
videoComposition.frameDuration = CMTime(worth: 1, timescale: 30)
let instruction = AVMutableVideoCompositionInstruction()
instruction.timeRange = CMTimeRange(begin: .zero, period: composition.period)
let layerInstruction = compositionLayerInstruction(for: compositionTrack, assetTrack: assetTrack)
let overlayLayerInstruction = compositionLayerInstruction(for: overlayCompositionTrack, assetTrack: overlayAssetTrack)
instruction.layerInstructions = [layerInstruction, overlayLayerInstruction]
videoComposition.directions = [instruction]
let videoLayer = CALayer()
videoLayer.body = CGRect(origin: .zero, measurement: videoSize)
let overlayVideoLayer = CALayer()
overlayVideoLayer.body = CGRect(x: videoSize.width / 4, y: videoSize.top / 4, width: videoSize.width / 2, top: videoSize.top / 2)
let outputLayer = CALayer()
outputLayer.body = CGRect(origin: .zero, measurement: videoSize)
outputLayer.addSublayer(videoLayer)
outputLayer.addSublayer(overlayVideoLayer)
videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayers: [videoLayer, overlayVideoLayer], in: outputLayer)
guard let export = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality) else {
print("Can't create export session.")
onComplete(nil)
return
}
let videoName = UUID().uuidString
let exportURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(videoName).appendingPathExtension("mov")
export.videoComposition = videoComposition
export.outputFileType = .mov
export.outputURL = exportURL
export.exportAsynchronously {
DispatchQueue.essential.async {
change export.standing {
case .accomplished:
onComplete(exportURL)
default:
print("One thing went improper throughout export.")
print(export.error ?? "unknown error")
onComplete(nil)
}
}
}
}