Moviepy: ffmpeg_extract_subclip returns black frames

Created on 24 Mar 2017  路  15Comments  路  Source: Zulko/moviepy

I am trying to extract particular sub clips from videos and I see that when the duration of the sub clip is shorter (around 2- 3 seconds), only black frames are seen in the subclip. I guess this might be because ffmpeg is unable to locate the key frames. How do I deal with this?

3rd-party bug

All 15 comments

Hey - That's not enough informations and I've never seen this before, can you provide some code to reproduce the issue ? (and possibly a videofile for which the issue exists too)

Hi, I recreated the issue using this gist https://gist.github.com/ksharsha/f28ca2f019070389c38741fb90a077d1 . I am attaching the video file as well. You can see that the audio is still preserved however, the video is completely blank. This is the video that I am trying to extract the subclip from (tstart = 12.334277199999999, tend = 15.97166675). This is the video https://www.youtube.com/watch?v=a-6lVnhqU4w
Videos.zip

It seems like this might help..
https://trac.ffmpeg.org/wiki/Seeking

when I try what is recommended by this link, I do get video, but the video seems to be a bit messed up (like a bad key frame). I'm not very good with ffmpeg, so maybe someone else sees a solution?

@earney true, the problem is with this cmd = [get_setting("FFMPEG_BINARY"),"-y",
"-i", filename,
"-ss", "%0.2f"%t1,
"-t", "%0.2f"%(t2-t1),
"-vcodec", "copy", "-acodec", "copy", targetname]
I am not good with ffmpeg either but looks like the above cmd has to be changed.

Is this issue resolved? Is there any other way instead of using ffmpeg_extract_subclip to clip videos?

Looks like PR #579 could fix this.

Hi !

There is https://github.com/Zulko/moviepy/pull/848 which is quite clear and well-documented. It seems if fell unoticed, but it does fix this issue, in a better way than #579. (It might not be THE universal fix but it seems very correct)

It would be cool if it could get merged soon :) this issue is getting old, and remains kinda annoying :smile:

Regards

Updating to say I believe this may still be a problem. Using ffmpeg_extract_subclip for 2-3 second clips and continue to run into this issue. As far as I can tell, the only way to get the frame back is removing the copy/encode options, but this reduces the picture in quality.

@ebenz99 Should we reopen this issue?

Up to you. I ended up just using the workaround I mentioned (removing some options and taking a quality hit), but it might be nice to not have to do that.

This is an issue for me, I'm using moviepy to automate the refining of a machine learning dataset and the samples need all the quality it can get.

Even with the quality hit, I'm not sure how to remove the copy/encode options, as I'm not passing any copy/encode options to ffmpeg_extract_subclip()

Any update on this issue @jeff-hykin ?? I am in the very same position as you were back at the time that you commented on this

Which options did you remove @ebenz99 ??

Because most of my time segments were tiny (less than 1 second), and I couldn't sacrifice on quality, I currently use opencv to load all of the frames, skip to the needed subsection, pull out all the frames, and then create a new video with those frames.

My older method was a direct call to ffmpeg. I gave up on the movie.py library

from subprocess import call,run
from pathlib import Path
import os

def cut_video(source, start, end, output_path, hide_errors=False, errors_to_ignore=None):
    """
    Example:
        exit_code, stdout, stderr = cut_video(source="./myvid.mp4", start=30, end=60, output_path="./myvid_30to60.mp4")

    Note:
        - this will not modify the existing video
        - this was tested with ffmpeg 4.3.1

    Args:
        source: filepath to the video
        start: seconds (float or int)
        end: seconds (float or int)
        output_path: filepath to new clip
        hide_errors: print or dont print stderr
        errors_to_ignore: list of strings, if string is in the stderr the stderr wont be printed

    Returns:
        (exit_code, stdout, stderr)

    Raises:
        Exception: "End time is before start time for "+source
        Exception: "When calling cut_video() it seems ffmpeg is not installed (or not on the path). This was called with "+source
        Exception: "When calling cut_video() it seems the video didn't exist as a file: "+source
    """
    errors_to_ignore = [] if errors_to_ignore is None else errors_to_ignore
    duration = end - start
    # check start/end
    if duration <= 0:
        raise Exception("End time is before start time for "+source)
    # make sure ffmpeg exists (only check once per python process)
    if globals().get("__ffpeg_exists", False):
        command_output = run(["ffmpeg", "-version",], capture_output=True)
        stdout = str(command_output.stdout.decode('UTF-8'))
        if "ffmpeg version" in stdout:
            globals()["__ffpeg_exists"] = True
        else:
            raise Exception("When calling cut_video() it seems ffmpeg is not installed (or not on the path). This was called with "+source)
    # make sure the video exists
    if not os.path.isfile(source):
        raise Exception("When calling cut_video() it seems the video didn't exist as a file: "+source)

    # touch the original video so that the file system knows it has been used recently
    Path(source).touch()

    # 
    # actually run the command
    # 
    command_output = run(["ffmpeg", "-i", str(source), "-ss", str(start), "-t", str(duration), "-async", "1", str(output_path), "-hide_banner", "-loglevel", "panic"], capture_output=True)

    # process the output
    exit_code = command_output.exit_code
    stdout = str(command_output.stdout.decode('UTF-8'))
    stderr = str(command_output.stderr.decode('UTF-8'))
    if not hide_errors and len(stderr) != 0:
        common_errors = [ common_error for common_error in errors_to_ignore if common_error in stderr ]
        if len(common_errors) == 0:
            print('ffmpeg inside cut_video(source='+str(source)+') produced some errors:')
            print(stderr)

    return exit_code, stdout, stderr

Reopening because several people commented since close / problem persists.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Netherdrake picture Netherdrake  路  4Comments

Gicehajunior picture Gicehajunior  路  3Comments

skizzy picture skizzy  路  3Comments

bilel picture bilel  路  4Comments

tburrows13 picture tburrows13  路  3Comments