14

I'm trying to use subprocess.Popen to construct a sequence to grab the duration of a video file. I've been searching for 3 days, and can't find any reason online as to why this code isn't working, but it keeps giving me a blank result:

import sys
import os
import subprocess

def main():
  the_file = "/Volumes/Footage/Acura/MDX/2001/Crash Test/01 Acura MDX Front Crash.mov"
  ffmpeg = subprocess.Popen(['/opt/local/bin/ffmpeg', '-i', the_file], stdout = subprocess.PIPE, )
  grep = subprocess.Popen(['grep', 'Duration'], stdin = subprocess.PIPE, stdout = subprocess.PIPE, )
  cut = subprocess.Popen(['cut', '-d', ' ', '-f', '4'], stdin = subprocess.PIPE, stdout = subprocess.PIPE, )
  sed = subprocess.Popen(['sed', 's/,//'], stdin = subprocess.PIPE, stdout = subprocess.PIPE, )

  duration = sed.communicate()
  print duration

if __name__ == '__main__':
  main()
2
  • 5
    Why are you using grep, cut and sed to parse the output instead of using builtin Python functions? Commented Mar 22, 2010 at 16:35
  • 1
    subprocess.PIPE is your enemy Commented Feb 19, 2015 at 12:15

4 Answers 4

25

As others have pointed out, you need to pass the PIPE from one process to the next. The stdout (PIPE) from one process becomes the stdin for the following task.

Something like this (starting from your example):

import sys
import os
import subprocess

def main():
  the_file = "/Volumes/Footage/Acura/MDX/
              2001/Crash Test/01 Acura MDX Front Crash.mov"
  ffmpeg = subprocess.Popen(['/opt/local/bin/ffmpeg', '-i', the_file],
                            stdout = subprocess.PIPE)
  grep = subprocess.Popen(['grep', 'Duration'], 
                          stdin = ffmpeg.stdout, stdout = subprocess.PIPE)
  cut = subprocess.Popen(['cut', '-d', ' ', '-f', '4'],
                         stdin = grep.stdout, stdout = subprocess.PIPE)
  sed = subprocess.Popen(['sed', 's/,//'],
                         stdin = cut.stdout, stdout = subprocess.PIPE)

  duration = sed.communicate()[0]
  print duration

if __name__ == '__main__':
  main()
Sign up to request clarification or add additional context in comments.

2 Comments

I'd consider this the correct answer, it answers exactly what OP asked and isn't instructing on how you could work around it.
There is a pipes module nowadays: docs.python.org/3/library/…
15

stderr needs to be redirected to stdout. Also, there's no need to call other tools like cut/sed etc. do your string manipulation in Python

import subprocess
....
the_file = "/Volumes/Footage/Acura/MDX/2001/Crash Test/01 Acura MDX Front Crash.mov"
ffmpeg = subprocess.Popen(['/usr/bin/ffmpeg', '-i', the_file], stderr=subprocess.STDOUT,stdout = subprocess.PIPE )
out, err = ffmpeg.communicate()
if "Duration" in out:
    print out[out.index("Duration"):].split()[1]

If Python is not a must, you can use the shell directly.

the_file="/Volumes/Footage/Acura/MDX/2001/Crash Test/01 Acura MDX Front Crash.mov"
ffmpeg -i "$file" 2>&1 | awk '/Duration/{print $2}'

1 Comment

Thank you. I didn't realize I had to redirect stderr as well.
14

Using subprocess.PIPE will not magically wire the correct pipes for you.

You must pass the output pipe of the first process as the value for the parameter stdin of the second process. See the docs for an example.

Comments

4

Python can't "build a whole pipeline" in this way -- it could delegate the task to the shell, or glue it up more directly using the stdout attributes of previous subprocess objects in the line, but there's really no reason for that in this specific case, since you can code it directly in Python pretty easily. E.g.:

  ffmpeg = subprocess.Popen(['/opt/local/bin/ffmpeg', '-i', the_file],
                            stdout=subprocess.PIPE)
  for line in ffmpeg.stdout:
    if 'Duration' not in line: continue
    fields = line.split()
    duration = fields[4].replace(',', '')
    break

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.