I'm trying to write a gui for FFMPEG
. I'm using pythons subprocess to create a ffmpeg process for every conversion I want. This works fine, but I'd also like a way to get the progress of the conversion, whether it failed or not etc. I figured I could do this by accessing the process's stdout like so:
Calling subprocess.Popen()
# Convert - Calls FFMPEG with current settings. (in a seperate
# thread.)
def convert(self):
# Check if options are valid
if self.input == "" or self.output == "":
return False
# Make the command string
ffmpegString = self.makeString()
# Try to open with these settings
try:
self.ffmpeg = subprocess.Popen(ffmpegString, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
except OSError:
self.error.append("OSError: ")
except ValueError:
self.error.append("ValueError: Couldn't call FFMPEG with these parameters")
# Convert process should be running now.
And reading stdout
:
convert = Convert()
convert.input = "test.ogv"
convert.output = "test.mp4"
convert.output_size = (0, 0)
convert.convert()
while 1:
print convert.ffmpeg.stdout.readline()
This works but, ffmpeg's status doesn't show. I'm assuming it has something to do with way ffmpeg refreshes it. Is there a way to access it?
Simply add ,universal_newlines=True to your subprocess.Popen line.
For now you got line in cycle like:
Use the time= value to determine progress in percentage.
Since ffmpeg writes the data unflushed to stderr you have to set the stderr file descriptor to non-blocking using fcntl.
and then loop using select to read the data
for full example go here.
I've often noticed problems reading standard output (or even standard error!) with subprocess, due to buffering issues that are hard to defeat. My favorite solution, when I do need to read such stdout/stderr from the subprocess, is to switch to using, instead of
subprocess
,pexpect
(or, on Windows,wexpect
).I think you can't use readline because ffmpeg never prints one line, the status is updated by writing \r (carrige return) and then writing the line again.
If you examine the row above you'll notice that there is only one \n and that gets printed when the file is done converting.
FFMPEG:
FFMPEG output all the status text (what you see when you run it manually on the command line) on the stderr interface. In order to capture output from ffmpeg, you need to be watching the stderr interface - or redirecting it like the example.
Check for output on stderr:
Here is another way to try and read from stderr, instead of redirecting it when calling Popen
The Popen class in Python has an file object called stderr, you would access it in the same way that you are accessing stdout. I'm thinking your loop would look something like this:
Disclaimer: I haven't tested this in Python, but I made a comparable application using Java.