Zulko/moviepy

concatenate_videoclips() can't handle TextClips

Closed this issue ยท 9 comments

Description

When composing a clip with an ImageClip and a TextClip, the composition will render, but the clip resulting from calling concatenate_videoclips() won't.

HowTo reproduce

  1. save example to .py file
  2. Have moviepy version 0.2.3.2 installed
  3. run the example with python 3 (tested with 3.5.2)
#!/usr/bin/python3

import requests
import os
from moviepy.editor import ImageClip, TextClip, CompositeVideoClip, concatenate_videoclips

IMAGE_URL = 'http://www.planwallpaper.com/static/images/4-Nature-Wallpapers-2014-1_cDEviqY.jpg'
IMAGE_PATH = '/tmp/test.jpg'
RESULT_PATH = '/tmp/result.png'

# get test image if necessary 
if not os.path.exists(IMAGE_PATH):
    resp = requests.get(IMAGE_URL)
    with open(IMAGE_PATH, 'wb') as f:
        for chunk in resp.iter_content(chunk_size=128):
            f.write(chunk)

image_clip = ImageClip(IMAGE_PATH, duration=1)
text_clip = TextClip('Hello World', fontsize=70, color='white')
comp_clip = CompositeVideoClip([image_clip, text_clip])
comp_clip.save_frame(RESULT_PATH) # works

concat = concatenate_videoclips([comp_clip], method="compose")
concat.save_frame(RESULT_PATH) # fails

Behaviour

The code will render the image to the specified path but will crash afterwars when trying the same with
the concatenate_videoclips() function.
The error looks like this:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/numpy/core/fromnumeric.py", line 2112, in cumsum
    cumsum = a.cumsum
AttributeError: 'list' object has no attribute 'cumsum'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "moviepy_bug.py", line 21, in <module>
    concat = concatenate_videoclips([comp_clip], method="compose")
  File "/usr/local/lib/python3.5/dist-packages/moviepy-0.2.3.2-py3.5.egg/moviepy/video/compositing/concatenate.py", line 71, in concatenate_videoclips
    tt = np.cumsum([0] + [c.duration for c in clips])
  File "/usr/lib/python3/dist-packages/numpy/core/fromnumeric.py", line 2114, in cumsum
    return _wrapit(a, 'cumsum', axis, dtype, out)
  File "/usr/lib/python3/dist-packages/numpy/core/fromnumeric.py", line 48, in _wrapit
    result = getattr(asarray(obj), method)(*args, **kwds)
TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'

Thoughts

I saw #123, but TextClip does not have a duration afaik. CompositionClips neither. Please tell me if I'm wrong here.

Zulko commented

This is not a rendering bug, it's just that concatenate_videoclip is not meant to accept clips with no duration. Your CompositeClip has no duration because the TextClip is considered infinite, but my guess is that if you give a duration to the CompositeClip it should work:

comp_clip = CompositeVideoClip([image_clip, text_clip]).set_duration(1)

That's right. Thanks. I feel dumb now.
I hope I leave at least a helpful Q&A for someone else ...

We really need to implement a more user friendly error message. May we use your example as a base case for testing?

Accept my humble contribution

Thanks..

ValueError Traceback (most recent call last)
in
----> 1 img = concatenate_videoclips(clips)

~/.local/lib/python3.6/site-packages/moviepy/video/compositing/concatenate.py in concatenate_videoclips(clips, method, transition, bg_color, ismask, padding)
73 sizes = [v.size for v in clips]
74
---> 75 w = max([r[0] for r in sizes])
76 h = max([r[1] for r in sizes])
77

ValueError: max() arg is an empty sequence

I think my current issue might be related to this. Here is what I am trying to do:

from moviepy import *
from moviepy.editor import *

video = VideoFileClip("video_orig.mp4")

txt_clip = (TextClip("Some dummy text",
                              fontsize=70,
                              color='white'
                              )
                  .with_position('center')
                  .with_duration(10)
                  )

I am getting this error:

AttributeError: 'TextClip' object has no attribute 'with_position'

Is this also due to something with duration, or another issue ?

Use set_position and set_duration because you are still on v1.x. They are being renamed in v2.0.