2

I'm working on something that concatenate videos and adds some titles on through moviepy.

As I saw on the web and on my on pc moviepy works on the CPU and takes a lot of time to save(render) a movie. Is there a way to improve the speed by running the writing of moviepy on GPU? Like using FFmpeg or something like this?

I didn't find an answer to that on the web, so I hope that some of you can help me. I tried using thread=4 and thread=16 but they are still very very slow and didn't change much.

My CPU is very strong (i7 10700k), but still, rendering on moviepy takes me for a compilation with a total of 8 minutes 40 seconds, which is a lot.

Any ideas?Thanks! the code doesnt realy matter but :

def Edit_Clips(self):

    clips = []

    time=0.0
    for i,filename in enumerate(os.listdir(self.path)):
        if filename.endswith(".mp4"):
            tempVideo=VideoFileClip(self.path + "\\" + filename)

            txt = TextClip(txt=self.arrNames[i], font='Amiri-regular',
                           color='white', fontsize=70)
            txt_col = txt.on_color(size=(tempVideo.w + txt.w, txt.h - 10),
                                   color=(0, 0, 0), pos=(6, 'center'), col_opacity=0.6)

            w, h = moviesize = tempVideo.size
            txt_mov = txt_col.set_pos(lambda t: (max(w / 30, int(w - 0.5 * w * t)),
                                                 max(5 * h / 6, int(100 * t))))

            sub=txt_mov.subclip(time,time+4)
            time = time + tempVideo.duration

            final=CompositeVideoClip([tempVideo,sub])

            clips.append(final)

    video = concatenate_videoclips(clips, method='compose')
    print("after")
    video.write_videofile(self.targetPath+"\\"+'test.mp4',threads=16,audio_fps=44100,codec = 'libx264')
Shenhav Mor
  • 23
  • 1
  • 6
  • Can you please post your code? – jkr Sep 10 '20 at 20:56
  • Posted a code jakub – Shenhav Mor Sep 10 '20 at 21:14
  • I see `os.listdir()` - how many files .mp4 do you have in file? Maybe you should use `subprocess` to runs many files at the same time ? – furas Sep 11 '20 at 01:17
  • i have between 15-25 – Shenhav Mor Sep 11 '20 at 11:29
  • i use it so i can take all the videos from a directory but i dont run them at the same time i concatnate them – Shenhav Mor Sep 11 '20 at 11:29
  • High quality-per-bitrate video encoding is *very* CPU intensive, especially x265; but x264 `-preset slower` is fairly usable. That's pretty much unavoidable, unless you want to consider lower video-quality options like hardware encoders built in to your GPU. (These days they might not be too bad, especially if you don't mind throwing lots of bitrate at it, but if you want to archive your results, quality-per-bitrate is important for disk space. If you're going to upload to youtube or something, they'll transcode anyway so use plenty of bitrate for that.) – Peter Cordes Jul 20 '22 at 22:24

4 Answers4

6

I was able to significantly speed things up by trying different encoders.

You can type in the following command to get a list on your system:

ffmpeg -encoders

Then you can try each codec to see which one gives you the best result:

final.write_videofile(
        filename,
        threads=5,
        bitrate="2000k",
        audio_codec="aac",
        codec="h264_videotoolbox",
    )

For me h264_videotoolbox worked the best, but your system may be different. To my understanding you would have h264_nvenc if you were on an nvidia system.

Rob
  • 7,028
  • 15
  • 63
  • 95
2

I am using a GTX3070 on Windows and the h264_nvenc codec allowed me to use my GPU. clip.write_videofile(video_file, codec='h264_nvenc')

Kurt
  • 31
  • 1
  • 2
1

in the past I was same problem and I solved that.

You need to use this command in your code ONLY one time.

video = CompositeVideoClip([clip1, clip2, clip3])

and export the video:

video.write_videofile(path_final_video)

while the video is export, moviepy will use all your cores.

Hope I helped :)

Idan Cohen
  • 104
  • 2
0

My gpu type is nvida, and I got 10 times faster with this command. you can try this:

echo y|ffmpeg -r 25 -i "a.mkv" -vcodec h264_nvenc "b.mp4"

If that not work, you can try else gpu accelerators:

-vcodec [accelerator_type]
# h264_nvenc
# hevc
# hevc_nvenc
# libx265

Run call in python(win 10):

input = 'a.mkv'
output = 'b.mp4'

call = "echo y|ffmpeg -r 25 -i \"%s\" -vcodec h264_nvenc  \"%s\"" % (input, output)
call

import os
os.system(call)

# subprocess.call or os.popen can get the call's return, 
# but if you want get the return at the same time,
# you should use this way:
import subprocess
pi= subprocess.Popen(call,shell=True,stdout=subprocess.PIPE)
for i in iter(pi.stdout.readline,'b'):
    print(i)

But this way is not work on moviepy's concat function because it's not support GPU. u'd better use ffmpeg to connact clips.

# concat_ffmpeg.bat
echo y|ffmpeg -i 1.mkv  -qscale 4 1.mpg
echo y|ffmpeg -i 2.mkv  -qscale 4 2.mpg
echo y|ffmpeg -i "concat:1.mpg|2.mpg" -c copy output.mp4

## sometimes can't use the [-c copy], u can try this and use GPU: 
# echo y|ffmpeg -i "concat:1.mpg|2.mpg" -vcodec h264_nvenc output.mp4

or Concatenating media files.

Reference:

How can I speed up moviepy by gpu? #923

ffmpeg 4.0 NVIDIA NVDEC-accelerated Support ? #790

bode liang
  • 119
  • 3
  • but where do i add it ? because i run my program like "python main.py" so where do i add this command – Shenhav Mor Sep 20 '20 at 22:55
  • you can use the `call = 'command'`, then `import os; os.system(call)` – bode liang Sep 21 '20 at 19:28
  • Why would you transcode both `.mkv` files to MPEG-2 / MPEG-1 `.mpg`? That's an ancient codec much worse than x264 or other h.264 encoders, let alone h.265 or VP9. FFmpeg can concat two different input files to a single encode into a `.mp4` or `.mkv`. [How to concatenate two MP4 files using FFmpeg?](https://stackoverflow.com/q/7333232) shows how, including with inputs where the inputs are different formats or even resolutions and need rescaling or filtering. You can use that with a standard `-c:v libx264 -preset slow -crf 22 -c:a libopus -b:a 80k output.mkv` to get good quality-per-bitrate. – Peter Cordes Jul 20 '22 at 22:31
  • re: quality per bitrate: see [Why does preset "veryfast" in FFmpeg generate the most compressed file compared to all other presets?](https://superuser.com/a/1557090) – Peter Cordes Jul 20 '22 at 22:32