Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

quiet mode for run_async method might cause ffmpeg process to stick. #195

Closed
ArchieMeng opened this issue Apr 19, 2019 · 9 comments · Fixed by #417
Closed

quiet mode for run_async method might cause ffmpeg process to stick. #195

ArchieMeng opened this issue Apr 19, 2019 · 9 comments · Fixed by #417

Comments

@ArchieMeng
Copy link

What I experienced

Recently, I was using this module in my project for decoding video into pipe as well as encoding target frames into a result video.
But I found that setting the parameter "quiet" of the encoder process to True (which set both stdout and stderr to PIPE) will cause the ffmpeg process to stick at some stage ( and in this case, I cannot write anything into its stdin). If I leave "quiet" to default or set both pipe_stdout and pipe_stderr to False, everything goes well.

What I tried

I tried to edit the run_async function, changing it from

args = compile(stream_spec, cmd, overwrite_output=overwrite_output)
    stdin_stream = subprocess.PIPE if pipe_stdin else None
    stdout_stream = subprocess.PIPE if pipe_stdout or quiet else None
    stderr_stream = subprocess.PIPE if pipe_stderr or quiet else None
    return subprocess.Popen(
        args, stdin=stdin_stream, stdout=stdout_stream, stderr=stderr_stream)

to

 args = compile(stream_spec, cmd, overwrite_output=overwrite_output)
    stdin_stream = subprocess.PIPE if pipe_stdin else None
    stdout_stream = subprocess.PIPE if pipe_stdout else None
    stderr_stream = subprocess.PIPE if pipe_stderr else None
    if quiet:
        stdout_stream = stderr_stream = subprocess.DEVNULL
    return subprocess.Popen(
        args, stdin=stdin_stream, stdout=stdout_stream, stderr=stderr_stream)

Then, using this modified version of ffmpeg-python in my project, it works without any problems.

After all, I don't think this issue is solved, for it will stick again if setting either pipe_stdout or pipe_stderr (I confirmed).

My forked version works. Should I make a pull request? Or do it only when we find the real reason for this issue.

@RZinman
Copy link

RZinman commented Aug 9, 2020

The issue seems to be that pipe buffers are finite in size, so they fill up and eventually block. One workaround when running asynchronously is to just read() from the output pipes periodically. E.g., if you have a loop where you're feeding frames to stdin:

process = (
    ffmpeg
    .input('pipe:', format='rawvideo', pix_fmt='rgb24', s='{}x{}'.format(width, height))
    .output(video_file_out, pix_fmt='yuv420p')
    .run_async(pipe_stdin=True, quiet=True)
)

# Set non-blocking in case we don't get output for a frame
fcntl.fcntl(process.stderr, fcntl.F_SETFL, os.O_NONBLOCK)

for frame in my_frames:
    process.stdin.write(frame)
    
    # Do a read to clear the output pipe
    process.stderr.read()

But this is a bit hacky and relies on ffmpeg not producing too much output to stderr in one frame. I'd like it if the pipe_stdout and pipe_stderr arguments could take subprocess pipes directly. E.g., run_async(pipe_stdout=subprocess.PIPE, pipe_stderr=subprocess.DEVNULL).

@lcytzk
Copy link

lcytzk commented Aug 20, 2020

same problem

@0x3333
Copy link
Contributor

0x3333 commented Sep 4, 2020

Same issue.

@depau depau closed this as completed in #417 Dec 6, 2020
depau added a commit that referenced this issue Dec 6, 2020
Fix issue #195. Redirect stdout/err to /dev/null
@joeyballentine
Copy link

I do not think this issue was fixed. I am still running into it myself.

@ArchieMeng
Copy link
Author

ArchieMeng commented Oct 18, 2022

I do not think this issue was fixed. I am still running into it myself.

That's the reason why I am still using the modified ffmpeg-python of my own. :)

@joeyballentine
Copy link

Ahhh... Is that published to pypi?

@ArchieMeng
Copy link
Author

ArchieMeng commented Oct 18, 2022

Ahhh... Is that published to pypi?

No. It is still a forked ffmpeg-python repo. And since I have been away from such stuff for a long time, it is out of date with the repo now.

@ShirAmir
Copy link

ShirAmir commented Jul 2, 2024

is this planned to be integrated?

@ShirAmir
Copy link

ShirAmir commented Jul 3, 2024

This workaround worked for me:

#68 (comment)

(
    ffmpeg
    .input(in_filename, ss=time)
    .output(out_filename, vframes=1)
    .global_args('-loglevel', 'error')
    .global_args('-y')
    .run()
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants