Description
When using check_sp_output to capture output from continuous FFmpeg streams (such as live device inputs like ffmpeg -f v4l2 -i /dev/video0), the stream can occasionally freeze. Because the underlying subprocess.communicate() call lacks a timeout parameter, the Python script blocks execution indefinitely and can only be terminated manually via Ctrl+C.
Permalink to the affected code:
|
def check_sp_output(*args: Any, **kwargs: Any) -> bytes: |
|
""" |
|
## check_sp_output |
|
|
|
Returns FFmpeg `stdout` output from subprocess module. |
|
|
|
Parameters: |
|
args (based on input): Non Keyword Arguments |
|
kwargs (based on input): Keyword Arguments |
|
|
|
**Returns:** A string value. |
|
""" |
|
# workaround for python bug: https://bugs.python.org/issue37380 |
|
if platform.system() == "Windows": |
|
# see comment https://bugs.python.org/msg370334 |
|
sp._cleanup = lambda: None |
|
# handle additional params |
|
retrieve_stderr = kwargs.pop("force_retrieve_stderr", False) |
|
# execute command in subprocess |
|
process = sp.Popen( |
|
*args, |
|
stdout=sp.PIPE, |
|
stderr=sp.DEVNULL if not (retrieve_stderr) else sp.PIPE, |
|
**kwargs, |
|
) |
|
# communicate and poll process |
|
output, stderr = process.communicate() |
|
retcode = process.poll() |
|
# handle return code |
|
if retcode and not (retrieve_stderr): |
|
logger.error("[Pipeline-Error] :: {}".format(output.decode("utf-8"))) |
|
cmd = kwargs.get("args") |
|
if cmd is None: |
|
cmd = args[0] |
|
error = sp.CalledProcessError(retcode, cmd) |
|
error.output = output |
|
raise error |
|
# raise error if no output |
|
bool(output) or bool(stderr) or logger.error( |
|
"[Pipeline-Error] :: Pipeline failed to exact any data from command: {}!".format( |
|
args[0] if args else [] |
|
) |
|
) |
|
# return output otherwise |
|
return stderr if retrieve_stderr and stderr else output |
Issue Checklist
Expected behaviour
The check_sp_output function should accept a timeout argument (via kwargs) to prevent indefinite hanging. If the timeout is reached, it should cleanly catch the subprocess.TimeoutExpired exception, terminate the process, flush the remaining buffer, and return the captured output without raising a CalledProcessError.
Actual behaviour
The function delegates to process.communicate() without any time limits. If the FFmpeg process stalls, Python waits forever for the process to terminate.
Steps to reproduce
- Create a Python script that calls check_sp_output with a long-running or potentially blocking FFmpeg command (e.g., using a live input like ffmpeg -f v4l2 -i /dev/video0).
- Interrupt or stall the FFmpeg stream (e.g., disconnect the video device / simulate a hang).
- Observe that the Python process never returns from check_sp_output unless killed.
- Try to pass a timeout argument to check_sp_output (currently unsupported).
- The process should return/timeout gracefully rather than freeze indefinitely.
Terminal log output
Python Code(Optional)
DeFFcode Version
0.2.8
Python version
All
Operating System version
All
Any other Relevant Information?
This is both a bug and a possible enhancement, as resolving this will make DeFFcode more robust for handling real-time streaming inputs and non-blocking system calls.
Description
When using check_sp_output to capture output from continuous FFmpeg streams (such as live device inputs like ffmpeg -f v4l2 -i /dev/video0), the stream can occasionally freeze. Because the underlying subprocess.communicate() call lacks a timeout parameter, the Python script blocks execution indefinitely and can only be terminated manually via Ctrl+C.
Permalink to the affected code:
deffcode/deffcode/ffhelper.py
Lines 640 to 684 in 5162649
Issue Checklist
Expected behaviour
The check_sp_output function should accept a timeout argument (via kwargs) to prevent indefinite hanging. If the timeout is reached, it should cleanly catch the subprocess.TimeoutExpired exception, terminate the process, flush the remaining buffer, and return the captured output without raising a CalledProcessError.
Actual behaviour
The function delegates to process.communicate() without any time limits. If the FFmpeg process stalls, Python waits forever for the process to terminate.
Steps to reproduce
Terminal log output
Python Code(Optional)
DeFFcode Version
0.2.8
Python version
All
Operating System version
All
Any other Relevant Information?
This is both a bug and a possible enhancement, as resolving this will make DeFFcode more robust for handling real-time streaming inputs and non-blocking system calls.