首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从ffmpeg获取要在进度栏中使用的实时输出(PyQt4,stdout)

从ffmpeg获取要在进度栏中使用的实时输出(PyQt4,stdout)
EN

Stack Overflow用户
提问于 2011-10-03 16:20:45
回答 7查看 25.1K关注 0票数 26

我已经研究了许多问题,但仍然不能完全解决这个问题。我正在使用PyQt,我希望运行ffmpeg -i file.mp4 file.avi并获得流的输出,这样我就可以创建一个进度条。

我看过这些问题:Can ffmpeg show a progress bar? catching stdout in realtime from subprocess

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

代码语言:javascript
复制
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时,我没有收到任何输出。我猜这与stdout /输出缓冲有关,但我不知道如何阅读下面的代码行

代码语言:javascript
复制
frame=   51 fps= 27 q=31.0 Lsize=     769kB time=2.04 bitrate=3092.8kbits/s

我可以用它来计算进度。

有没有人可以给我举个例子,说明如何在使用或不使用PyQt的情况下,将这些信息从ffmpeg导入python (如果可能的话)。

jlp编辑:我最终采用了jlp的解决方案,我的代码如下:

代码语言:javascript
复制
#!/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

这将给出以下输出:

代码语言:javascript
复制
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

太棒了!

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2011-10-04 06:02:48

我发现从子进程获得动态反馈/输出的唯一方法是使用类似于pexpect的东西:

代码语言:javascript
复制
#! /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秒之间随机等待一段时间,下面是它的代码:

代码语言:javascript
复制
#! /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获得未缓冲的输出。

票数 17
EN

Stack Overflow用户

发布于 2016-02-16 09:50:14

在这个捕获ffmpeg的状态输出的特定情况下(到STDERR),这个SO问题为我解决了它:FFMPEG and Pythons subprocess

诀窍是将universal_newlines=True添加到subprocess.Popen()调用中,因为ffmpeg的输出实际上是无缓冲的,但带有换行符。

代码语言:javascript
复制
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)

还要注意,在此代码示例中,STDERR status输出被直接重定向到subprocess.STDOUT

票数 19
EN

Stack Overflow用户

发布于 2011-10-03 17:03:33

  1. 通常不需要从外壳调用。
  2. 我从经验中知道,stderr而不是stdout提供了部分ffmpeg输出。

如果您只想打印输出行,如上面的示例所示,则只需执行以下操作:

代码语言:javascript
复制
import subprocess

cmd = 'ffmpeg -i file.mp4 file.avi'
args = cmd.split()

p = subprocess.Popen(args)

请注意,ffmpeg chat的行以\r结尾,因此它将在同一行中被覆盖!我认为这意味着您不能像在p.stderr示例中那样遍历rsync中的行。然后,要构建自己的进度条,您可能需要自己处理读数,这应该可以让您开始:

代码语言:javascript
复制
p = subprocess.Popen(args, stderr=subprocess.PIPE)

while True:
  chatter = p.stderr.read(1024)
  print("OUTPUT>>> " + chatter.rstrip())
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7632589

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档