Unexpected Behavior With Subclip
I have a video clip that is created by concatenating intro and outro cards (ImageClips) around the video (VideoFileClip) itself:
clip = mpy.concatenate_videoclips([intro, mainevent, outro])
The behavior of subclip is inconsistent in this case.
- Creating a
subclipof the start of the video succeeds.sub = clip.subclip(0, 10)sub = clip.subclip(0, 60) - Creating a
subclipof the end of the video fails using the duration to calculate, IF the duration is entirely within the outro card:>>> clip.subclip(clip.duration-10, 0)*** ValueError: t_start (615.00) should be smaller than the clip's duration (585.00).>>> clip.duration625.0 - Creating a
subclipof the end of the video succeeds using the duration to calculate, IF the duration is not entirely within the outro card:>>> clip.subclip(clip.duration-60, 0)<moviepy.video.VideoClip.VideoClip object at 0x7f658f5d60f0>
Suggest investigating behavior so that the third case is consistent with other behavior.
So apparently... this works?
>>> clip.subclip(clip.duration-10)
*** ValueError: t_start (615.00) should be smaller than the clip's duration (585.00).
>>> clip.duration
625.0
>>> clip.set_duration(clip.duration).subclip(clip.duration-10)
<moviepy.video.VideoClip.VideoClip object at 0x7f9a76a3e240>
:confounded:
@SenorPez Not having used the feature you describe myself yet: could you let us know how you think this could/should be improved? Thanks.
When creating a clip with concatenate, the duration is set correctly (in my example, 625), but that duration isn't recognized by subclip (note the message that "t_start (615) should be smaller than the clip's duration (585)").
You need to chain a set_duration(clip.duration) into the call (which is like saying a=a) to make it work.
@SenorPez that's weird, can you provide a minimal code that produces the error ?
Also I dont understand clip.subclip(clip.duration-10, 0): you are setting t_end to 0 ? Does this actually work ? (it shouldn't).
The issue here is that even though clip.duration is 625, .subclip() is also applied to the clip's audio and mask, which may not have duration 625. In this case, because the outro is composed of an ImageClip, it does not have an audio, so it crashes when it tries to subclip the audio.
I have replicated it here:
from moviepy.editor import *
c1 = VideoFileClip("media/big_buck_bunny_0_30.webm")
c2 = ImageClip("media/vacation_2017.jpg").set_duration(10)
c = concatenate_videoclips([c1, c2])
c.duration
# 40.0
c.audio.duration
# 30.0
c.subclip(c.duration-5)
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "</Users/tomburrows/miniconda3/envs/moviepy/lib/python3.7/site-packages/decorator.py:decorator-gen-36>", line 2, in subclip
File "/Users/tomburrows/Python/moviepy-dev/moviepy/moviepy/decorators.py", line 89, in wrapper
return f(*new_a, **new_kw)
File "</Users/tomburrows/miniconda3/envs/moviepy/lib/python3.7/site-packages/decorator.py:decorator-gen-35>", line 2, in subclip
File "/Users/tomburrows/Python/moviepy-dev/moviepy/moviepy/decorators.py", line 32, in apply_to_mask
newclip = f(clip, *a, **k)
File "</Users/tomburrows/miniconda3/envs/moviepy/lib/python3.7/site-packages/decorator.py:decorator-gen-34>", line 2, in subclip
File "/Users/tomburrows/Python/moviepy-dev/moviepy/moviepy/decorators.py", line 45, in apply_to_audio
newclip.audio = f(newclip.audio, *a, **k)
File "/Users/tomburrows/Python/moviepy-dev/moviepy/moviepy/Clip.py", line 384, in subclip
+ "duration (%.02f)." % self.duration
ValueError: t_start (35.00) should be smaller than the clip's duration (30.00).
c.subclip(c.duration-5, 0)
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "</Users/tomburrows/miniconda3/envs/moviepy/lib/python3.7/site-packages/decorator.py:decorator-gen-36>", line 2, in subclip
File "/Users/tomburrows/Python/moviepy-dev/moviepy/moviepy/decorators.py", line 89, in wrapper
return f(*new_a, **new_kw)
File "</Users/tomburrows/miniconda3/envs/moviepy/lib/python3.7/site-packages/decorator.py:decorator-gen-35>", line 2, in subclip
File "/Users/tomburrows/Python/moviepy-dev/moviepy/moviepy/decorators.py", line 32, in apply_to_mask
newclip = f(clip, *a, **k)
File "</Users/tomburrows/miniconda3/envs/moviepy/lib/python3.7/site-packages/decorator.py:decorator-gen-34>", line 2, in subclip
File "/Users/tomburrows/Python/moviepy-dev/moviepy/moviepy/decorators.py", line 45, in apply_to_audio
newclip.audio = f(newclip.audio, *a, **k)
File "/Users/tomburrows/Python/moviepy-dev/moviepy/moviepy/Clip.py", line 384, in subclip
+ "duration (%.02f)." % self.duration
ValueError: t_start (35.00) should be smaller than the clip's duration (30.00).
@tburrows13 this is the exact issue I am facing. Did you find any solution to this?
For other people facing this issue, adding
complete_video = complete_video.set_duration(complete_video.duration)
before subclipping complete_video seemed to solve the problem for me.
sub = complete_video.subclip(55, 60)
For some reason, I keep on making these seemingly random values for duration when I run this code: clip = VideoFileClip('/media/video-1hr.mp4') clip = clip.set_duration(clip.duration) duration = math.floor(clip.duration)
rand_start = int(random.randint(0, int(duration - 60))) rand_end = int(rand_start + 60) print(rand_start, rand_end) short = clip.subclip(rand_start, rand_end) # bro what is wrong with this line
print(short.duration)
(Note it is extra large because I added extra measures to try and remedy the situation to no avail).
When I look at the values rand_start and rand_end, they have a difference of 60 perfectly every time, but when running the subclip function, and then finding out the duration of the clip, it comes out to an assortment of random numbers within the total range of the video, but not a consistent 60 seconds as it should be. Thanks!