Marino Linaje
Marino Linaje

Reputation: 612

subprocess.run output is empty (python 3.8)

I'm trying to capture the output of a command with the following code:

lines = subprocess.run(['ffmpeg', '-hide_banner', '-nostats', '-i', in_filename, '-vn', '-af', 'silencedetect=n={}:d={}'.format(silence_threshold, silence_duration), '-f', 'null', '-'], capture_output=True, text=True, shell=True, check=True, encoding='utf-8').stdout 
print (lines)

But lines is an empty string and nothing is printed. When capture_output=True is removed, the correct output is showed (without printing it).

I tested many combinations, including removing all the subprocess.run parameters and only include capture_output=True with the same result.

I also tested with few argument for a minimal example: subprocess.run(['ffmpeg', '-version'], capture_output=True, text=True, shell=True, check=True, encoding='utf-8').stdout

Also tested stdout=subprocess.PIPE and stderr=subprocess.PIPE as subprocess.run arguments instead of capture_output=True

I can't figure out what is happening. Thanks in advance!

Upvotes: 6

Views: 2111

Answers (1)

Veysel Olgun
Veysel Olgun

Reputation: 598

By default ffmpeg logs to stderr. You use capture_output=True, so run() func will capture stdout and stderr values

Q-1) Lines is an empty string and nothing is printed.

A-1) This is normal because ffmpeg not log to stdout by default.

Q-2) When capture_output=True is removed, the correct output is showed (without printing it).

A-2) This is what we expected, when you remove capture_output=True then ffmpeg logs to stderr (to your terminal/console by default) and you will see ffmpeg output on the screen(stdin,stdout,and stderr these are typically attached to the user's terminal). When you use capture_output=True, ffmpeg's logs go to the kernel pipe file-like object in the RAM (In Unix and Linux, no knowledge about windows). That's why you don't see any output in the terminal/console without print()'ing the captured stdout

subprocess.run() func will return CompletedProcess(process.args, retcode, stdout, stderr) instance and you can get stdout attribute's value but we don't need this, we need stderr attribute's value because ffmpeg logs to stderr by default as i said above.

You need to modify it like ;

lines = subprocess.run(['ffmpeg', '-hide_banner', '-nostats', '-i', in_filename, '-vn', '-af', 'silencedetect=n={}:d={}'.format(silence_threshold, silence_duration), '-f', 'null', '-'], capture_output=True, text=True, shell=True, check=True, encoding='utf-8').stderr
print (lines)

Upvotes: 3

Related Questions