Ändern Sie die Framerate in ffmpeg, ohne sie neu zu codieren

14

Ich habe ein mkv (h264) -Video mit 23,976 fps (24000/1001), aber ich möchte es in 25 fps konvertieren, ohne es neu zu codieren und die Qualität zu verlieren. Ich weiß, dass mkvmerge dies kann (mit der Option --default-duration '0: 25fps'), aber ich möchte es wenn möglich direkt von ffmpeg aus tun. Laut den Dokumenten sollte dies funktionieren:

ffmpeg -i input.mkv -r 25 -vcodec copy output.mkv

aber wenn ich es ausführe, bekomme ich nur die gleichen Video-FPS. Was ist die richtige Methode, um dies in ffmpeg zu tun (falls vorhanden)?

phate89
quelle
1
Ich glaube, das ist mit FFmpeg momentan nicht möglich. -rist nicht mit der Stream-Kopie kompatibel und es gibt keine Bitstream-Filter zum Ändern der Framerate.
Ely
1
schade. Ich muss jedes Mal mkvmerge verwenden. danke
phate89
1
Es gibt einen komplizierten Weg, dies mit normalem ffmpeg zu tun, und einen direkten Weg, dies mit einer alten modifizierten Version von ffmpeg zu tun. Wenn Sie interessiert sind, schreibe ich es als Antwort.
Gyan
1
Ja danke .. Ich würde es gerne ohne zusätzliche Tools machen (ich brauche bereits ffmpeg)
phate89
1
@Mulvya Sie sprechen dieses Recht? Ich habe gezögert, es zu verlinken, aber es ist jetzt alt. Interessiert an der verschlungenen Art und Weise, es mit normalem FFmpeg zu machen.
Ely

Antworten:

15

Hier ist die Methode mit aktuellen Versionen von FFmpeg. Es basiert darauf, dass der Concat-Demuxer das PTS der Eingaben nach der ersten Datei nicht neu skaliert, sondern einfach einen festen Offset anwendet. Angenommen, Sie haben einen 30-fps-Stream mit einer Zeitskala von 15360(typisch für die FFmpeg-Ausgabe). Das heißt, Frame 0hat PTS 0und Frame 30hat PTS 15360. Dies würde zu einem 45-fps-Stream werden, wenn wir die Zeitskala ändern könnten, 23040ohne die PTS-Werte zu beeinflussen.

Im Wesentlichen ist dies die folgende Methode.

1 . Identifizieren Sie die Quelleneigenschaften.

Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1171 kb/s,
       30 fps, 30 tbr, 15360 tbn (default)

Sie möchten die Quelleneigenschaften notieren, insbesondere die Auflösung und tbn.


2a . (Optional) Ändern Sie die Zeitskala auf einen geeigneten Wert, um die Berechnung zu vereinfachen.

ffmpeg -i in.mp4 -c copy -an -video_track_timescale 30 in-v30.mp4

Das bringt uns

Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1171 kb/s, \
       30 fps, 30 tbr, 30 tbn (default

Wenn Sie diesen Schritt ausführen, sollte die neue Zeitskala gleich oder ein ganzzahliges Vielfaches der ursprünglichen Bildrate sein.

2b . Berechnen Sie die benötigte Zeitskala, damit der xPTS von Frame # xin der Quelle für die Zielframerate den gleichen Wert wie der neue hat tbn. Wenn Sie Schritt 2a ausgeführt haben, ist dies sehr einfach und es ist einfach die neue Framerate. Für Ziel-FPS sollte also 45neu tbnsein 45.


3 . Dummy-Video generieren.

ffmpeg -f lavfi -i color=s=1280x720:r=45:d=1 -profile:v main -video_track_timescale 45 0.mp4

Alle Eigenschaften sollten identisch sein wie Auflösung, H.264-Profil, Pixelformat, Refs-Anzahl usw. für beste Ergebnisse.


4 Konzentrieren Sie sich auf die Videos.

Erstellen Sie zuerst eine Textdatei

file '0.mp4'
file 'in-v30.mp4'

Dann der Concat

ffmpeg -f concat -i list.txt -c copy -video_track_timescale 45 45fps.mp4

In der Ausgabedatei wird das 2. Video mit 45 fps abgespielt.

5 . Jetzt spalten Sie das Dummy-Preroll ab

ffmpeg -ss 1.1 -i 45fps.mp4 -c copy -avoid_negative_ts make_zero in45.mp4

und du hast

Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1757 kb/s, \
       45 fps, 45 tbr, 11520 tbn (default)

Ich habe gesagt, das war verworren!

Gyan
quelle
1
sehr klug, gute Antwort.
Rowe Morehouse