0

I am having a bad time trying to figure out how to write this command in the subprocess.

In the terminal I run :

ffprobe -i test.avi -show_format -v quiet | sed -n 's/duration=//p' | xargs printf %.0f

and it runs fine. Now in the python 3 I want to run it in my code and it gives me an error. I tried

subprocess.call(['ffprobe', '-i', 'test.avi' ,'-show_format', '-v' ,'quiet' ,'|', 'sed' ,'-n' ,'s/duration=//p', '|' ,'xargs printf %.0f']) and

subprocess.run(['ffprobe', '-i', 'test.avi' ,'-show_format', '-v' ,'quiet' ,'|', 'sed' ,'-n' ,'s/duration=//p', '|' ,'xargs printf %.0f']) but none works.

alan
  • 3
  • 1

1 Answers1

0

In terminal, | is used to pipe the output of a program to the input of another.

Your command mean the following flow:

ffmpeg => sed => xargs ( and xargs runs printf for each line of its input separately)

Python can take over the jobs of sed and xargs easily.

You program may become:

import subprocess
import re

# subprocess.run() is usually a better choice
completed = subprocess.run(
    [
        'ffprobe',
        '-i', 'test.avi', '-show_format', '-v', 'quiet',
    ],
    capture_output=True,  # output is stored in completed.stdout
    check=True,  # raise error if exit code is non-zero
    encoding='utf-8',  # completed.stdout is decoded to a str instead of a bytes
)

# regex is used to find the duration
for match in re.finditer(r'duration=(.*)$', completed.stdout):
    duration = float(match.group(1).strip())
    print(f'{duration:.0f}')  # f-string is used to do formatting

If you want to do piping between commands in Python, see How to use `subprocess` command with pipes

Though there is a shell=True argument in subprocess functions, it has security consideration.

Aaron
  • 1,255
  • 1
  • 9
  • 12