VideoFlint / Cabbage

A video composition framework build on top of AVFoundation. It's simple to use and easy to extend.
MIT License
1.52k stars 221 forks source link

Is there a way to change only the URL resource without having to rebuild composition? #36

Closed mvn-thanhluu-hn closed 4 years ago

mvn-thanhluu-hn commented 4 years ago

Hi Vitoziv!

I am currently using your library in some video editing projects and it is really awesome. Thank you for your efforts to create this library and to make editing videos easier.

While using your library I have encountered some issues that I would like to share and look forward to your feedback.

I often have to change track items and re-build player item. Ex: change the URL of a track item ... But I'm having performance issues because the build player item takes a long time and takes up a lot of device resources

So is there a way for me to not have to re-build the player item but only update the changes?

Ex: The code below when I want to change the URL of bambooTrackItem, I am currently rebuilding the compositionGenerator and re-build player item.

Looking forward to hearing from you. Thank you!

let bambooTrackItem: TrackItem = {
            let url = Bundle.main.url(forResource: "bamboo", withExtension: "mp4")!
            let resource = AVAssetTrackResource(asset: AVAsset(url: url))
            let trackItem = TrackItem(resource: resource)
            trackItem.videoConfiguration.contentMode = .aspectFit
            return trackItem
        }()

        let overlayTrackItem: TrackItem = {
            let url = Bundle.main.url(forResource: "overlay", withExtension: "jpg")!
            let image = CIImage(contentsOf: url)!
            let resource = ImageResource(image: image, duration: CMTime.init(seconds: 5, preferredTimescale: 600))
            let trackItem = TrackItem(resource: resource)
            trackItem.videoConfiguration.contentMode = .aspectFit
            return trackItem
        }()

        let seaTrackItem: TrackItem = {
            let url = Bundle.main.url(forResource: "sea", withExtension: "mp4")!
            let resource = AVAssetTrackResource(asset: AVAsset(url: url))
            let trackItem = TrackItem(resource: resource)
            trackItem.videoConfiguration.contentMode = .aspectFit
            return trackItem
        }()

        let transitionDuration = CMTime(seconds: 2, preferredTimescale: 600)
        bambooTrackItem.videoTransition = PushTransition(duration: transitionDuration)
        bambooTrackItem.audioTransition = FadeInOutAudioTransition(duration: transitionDuration)

        overlayTrackItem.videoTransition = BoundingUpTransition(duration: transitionDuration)

        let timeline = Timeline()
        timeline.videoChannel = [bambooTrackItem, overlayTrackItem, seaTrackItem]
        timeline.audioChannel = [bambooTrackItem, seaTrackItem]

        do {
            try Timeline.reloadVideoStartTime(providers: timeline.videoChannel)
        } catch {
            assert(false, error.localizedDescription)
        }
        timeline.renderSize = CGSize(width: 1920, height: 1080)

        let compositionGenerator = CompositionGenerator(timeline: timeline)
        let playerItem = compositionGenerator.buildPlayerItem()
        return playerItem
vitoziv commented 4 years ago

Hi

Unfortunately, you need to rebuild playerItem after change trackItem's resource.

But the rebuild time shouldn't be taking too long, I rebuild the playerItem in my app, and it's quick. Maybe you take too long to create other resources?

mvn-thanhluu-hn commented 4 years ago

You are right, after measuring the time I discovered it took a long time to create resources. Thanks for your response.