Zulko / moviepy

Video editing with Python
https://zulko.github.io/moviepy/
MIT License
12.42k stars 1.55k forks source link

CompositeVideoClip use_bgclip=True with different length videos #2053

Open rsewell97 opened 11 months ago

rsewell97 commented 11 months ago

Expected Behavior

I would like to overlay an ImageClip over a VideoClip for a set period of time (not the entire duration of the VideoClip). I am using use_bgclip=True for performance as it's significantly quicker than without.

Actual Behavior

After the ImageClip disappears, the VideoClip freezes for the remainder of the clip.

Steps to Reproduce the Problem

size = (1920, 1080) 
cu_clip = (
    ImageClip(np.zeros(size), duration=5)
    .set_fps(24)
    .set_position((0, 0))
)  # Top-left

section = CompositeVideoClip(
    [
        some_videoclip_with_duration_20a,
        cu_clip.set_start(5)
        .crossfadein(0.5)
        .crossfadeout(0.5)
    ],
    use_bgclip=True,
).set_audio(some_videoclip_with_duration_20a.audio)
section.write_videoclip('tmp.mp4')

Specifications

Goyet-Christopher commented 11 months ago

This appears to be related to the 'use_bgclip' option. If you don't use it, the video duration is correct:

section = CompositeVideoClip([
        bg_clip,
        cu_clip.with_start(5)
        .crossfadein(0.5)
        .crossfadeout(0.5)
])

The bug comes from this piece of code in CompositeVideoClip.py, which recalculates the total time from the clips :

        # compute duration
        ends = [clip.end for clip in self.clips]
        if None not in ends:
            duration = max(ends)
            self.duration = duration
            self.end = duration    

But the bg has been removed juste above :

      if use_bgclip:
            self.bg = clips[0]
            self.clips = clips[1:]
            self.created_bg = False

Is it a bug, or is it intentional? It appears to me that a background clip is meant to fill in the background when other videos are playing. If there are no more videos, it seems reasonable for the video to stop, right?

Edit : With moviepy v2, you should use new functions : with_fps, with_position, with_start, write_videofile, ...