FFmpeg subprocess.Popen stdout leer?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
tommyly
User
Beiträge: 9
Registriert: Sonntag 13. Februar 2011, 21:37

Hey!
Ich hocke hier jetzt schon 2 Tage dran und kämpfe mit den Kommandozeilenausgaben von ffmpeg rum :D
Ergebnis: Läuft immer noch nicht.
Eigentlich klingt das Problem noch recht einfach: FFmpeg auf eine Videodatei ausführen und die Ausgabe in eine Variable bekommen. (Um die Metadaten zu bekommen, v.a. Länge usw.)
Hier der Code:

Code: Alles auswählen

import subprocess

output = subprocess.Popen(r"[PFAD_ZU_FFMPEG_BIN] -i [PFAD_ZU_VIDEODATEI]", stdout=subprocess.PIPE).stdout.read()
Ausgabe von output mittels print liefert mir nur nen leeren Bytesstring, also wohl die letzte Zeile der Ausgabe. Wo bleibt der Rest? :D

Danke ;)
Es gibt 10 Arten von Menschen: Die Einen verstehen das Dualsystem, die Anderen nicht.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Das ist doch kein funktionierender Parameter?!?

Code: Alles auswählen

r"[PFAD_ZU_FFMPEG_BIN] -i [PFAD_ZU_VIDEODATEI]"
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
tommyly
User
Beiträge: 9
Registriert: Sonntag 13. Februar 2011, 21:37

natürlich ist das keiner :D
Ich kann euch ja auch gerne mit dem ganzen Pfad posten:

Code: Alles auswählen

import subprocess

output = subprocess.Popen(r"Z:\Python\bin\ffmpeg -i Z:\Python\bin\video.wmv", stdout=subprocess.PIPE).stdout.read()
Es gibt 10 Arten von Menschen: Die Einen verstehen das Dualsystem, die Anderen nicht.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

tommyly hat geschrieben:natürlich ist das keiner :D
Man sollte das schon genau so posten, wie man es auch ausführt - der Fehler kann ja durchaus da drin liegen ;-)
tommyly hat geschrieben:

Code: Alles auswählen

import subprocess

fileoutput = subprocess.Popen([r"Z:\Python\bin\ffmpeg",  "-i", r"Z:\Python\bin\video.wmv"], stdout=subprocess.PIPE).stdout.read()
Probiere es mal so! Die Parameter sollte man als Iterable übergeben, nicht als konkatenierten String.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
tommyly
User
Beiträge: 9
Registriert: Sonntag 13. Februar 2011, 21:37

Gleiches Ergebniss, immer noch leerer Bytesstring :?
Es gibt 10 Arten von Menschen: Die Einen verstehen das Dualsystem, die Anderen nicht.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Führ doch auf dem Popen-Objekt mal die communicate()-Methode auf. (Oder ggf. auch wait)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
tommyly
User
Beiträge: 9
Registriert: Sonntag 13. Februar 2011, 21:37

Keine Veränderung bei diesem Code:

Code: Alles auswählen

import subprocess

file = subprocess.Popen([r"Z:\Python\test\bin\ffmpeg",  "-i", r"Z:\Python\test\bin\video.wmv"], stdout=subprocess.PIPE)
file.wait()
[output, other] = file.communicate()
print(output)
(Nicht wundern, Pfad geändert: Habe Dateien verschoben)
Es gibt 10 Arten von Menschen: Die Einen verstehen das Dualsystem, die Anderen nicht.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Na, beides macht keinen Sinn! Zudem solltest Du das nicht "file" nennen, da das ein Built-in überschreibt.

Mal doof gefragt: In einer Shell kannst Du das ausführen?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
tommyly
User
Beiträge: 9
Registriert: Sonntag 13. Februar 2011, 21:37

Habs auch einzeln probiert.
In der Shell funktionierts und wirft dann ne mehrere Zeilen lange Meldung aus (mit allen Metadaten usw.)

U.a. aber auch, dass mindestens eine Ausgabedatei angegeben sein muss. Könnte es sein, dass ffmpeg einen Returncode != 0 zurückgibt und deswegen die vorigen Meldungen alle verworfen werden?

EDIT:
Habs nochmal per call probiert, Returncode ist 1. Vielleicht liegt es daran ... Andere Vorschläge, trotzdem die Ausgaben zu bekommen?

EDIT2:
Lösung selber gefunden:
Returncode != 0 also nen Error. Dann werden die Ausgaben auch nicht mehr in stdout geschrieben sondern in stderr. Mit der zusätzlichen Angabe von stderr=subprocess.STDOUT schreibt er dann auch alle Errors in stdout und man kann sie wie ganz normale Ausgaben behandeln. Trotzdem danke :)
Zuletzt geändert von tommyly am Mittwoch 16. Februar 2011, 20:36, insgesamt 1-mal geändert.
Es gibt 10 Arten von Menschen: Die Einen verstehen das Dualsystem, die Anderen nicht.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Evtl schreibt ffmpeg auf `stderr`, das wird es auf jeden Fall tun, wenn der Exitcode != 0 ist.
Ausgaben werden aber nicht verworfen.
tommyly
User
Beiträge: 9
Registriert: Sonntag 13. Februar 2011, 21:37

Habs schon selbst entdeckt.
Trotzdem vielen Dank ;)
Es gibt 10 Arten von Menschen: Die Einen verstehen das Dualsystem, die Anderen nicht.
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Ich rate mal: ffmpeg haette gerne auch einen Parameter fuer die Ausgabedatei.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
tommyly
User
Beiträge: 9
Registriert: Sonntag 13. Februar 2011, 21:37

Ja, genau, den kann ich aber nicht angeben.
Wollte ja nur die Metadaten des Videos bekommen ;)
Es gibt 10 Arten von Menschen: Die Einen verstehen das Dualsystem, die Anderen nicht.
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

Nur mal kurz danke, der Thread hat mir geholfen. :)

meine function sieht so aus:

Code: Alles auswählen

def run_command(command):
    import subprocess
    return subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.read()
empty Sig
BlackJack

@harryberlin: Und warum verwendest Du nicht einfach `subprocess.check_output()`? Was zudem den Vorteil hat nicht ausversehen Zombie-Prozesse zu produzieren, den Rückgabecode über die Ausnahme liefert falls der nicht 0 ist, und auch nicht standardmässig ``shell=True`` gesetzt hat, was man vermeiden sollte.
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

wie muss es mit check_out() aussehen?
hatte heut etliches probiert, auch "check_out()" war dabei, aber ohne erfolg.
Wo entsteht und Was ist ein Zombie-Prozess?
empty Sig
BlackJack

@harryberlin: Ein Zombie-Prozess ist einer der zwar schon komplett durchgelaufen ist, wo aber der Elternprozess den Rückgabecode noch nicht abgefragt hat. Deshalb muss das Betriebssystem noch in der Prozesstabelle führen. Der ist also noch da, obwohl er eigentlich tot ist → Zombie. Die Wikipedia-Seite zu dem Begriff ist übrigens der erste Treffer wenn ich nach „zombie prozess“ suche…
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

also "shell=True" einfach weglassen, und dann passt es?
wie muss es mit check_out() aussehen?
hatte heut etliches probiert, auch "check_out()" war dabei, aber ohne erfolg.
empty Sig
BlackJack

@harryberlin: Naja nicht nur das `shell`-Argument weglassen sondern dann natürlich auch das Kommando als Liste angeben und nicht als Zeichenkette die erst von einer Shell interpretiert werden muss.
harryberlin
User
Beiträge: 227
Registriert: Donnerstag 17. Dezember 2015, 12:17

zu check_out:
wie muss es mit check_out() aussehen?
hatte heut etliches probiert, auch "check_out()" war dabei, aber ohne erfolg.

zu zombie:
also so?

Code: Alles auswählen

def run_command(command):
    import subprocess
    return subprocess.Popen(command.split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout.read()
empty Sig
Antworten