The sample code creates a color clip with a duration of 2.24, a size of [1080, 1080] and fps=50.0
The clip writes properly after CompositeVideoClip but if it is concatenated then the duration changes slightly and writing fails.
>>> vclip = ColorClip([1080, 1080], color=[255, 128, 64], duration=2.24)
>>> vclip.duration
2.24
>>> vclip.size
(1080, 1080)
>>> comp = CompositeVideoClip([vclip])
>>> comp = comp.set_fps(50.0)
>>> comp.fps
50.0
>>> comp.write_videofile('comp.mp4', preset='ultrafast')
The file writes successfully
>>> concat = concatenate([comp])
>>> concat.duration
2.2400000000000002
>>> concat.write_videofile('concat.mp4', preset='ultrafast')
The write_videofile() fails with IndexError
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<decorator-gen-51>", line 2, in write_videofile
File "/usr/local/lib/python3.6/site-packages/moviepy/decorators.py", line 54, in requires_duration
return f(clip, *a, **k)
File "<decorator-gen-50>", line 2, in write_videofile
File "/usr/local/lib/python3.6/site-packages/moviepy/decorators.py", line 137, in use_clip_fps_by_default
return f(clip, *new_a, **new_kw)
File "<decorator-gen-49>", line 2, in write_videofile
File "/usr/local/lib/python3.6/site-packages/moviepy/decorators.py", line 22, in convert_masks_to_RGB
return f(clip, *a, **k)
File "/usr/local/lib/python3.6/site-packages/moviepy/video/VideoClip.py", line 349, in write_videofile
progress_bar=progress_bar)
File "/usr/local/lib/python3.6/site-packages/moviepy/video/io/ffmpeg_writer.py", line 209, in ffmpeg_write_video
fps=fps, dtype="uint8"):
File "/usr/local/lib/python3.6/site-packages/tqdm/_tqdm.py", line 833, in __iter__
for obj in iterable:
File "/usr/local/lib/python3.6/site-packages/moviepy/Clip.py", line 475, in generator
frame = self.get_frame(t)
File "<decorator-gen-14>", line 2, in get_frame
File "/usr/local/lib/python3.6/site-packages/moviepy/decorators.py", line 89, in wrapper
return f(*new_a, **new_kw)
File "/usr/local/lib/python3.6/site-packages/moviepy/Clip.py", line 95, in get_frame
return self.make_frame(t)
File "/usr/local/lib/python3.6/site-packages/moviepy/video/compositing/concatenate.py", line 83, in make_frame
return clips[i].get_frame(t - tt[i])
IndexError: list index out of range
Can confirm this problem, thanks for spotting!
@tburrows13 Who are you asking for confirmation?
I meant that I can confirm this problem, sorry!
@tburrows13 Great. Thanks for your help.
Can confirm this is still happening. the output of concatenate_videoclips assumes there's one more frame than there are in the clips that were merged. Seems to happen because of the float precision when the time of certain clip cannot be represented exactly.
Temporary workaround if anyone's still stuck:
final_clip = concatenate_videoclips(list_of_clips)
try:
final_clip.write_videofile(save_path, threads=6, logger=None)
logger.info("Saved .mp4 without Exception at {}".format(save_path))
except IndexError:
# Short by one frame, so get rid on the last frame:
final_clip = final_clip.subclip(t_end=(clip.duration - 1.0/final_clip.fps))
final_clip.write_videofile(save_path, threads=6, logger=None)
logger.info("Saved .mp4 after Exception at {}".format(save_path))
except Exception as e:
logger.warning("Exception {} was raised!!".format(e))
Still get the same IndexError problem but the @AidasLiaudanskas patch works perfectly fine ! Thanks