Getting realtime output from ffmpeg to be used in progress bar (PyQt4, stdout) Getting realtime output from ffmpeg to be used in progress bar (PyQt4, stdout) python python

Getting realtime output from ffmpeg to be used in progress bar (PyQt4, stdout)


In this specific case for capturing ffmpeg's status output (which goes to STDERR), this SO question solved it for me: FFMPEG and Pythons subprocess

The trick is to add universal_newlines=True to the subprocess.Popen() call, because ffmpeg's output is in fact unbuffered but comes with newline-characters.

cmd = "ffmpeg -i in.mp4 -y out.avi"process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,universal_newlines=True)for line in process.stdout:    print(line)

Also note that in this code sample the STDERR status output is directly redirected to subprocess.STDOUT


The only way I've found to get dynamic feedback/output from a child process is to use something like pexpect:

#! /usr/bin/pythonimport pexpectcmd = "foo.sh"thread = pexpect.spawn(cmd)print "started %s" % cmdcpl = thread.compile_pattern_list([pexpect.EOF,                                   'waited (\d+)'])while True:    i = thread.expect_list(cpl, timeout=None)    if i == 0: # EOF        print "the sub process exited"        break    elif i == 1:        waited_time = thread.match.group(1)        print "the sub process waited %d seconds" % int(waited_time)thread.close()

the called sub process foo.sh just waits a random amount of time between 10 and 20 seconds, here's the code for it:

#! /bin/shn=5while [ $n -gt 0 ]; do    ns=`date +%N`    p=`expr $ns % 10 + 10`    sleep $p    echo waited $p    n=`expr $n - 1`done

You'll want to use some regular expression that matches the output you're getting from ffmpeg and does some kind of calculation on it to show the progress bar, but this will at least get you the unbuffered output from ffmpeg.


  1. Calling from the shell is generally not required.
  2. I know from experince that part of the ffmpeg output comes on stderr, not stdout.

If all you want to do is print the output line, like in your example above, then simply this will do:

import subprocesscmd = 'ffmpeg -i file.mp4 file.avi'args = cmd.split()p = subprocess.Popen(args)

Note that the line of ffmpeg chat is terminated with \r, so it will overwrite in the same line! I think this means you can't iterate over the lines in p.stderr, as you do with your rsync example. To build your own progress bar, then, you may need to handle the reading yourself, this should get you started:

p = subprocess.Popen(args, stderr=subprocess.PIPE)while True:  chatter = p.stderr.read(1024)  print("OUTPUT>>> " + chatter.rstrip())