从 ffmpeg 获取实时输出以在进度条中使用(PyQt4,stdout)
问题描述
我已经查看了许多问题,但仍然无法完全弄清楚这一点.我正在使用 PyQt,并希望运行 ffmpeg -i file.mp4 file.avi
并在流式传输时获取输出,以便创建进度条.
I've looked at a number of questions but still can't quite figure this out. I'm using PyQt, and am hoping to run ffmpeg -i file.mp4 file.avi
and get the output as it streams so I can create a progress bar.
我查看了以下问题:ffmpeg可以显示进度条吗?从子进程实时捕获标准输出
我可以看到 rsync 命令的输出,使用以下代码:
I'm able to see the output of a rsync command, using this code:
import subprocess, time, os, sys
cmd = "rsync -vaz -P source/ dest/"
p, line = True, 'start'
p = subprocess.Popen(cmd,
shell=True,
bufsize=64,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)
for line in p.stdout:
print("OUTPUT>>> " + str(line.rstrip()))
p.stdout.flush()
但是当我将命令更改为 ffmpeg -i file.mp4 file.avi
时,我没有收到任何输出.我猜这与标准输出/输出缓冲有关,但我不知道如何读取看起来像
But when I change the command to ffmpeg -i file.mp4 file.avi
I receive no output. I'm guessing this has something to do with stdout / output buffering, but I'm stuck as to how to read the line that looks like
frame= 51 fps= 27 q=31.0 Lsize= 769kB time=2.04 bitrate=3092.8kbits/s
我可以用它来计算进度.
Which I could use to figure out progress.
有人可以告诉我一个例子,说明如何使用或不使用 PyQt(如果可能的话)将这些信息从 ffmpeg 获取到 python 中
Can someone show me an example of how to get this info from ffmpeg into python, with or without the use of PyQt (if possible)
我最终选择了 jlp 的解决方案,我的代码如下所示:
I ended up going with jlp's solution, my code looked like this:
#!/usr/bin/python
import pexpect
cmd = 'ffmpeg -i file.MTS file.avi'
thread = pexpect.spawn(cmd)
print "started %s" % cmd
cpl = thread.compile_pattern_list([
pexpect.EOF,
"frame= *d+",
'(.+)'
])
while True:
i = thread.expect_list(cpl, timeout=None)
if i == 0: # EOF
print "the sub process exited"
break
elif i == 1:
frame_number = thread.match.group(0)
print frame_number
thread.close
elif i == 2:
#unknown_line = thread.match.group(0)
#print unknown_line
pass
给出这个输出:
started ffmpeg -i file.MTS file.avi
frame= 13
frame= 31
frame= 48
frame= 64
frame= 80
frame= 97
frame= 115
frame= 133
frame= 152
frame= 170
frame= 188
frame= 205
frame= 220
frame= 226
the sub process exited
完美!
解决方案
我发现从子进程获取动态反馈/输出的唯一方法是使用 pexpect 之类的东西:
The only way I've found to get dynamic feedback/output from a child process is to use something like pexpect:
#! /usr/bin/python
import pexpect
cmd = "foo.sh"
thread = pexpect.spawn(cmd)
print "started %s" % cmd
cpl = 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()
被调用的子进程 foo.sh 只是等待 10 到 20 秒之间的随机时间,这是它的代码:
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/sh
n=5
while [ $n -gt 0 ]; do
ns=`date +%N`
p=`expr $ns % 10 + 10`
sleep $p
echo waited $p
n=`expr $n - 1`
done
您需要使用一些与您从 ffmpeg 获得的输出相匹配的正则表达式,并对其进行某种计算以显示进度条,但这至少可以让您获得 ffmpeg 的无缓冲输出.
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.
相关文章