[Python] Minimizing video export time in Moviepy

Discussão em 'Python' iniciado por Stack, Junho 7, 2025.

  1. Stack

    Stack Membro Participativo

    I'm trying to export videos programmatically using Moviepy. The code below generates a video from input in the form of audio and image, and adds a zoom-out effect.

    I'm using this program to generate very long (2.5+ h) videos and I'm looking to speed up the export. What are some ideas for achieving this? Thanks!

    Moviepy version is 2.1.2 Pillow version is 9.5.0

    # import
    import math
    import numpy

    from PIL import Image

    from moviepy import AudioFileClip, ImageClip, CompositeVideoClip
    from moviepy.audio.fx import MultiplyVolume
    from moviepy.video.fx import FadeOut


    def generate_video(video_folder_path, audio_file_path, image_file_path, temp_path):

    # define zoom effect function
    def zoom_effect(clip, zoom_ratio=1.2):
    def effect(get_frame, t):
    img = Image.fromarray(get_frame(t))
    base_size = img.size

    new_size = [
    math.ceil(img.size[0] * zoom_ratio * 1 / (1 - (t / clip.duration) * (1 - zoom_ratio))),
    math.ceil(img.size[1] * zoom_ratio * 1 / (1 - (t / clip.duration) * (1 - zoom_ratio)))
    ]

    img = img.resize(new_size, Image.LANCZOS)

    x = math.ceil((new_size[0] - base_size[0]) / 2)
    y = math.ceil((new_size[1] - base_size[1]) / 2)

    img = img.crop([
    x, y, new_size[0] - x, new_size[1] - y
    ]).resize(base_size, Image.LANCZOS)

    result = numpy.array(img)
    img.close()

    return result

    return clip.transform(effect)

    # define export settings
    audio_volume = 1
    aspect_ratio = 16 / 9
    z_ratio = 1.18
    fade_out_duration = 1.15
    export_fps = 24

    # create clips
    audio_clip = AudioFileClip(audio_file_path).with_effects([MultiplyVolume(audio_volume)])
    image_clip = ImageClip(image_file_path, duration=audio_clip.duration).with_position(('center', 'center'))

    # set dimensions
    height = image_clip.size[1]
    width = int(height * aspect_ratio)

    # apply zoom effect
    image_clip = zoom_effect(image_clip, z_ratio)

    # compose
    video_clip = CompositeVideoClip([image_clip], size=(width, height)).with_effects([FadeOut(fade_out_duration)])

    # set audio
    video_clip.audio = audio_clip

    # write
    video_clip.write_videofile(
    video_folder_path + '/main_video.mp4', fps=export_fps,
    temp_audiofile_path=temp_path, preset='ultrafast', threads=18)



    Then, the function runs inside a for loop for every subdirectory in a directory:

    for video_folder in sorted([f for f in os.scandir('path/to/directory')
    if os.path.isdir(f)], key=lambda x: id_to_num(x.name)):
    generate_video(video_folder.path)



    I have tried different options for the parameters "preset" and "threads" in write_videofile. I'm guessing there is room for improvement with the zoom effect. Disabling the zoom effect results in circa 23 it/s increase. The rate is about 24 it/s with the zoom enabled.

    Continue reading...

Compartilhe esta Página