7

I'm using the library moviepy on Linux Mint 18.1.

Specifically, it's moviepy 0.2.3.2 on python 3.5.2

Since I'm getting started, I tried this simple script, which should concatenate two videos one after the other:

import moviepy.editor as mp

video1 = mp.VideoFileClip("short.mp4")
video2 = mp.VideoFileClip("motivation.mp4")

final_video = mp.concatenate_videoclips([video1,video2])
final_video.write_videofile("composition.mp4")

The two videos are short random videos that I downloaded from YouTube. They both play perfectly, both with VLC and the standard video player provided with Linux Mint.

The script runs fine with no errors, with the final message:

[MoviePy] >>>> Building video composition.mp4
[MoviePy] Writing audio in compositionTEMP_MPY_wvf_snd.mp3
100%|██████████████████████████████| 1449/1449 [00:23<00:00, 59.19it/s]
[MoviePy] Done.
[MoviePy] Writing video composition.mp4
100%|██████████████████████████████| 1971/1971 [11:34<00:00,  2.84it/s]
[MoviePy] Done.
[MoviePy] >>>> Video ready: composition.mp4 

The file is indeed created, and it also have a size (about 20 MB). However, when I try to play it, nothing happens: it seems to be corrupted. The standard video player even tells me that "there is no video stream to be played".

If I try to do the same with the interactive console, and use final_video.preview(), I get an AttributeError, along with this traceback:

In [5]: final_video.preview()
Exception in thread Thread-417:
Traceback (most recent call last):
  File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.5/threading.py", line 862, in run
    self._target(*self._args, **self._kwargs)
  File "<decorator-gen-211>", line 2, in preview
  File "/usr/local/lib/python3.5/dist-packages/moviepy/decorators.py", line 54, in requires_duration
    return f(clip, *a, **k)
  File "/usr/local/lib/python3.5/dist-packages/moviepy/audio/io/preview.py", line 49, in preview
    sndarray = clip.to_soundarray(tt,nbytes=nbytes, quantize=True)
  File "<decorator-gen-184>", line 2, in to_soundarray
  File "/usr/local/lib/python3.5/dist-packages/moviepy/decorators.py", line 54, in requires_duration
    return f(clip, *a, **k)
  File "/usr/local/lib/python3.5/dist-packages/moviepy/audio/AudioClip.py", line 107, in to_soundarray
    fps = self.fps
AttributeError: 'CompositeAudioClip' object has no attribute 'fps'

and the video seems frozen at the first frame.

I don't have any clue, since everything seems to work fine (except with the preview, which doesn't work because of the error). I tried to reinstall ffmpeg, but no succes: everything is exactly the same. Without any useful error, I can't figure out how to fix this problem. Can anyone help me?

EDIT: What are the 4 magic letters? R-T-F-M! I solved the problem by setting the kwarg method of mp.concatenate_videoclips to compose, since the original videos have a different frame size.

Russell Teapot
  • 511
  • 1
  • 6
  • 19
  • moviepy version? – sascha Oct 10 '17 at 21:00
  • Interesting. I though it would be [this bug](https://github.com/Zulko/moviepy/issues/407). But you already have some newer version, where this was fixed (v0.2.3.1). Maybe this fix was not enough. So if your videos have different fps; you might check moviepy's sources to see what's going on. Or convert both videos to the same fps before using moviepy (yeah, annoying). – sascha Oct 10 '17 at 21:07
  • pretty close, but the `AttributeError` here is related to `CompositeAudioClip`, not `VideoClip`. In the issue tracker, @zulko states that " `concatenate` will only attribute fps to the final clip if all the clips have the same fps, otherwise it's an ambigous case" and "..make the default fps as the largest fps in the list". This is exactly the behaviour I experience here: one clip has exactly 30.0 fps, the other 29.999..., and if I check `final_video.fps` from the interactive console, I get 30.0 fps. So, this shouldn't be the problem – Russell Teapot Oct 10 '17 at 21:14
  • I would try the same code with two equal-fps inputs. Just for debugging. – sascha Oct 10 '17 at 21:15
  • Ahhh.. too bad, I tried to convert the video using the command `ffmpeg -i -r 30 `, succesfully converting it to 30 fps, but no luck: it's still the same. – Russell Teapot Oct 10 '17 at 21:43

2 Answers2

6

To hopefully figure out what's going on, I decided to take a more systematic approach, following these steps:

  1. Create a virtual environment with no packages other than moviepy and its dependencies
  2. Use videos from a different source
  3. Try different codecs and/or other different parameters
  4. Dig into the source code of moviepy
  5. Sacrifice a goat to the Angel of Light, the Deceiver, the Father of Lies, the Roaring Lion, Son of Perdition Satan Lucifer

In each case I will this script (test.py):

import moviepy.editor as mp

video1 = mp.VideoFileClip("short.mp4")
video2 = mp.VideoFileClip("motiv_30.mp4")

final_video = mp.concatenate_videoclips([video1,video2])
final_video.write_videofile("composition.mp4")

with some minor changes, when needed. I'll update this post as I follow the steps.

1. Create a virtual environment

I created a virtual environment using virtualenv, activated it and installed moviepy with pip. This is the output of pip freeze:

decorator==4.0.11
imageio==2.1.2
moviepy==0.2.3.2
numpy==1.13.3
olefile==0.44
Pillow==4.3.0
tqdm==4.11.2

All with python 3.5.2.

After running test.py, the video is created, with no apparent problems. However, the video can't be played, neither by VLC nor by the default video player of Linux Mint 18.1.

Then, I noticed that mp.concatenate_videoclips has the kwarg method, which is by default set to chain. In the documentation, I read that:

- method="compose", if the clips do not have the same
  resolution, the final resolution will be such that no clip has
   to be resized.

So, I tried to use the kwarg method="compose", since the two videos have different frame sizes and... it worked. I am an idiot. Oh well, no goats for Satan, I suppose. Lesson learned: RTFM

Joshua Wolff
  • 2,687
  • 1
  • 25
  • 42
Russell Teapot
  • 511
  • 1
  • 6
  • 19
  • 1
    I had a different issue: I my rendered video contained parts where is was corrupted,and other parts where it was completely fine. Changing the method to "compose" fixed the issue. Thanks for sharing! – RealA10N Sep 23 '20 at 11:44
  • @RealA10N ahah! Glad it helped! – Russell Teapot Sep 24 '20 at 19:45
2

I was having the same trouble. I fond the solution at https://zulko.github.io/moviepy/FAQ.html It turns out that the video cannot have a odd ratio like 1080 x 351, so you just have to check if it's not even them add ou subtract one from that.