从ffmpeg获取实时输出,用于进度条(PyQt4,stdout) [英] Getting realtime output from ffmpeg to be used in progress bar (PyQt4, stdout)

查看:6213
本文介绍了从ffmpeg获取实时输出,用于进度条(PyQt4,stdout)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经看了很多问题,但仍然无法弄明白这一点。我正在使用PyQt,希望运行 ffmpeg -i file.mp4 file.avi ,并将其输出为流,因此我可以创建一个进度条。 p>

我已经看过这些问题:
可以ffmpeg显示进度条吗?
从子进程实时捕获stdout



我可以使用以下代码查看rsync命令的输出:

  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)

在p.stdout中的行:
print(OUTPUT>>>>> + str(line.rstrip()))
p.stdout.flush()

但是当我将命令更改为 ffmpeg -i file.mp4 file.avi 我没有收到输出,我猜这是与stdout / output缓冲有关的,但我被困在如何阅读看起来像

  frame = 51 fps = 27 q = 31.0 Lsize = 769kB时间= 2.04比特率= 3092.8kbits / s 

我可以用它来确定进度。有人可以向我展示如何从ffmpeg获取这个信息到python的例子,有或没有使用PyQt(如果可能的话)






编辑:
我结束了使用jlp的解决方案,我的代码看起来像这样:

 #!/ usr / bin / python 
import pexpect

cmd ='ffmpeg -i file.MTS文件.avi'
thread = pexpect.spawn(cmd)
printstarted%s%cmd
cpl = thread.compile_pattern_list([
pexpec t.EOF,
frame = * \d +,
'(。+)'
])
while True:
i = thread.expect_list(cpl ,timeout = None)
if i == 0:#EOF
print子进程退出
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

哪一个输出:

 启动ffmpeg -i文件.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
子进程退出

完美!

解决方案

我发现获得动态f的唯一方法来自子进程的eedback /输出是使用类似pexpect的东西:

 #! / usr / bin / python 

import pexpect

cmd =foo.sh
thread = pexpect.spawn(cmd)
printstarted %s%cmd
cpl = thread.compile_pattern_list([pexpect.EOF,
'waiting(\d +)'])
while True:
i = thread.expect_list cpl,timeout = None)
如果i == 0:#EOF
打印子进程退出
break
elif i == 1:
waited_time = thread.match.group(1)
打印子进程等待%d秒%int(waited_time)
thread.close()

被调用的子进程foo.sh只是等待10到20秒之间的随机时间,这里是它的代码:

 #! / bin / sh 

n = 5
while [$ n -gt 0]; do
ns =`date +%N`
p =`expr $ ns%10 + 10`
sleep $ p
echo等待$ p
n =`expr $ n - 1`
done

你将要使用一些与输出您从ffmpeg获得,并对其进行某种计算以显示进度条,但这至少将使您得到ffmpeg的无缓冲输出。


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.

I've looked at these questions: Can ffmpeg show a progress bar? catching stdout in realtime from subprocess

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()

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.

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)


EDIT: 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

Which gives this output:

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

Perfect!

解决方案

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()

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

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.

这篇关于从ffmpeg获取实时输出,用于进度条(PyQt4,stdout)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆