TrackItem with ImageResource does not work in Timeline overlays
Hello there,
I'm new to Cabbage and I'm struggling to figure out how to overlay image content on top of another video. Overlaying video on top another video works fine.
Here's what I'm trying to do:
let resource = ImageResource(image: CIImage(image: embed.image)!, duration: CMTime(seconds: 2.0, preferredTimeScale: 600))
let t = TrackItem(resource: resource)
t.startTime = embed.insertTime
t.duration = overlayDuration
t.videoConfiguration.frame = embed.frame
timeline.overlays = [t]
let compositionGenerator = CompositionGenerator(timeline: timeline)
guard let exporter = compositionGenerator.buildExportSession(presetName: AVAssetExportPreset1280x720) else {
completion(nil)
return
}
let outputFileURL = URL(fileURLWithPath: NSTemporaryDirectory() + UUID().uuidString + ".mp4")
exporter.outputURL = outputFileURL
exporter.outputFileType = .mp4
exporter.shouldOptimizeForNetworkUse = true
exporter.exportAsynchronously {
switch exporter.status {
case .completed:
DispatchQueue.main.async {
completion(exporter)
}
case .failed:
DispatchQueue.main.async {
completion(exporter)
}
case .cancelled:
DispatchQueue.main.async {
completion(exporter)
}
default:
break
}
}
The video gets exported but does not contain the image overlay. I'd appreciate any help. Thanks!
For the question
If t.startTime = embed.insertTime is not zero, you should add a empty resource, and it's timeRange is 0 to t.startTime. Make sure the track is full.
like this |------------------| not this |[empty]----------|
let resource = Resource()
resource.duration = t.startTime
resource.selectedTimeRange = CMTimeRange(start: CMTime.zero, end: t.startTime)
let emptyTrackItem = TrackItem(resource: )
timeline.overlays = [emptyTrackItem , t]
Better way to add overlay image
timeline.overlays is for video overlay, it will add track to AVAsset
Another way, see the demo code https://github.com/VideoFlint/Cabbage/blob/8fa17a18afc40dd00da267865edbd12923694553/Cabbage/ViewController.swift#L79-L129
simplest and better way to add overlay image
let url = Bundle.main.url(forResource: "overlay", withExtension: "jpg")!
let image = CIImage(contentsOf: url)!
let resource = ImageResource(image: image, duration: CMTime.init(seconds: 3, preferredTimescale: 600))
let imageCompositionProvider = ImageOverlayItem(resource: resource)
timeline.passingThroughVideoCompositionProvider = imageCompositionProvider
Thanks for the explanation.
The users of my app can embed multiple video and image overlays on a given video background. These embeds might be temporally and spatially overlapping with each other. My simple approach adding the TrackItems to the overlays array works great if the embeds are videos. That's why I was confused when it didn't work with images.
For now I'll try the empty track item approach but I'd be happy to send a PR to make this possible with TrackItems with ImageResources as well, if you think that's possible.