L'obtention de la sortie en temps réel à partir de ffmpeg pour être utilisé dans la barre de progression (PyQt4, stdout)
J'ai regardé un certain nombre de questions, mais ne peut toujours pas tout à fait le comprendre. Je suis l'aide de PyQt, et j'espère pour exécuter ffmpeg -i file.mp4 file.avi
et obtenir la sortie en elle diffuse donc je peux créer une barre de progression.
J'ai regardé ces questions:
Peut ffmpeg afficher une barre de progression?
la capture de la sortie standard stdout en temps réel à partir de sous-processus
Je suis en mesure de voir la sortie d'une commande rsync, à l'aide de ce 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()
Mais quand j'ai changer la commande à ffmpeg -i file.mp4 file.avi
je ne reçois aucune sortie. Je suppose que cela a quelque chose à voir avec stdout /tampon de sortie, mais je suis coincé à la façon de lire la ligne qui ressemble à
frame= 51 fps= 27 q=31.0 Lsize= 769kB time=2.04 bitrate=3092.8kbits/s
Que je pourrais utiliser pour déterminer les progrès accomplis.
Quelqu'un peut-il me montrer un exemple de la façon d'obtenir cette information de ffmpeg en python, avec ou sans l'utilisation de PyQt (si possible)
EDIT:
J'ai fini par aller avec pam, c'est la solution, mon code ressemble à ceci:
#!/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
Qui donne ce résultat:
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
Parfait!
- votre code dans le modifier n'est pas bon (et ne fonctionne pas pour moi)... je ne pense pas que vous voulez prendre un modèle générique et ne rien faire (vous ne devez attraper les modèles que vous vous souciez d') et, plus important encore, vous voulez les
thread.close
être hors le tout en boucle plutôt que de appelé la première fois que vous reprenez votre modèle d'intérêt. @pam 's code semble plus correct et fonctionne pour moi une fois adapté pour les formats de sortie. - En cas de Python3, il convient de:
frame_number = thread.match.group(0).decode('utf-8')
Vous devez vous connecter pour publier un commentaire.
Le seul moyen que j'ai trouvé pour obtenir une rétroaction dynamique/sortie à partir d'un processus enfant est d'utiliser quelque chose comme pexpect:
le sous-processus foo.sh attends un montant aléatoire de temps, entre 10 et 20 secondes, voici le code:
Vous aurez envie d'utiliser certaines expression régulière qui correspond à la sortie que vous obtenez à partir de ffmpeg et fait ce genre de calcul pour afficher la barre de progression, mais cela permettra au moins de vous obtenir le tampon de sortie de ffmpeg.
thread = pexpect.spawn(cmd)
J'ai modifié la ligne précédentecmd = "foo.sh"
decmd = "./foo.sh"
espère que ça va aider quelqu'un 🙂Dans ce cas spécifique pour la capture de ffmpeg sortie de l'état (qui va vers STDERR), cette question résolu pour moi: FFMPEG et des Pythons sous-processus
L'astuce consiste à ajouter
universal_newlines=True
à lasubprocess.Popen()
appeler, parce que ffmpeg sortie est en fait non, mais vient avec retour à la ligne de caractères.Également noter que dans cet exemple de code le STDERR sortie de l'état est directement redirigé vers
subprocess.STDOUT
stderr
, passtdout
.Si tout ce que vous voulez faire est d'imprimer la ligne de sortie, comme dans l'exemple ci-dessus, puis, tout simplement, ce sera à faire:
Notez que la ligne de ffmpeg chat est arrêté avec
\r
, donc il va remplacer dans la même ligne! Je pense que cela signifie que vous ne pouvez pas effectuer une itération sur les lignesp.stderr
, comme vous le faites avec votre rsync exemple. Pour créer votre propre barre de progression, puis, vous pourriez avoir besoin pour gérer la lecture vous-même, cela devrait vous aider à démarrer:Ce qui répond n'a pas fonctionné pour moi :/Ici est la façon dont je l'ai fait.
Son de mon projet KoalaBeatzHunter.
Profitez-en!
Ensuite, vous avez besoin de 3 plus de fonctions à mettre en œuvre.
Et enfin vous faire:
Espère que cela va vous aider!
Si vous avez la durée (que vous pouvez également obtenir de l'FFMPEG sortie), vous pouvez calculer le progrès par la lecture du temps écoulé (temps) de sortie lors de l'encodage.
Un exemple simple:
Vous pouvez aussi le faire assez clairement avec PyQt4 de QProcess (comme demandé dans la question d'origine) par la connexion d'un logement à partir de la QProcess à un QTextEdit ou quoi que ce soit. Je suis encore assez nouveau pour python et pyqt, mais voici comment j'ai juste réussi à le faire: