[Python] How to parallelize ffmpeg setPTS filter when using GPU?

Discussão em 'Python' iniciado por Stack, Fevereiro 28, 2025.

  1. Stack

    Stack Membro Participativo

    We have a long python code which chunks the video into multiple parts and changes the speed using setPTS filter.

    import ffmpeg
    ffmpeg.input(segment_path).filter("setpts", f"{1/speed_factor}*PTS").output(
    adjusted_segment_path,vcodec="h264_nvenc", acodec="aac",preset="fast", crf=23, g=30, keyint_min=30, sc_threshold=0,r=30,vsync='cfr',threads=1
    ).global_args("-hwaccel", "cuda").run(quiet=True, overwrite_output=True,capture_stdout=True, capture_stderr=True)


    Now, because this happens multiple times before concatenation, we thought, instead of sequential processing using a ThreadPool, it may help reduce the time. So we did that:

    import ffmpeg
    import concurrent.futures

    def process_video(segment_path, adjusted_segment_path, speed_factor):
    ffmpeg.input(segment_path).filter("setpts", f"{1/speed_factor}*PTS").output(
    adjusted_segment_path,
    vcodec="h264_nvenc",
    acodec="aac",
    preset="fast",
    crf=23,
    g=30,
    keyint_min=30,
    sc_threshold=0,
    r=30,
    vsync='cfr',
    threads=1
    ).global_args("-hwaccel", "cuda").run(
    quiet=True, overwrite_output=True, capture_stdout=True, capture_stderr=True
    )


    segment_paths = ["input1.mp4", "input2.mp4", "input3.mp4"] # List of input video segments
    output_paths = ["output1.mp4", "output2.mp4", "output3.mp4"] # Corresponding output paths
    speed_factor = 1.5

    # Using ThreadPoolExecutor for concurrent processing
    with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
    futures = [
    executor.submit(process_video, seg, out, speed_factor)
    for seg, out in zip(segment_paths, output_paths)
    ]

    # Wait for all tasks to complete
    for future in concurrent.futures.as_completed(futures):
    try:
    future.result() # This will raise any exceptions encountered in the thread
    except Exception as e:
    print(f"Error processing video: {e}")


    But the time required did not reduce. Previously, it was 50 seconds for a long video input, now too, it remains the same.

    Is there any other way I can improve the code?

    I also noticed the GPU utilization is low and the code is still executed sequentially (I can see when I run nvtop, which processes are running)

    I am using an L4 GPU with CUDA Version: 12.4, nvcc CUDA Toolkit is also at 12.4

    Continue reading...

Compartilhe esta Página