So extrahieren und ändern Sie Datenrate und Zeitskala aus einer OpenDML-Datei (AVI).

Ich arbeite an einem Python-Skript zur Massentranscodierung von Videodateien. Diese Dateien haben unterschiedliche Frameraten, und eines der Ziele besteht darin, sie alle auf die gleiche Framerate zu bringen, indem einige intelligente Entscheidungen getroffen werden, ob die Wiedergabe verlangsamt oder beschleunigt oder Frames dezimiert oder dupliziert werden sollen. So wie ich es verstehe, wird die Framerate als zwei 32-Bit-Ganzzahlen gespeichert, zum Beispiel werden 29,97 fps tatsächlich als 30000/1001 gespeichert, und ich muss mit diesen Werten arbeiten. Ich werde diese Werte auch verwenden, um zu berechnen, wie stark das Audio gedehnt und die Tonhöhe verschoben werden muss. Die Frameraten der Quelldateien sind nicht unbedingt Standard, aber sie können alles von etwas abweichend von PAL oder NTSC bis hin zu völlig vermasselt sein, und die Verwendung der Werte, die tatsächlich in den Dateien enthalten sind, macht es einfacher, die Berechnungen durchzuführen.

Wie kann ich sie also extrahieren und im Falle einer Verlangsamung oder Beschleunigung des Videos geänderte Werte zurückschreiben?
Vorzugsweise ein Kommandozeilentool (muss auf FreeBSD laufen).
Ich bin auch offen dafür, die Header direkt aus dem Skript zu analysieren, aber leider weiß ich nicht, wo ich sie finden kann.

Die Spezifikationen, die ich gefunden habe, listen mehr oder weniger die verschiedenen Strukturen (wie in C definiert) für die verschiedenen Header auf, und ein erfahrener Programmierer kann dies möglicherweise verwenden, aber ich brauche eine einfachere Erklärung. Ich brauche keine Hilfe beim eigentlichen Scripting, ich brauche nur Hilfe, um zu verstehen, wo sich die Informationen befinden.


OpenDML AVI-Dateiformaterweiterungen
AVI-Dateiformat

Welches Tool werden Sie zum Transcodieren verwenden?
@Mulvya Ich werde ffmpeg verwenden
Dann sind Sie fertig. Stellen Sie einfach a ein -r Nund ffmpeg wird nach Bedarf duplizieren oder dezimieren. In jedem Fall können Sie die Framerate von ffprobe abrufen.
@Mulvya Ich kenne ffprobe und es gibt mir nicht die Informationen, die ich brauche. Als Beispiel habe ich das aus einer Datei bekommen: 23.98 fps, 23.98 tbr, 23.98 tbn, 23.98 tbc. Ich muss die 24000 und 1001 davon bekommen. Und für eine Standard-Framerate wie diese ist es ziemlich einfach abzuleiten, aber die Quelle kann praktisch jede Framerate haben, z. B. 21,749128.
Sie müssen nach Stream-Einträgen fragen, dh ffprobe in.avi -show_entries stream=r_frame_rate,avg_frame_rate -select_streams v -v 0 -of compact=p=0:nk=1der erste rationale Wert stammt aus dem Stream-Header; der zweite ist der berechnete Wert, der sich für einen Stream mit variabler Bildrate unterscheidet.
Wie auch immer, mein Punkt war, wenn Sie während der Transcodierung ffmpeg bereitstellen -r N, kümmert sich ffmpeg um das Duplizieren oder Löschen von Frames. Wenn die Eingabe VFR ist. Es wird dupliziert, wo die Rate des Segments niedriger ist, und fällt, wenn sie höher ist.
@Mulvya Das hat es geschafft. Danke dir. Wenn Sie eine Antwort hinzufügen, werde ich sie akzeptieren. (der ffprobe-Befehl).

Antworten (1)

ffprobe kann die Framerate als rationalen Wert liefern

ffprobe in.avi -show_entries stream=r_frame_rate,avg_frame_rate -select_streams v -v 0 -of compact=p=0:nk=1

Der erste rationale Wert stammt aus dem Stream-Header; der zweite ist der berechnete Wert, der sich für einen Stream mit variabler Bildrate unterscheidet

Anscheinend war ich ein bisschen aufgeregt, und das war nur die halbe Lösung. In den Fällen, in denen ich das Skript entscheiden lasse, das Video zu verlangsamen oder zu beschleunigen, anstatt Frames zu dezimieren/duplizieren, muss ich auch die fps ändern, ohne den Stream zu ändern, aber ich habe festgestellt, dass ffmpeg auch diese Fälle verarbeiten kann. ZB Verlangsamung von 25 auf 23.98: ffmpeg -i in.avi -r 24000/1001 filter:v "setpts=1001/960*PTS" out.avi. Ich hatte Angst, dass dies zuerst einige Frames löschen und dann einige der verbleibenden duplizieren würde, aber in den Tests, die ich durchgeführt habe, scheint es nur die fps zu ändern und dann die ursprünglichen Frames zu transcodieren.
Es ist der Encoder, der Frames basierend auf der erforderlichen Framerate verwirft oder dupliziert. Dies geschieht durch einen Blick auf die PTS-Serie. Da der Setpts-Filter verwendet wird, erhält er die erwartete Anzahl von Frames. Wäre Ihr setpts-Argument unterschiedlich gewesen, aber derselbe rWert: PTS*2002/960Dann sehen Sie zB, dass Frames hinzugefügt werden.
Gut zu wissen. Vielen Dank. Ich werde sogar ein frohes Weihnachtsfest einwerfen. :)
Dir auch schöne Feiertage.