python - ffmpegからリアルタイム出力を取得してプログレスバーで使用する(PyQt4、stdout)

python ffmpeg pyqt subprocess stdout

私はいくつかの質問を見てきましたが、まだこれを理解することはできません。私はPyQtを使用しています。プログレスバーを作成できるように、ffmpeg -i file.mp4 file.aviを実行し、ストリームとして出力を取得することを望んでいます。

私はこれらの質問を見ました:
Can ffmpeg show a progress bar?
catching stdout in realtime from subprocess

このコードを使用して、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)

for line in p.stdout:
    print("OUTPUT>>> " + str(line.rstrip()))
    p.stdout.flush()


しかし、コマンドをffmpeg -i file.mp4 file.aviに変更すると、出力が表示されません。私はこれが標準出力/出力バッファリングと関係があると推測していますが、次のような行を読む方法については行き詰っています

frame=   51 fps= 27 q=31.0 Lsize=     769kB time=2.04 bitrate=3092.8kbits/s


進捗状況を把握するために使用できます。

誰かが私にffmpegからpythonにこの情報を取得する方法の例を教えてもらえますか?PyQtの使用の有無にかかわらず(可能であれば)



編集:
私はjlpのソリューションに行き着き、私のコードは次のようになりました。

#!/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のようなものを使用することです:

#! /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秒の間のランダムな時間だけ待機します。そのコードを次に示します。

#! /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からのバッファーなしの出力が取得されます。
関連記事

python - オブジェクト属性への関数の割り当て

python - デコレータを飾る:それを理解するために私の頭を取得しよう

python - Pythonジェネレーターをメモできますか?

python - PythonとUnicode:すべてがUnicodeである方法

python - Pythonでは、ファイルハンドル自体を反復処理できるのにreadlines()が必要なのはなぜですか?

c# - PythonでC#dllをロードする方法は?

python - Django 1.9では、JSONField(ネイティブpostgres jsonb)を使用するための規則は何ですか?

python - PythonのXGBoost XGBClassifierのデフォルト

python - Pythonでサブプロセスからリターンコードと出力の両方を取得する方法は? [複製]

python - Redis Pythonでのキーの有効期限の通知