So ändern Sie die Framerate eines Videos ohne Neukodierung

14

Ich versuche, die Framerate eines MP4-Videos zu ändern (es ist ein GoPro-Video mit 120 Bildern pro Sekunde, ich möchte es für einen Zeitlupeneffekt mit 30 Bildern pro Sekunde wiedergeben).

Ich benutze dafür avconv:

avconv -i SourceMovie.mp4 -vf setpts=4.0*PTS -r 30 DestMovie.mp4

Das funktioniert technisch, aber es kodiert den Film neu. Es ist nicht nur langsam, sondern auch ein Qualitätsproblem. Technisch sollte es eine Möglichkeit geben, einfach die fps im Header des Videos einzustellen, wie kann ich das ändern? (Jedes andere Tool als avconv würde auch funktionieren.)

EboMike
quelle

Antworten:

15

MP4Box schafft das.

Der Befehl

MP4Box -add SourceMovie.mp4#video -raw 1 -new test

erstellt die Dateien testund test_track1.h264. Sie können jetzt eine mp4-Datei mit der von Ihnen gewünschten unterstützten Bildrate erstellen (30 in diesem Beispiel):

MP4Box -add test_track1.h264:fps=30 -new DestMovie.mp4

MP4Box ist Teil des gpacPakets, stellen Sie also sicher, dass es installiert ist.

Mitch
quelle
6
Es ist wirklich nicht einfach, aber ich habe es verstanden - Sie müssen es in zwei Schritten tun. Extrahieren Sie den Videostream zunächst separat als raw ( MP4Box -add source.mp4#video -raw 1 -new test) und speichern Sie ihn dann erneut als MP4 ( MP4Box -add test_track1.h264:fps=30 -new dest.mp4). Sie können dort auch eine Audiospur hinzufügen (über #audio).
EboMike
Es ist besser, die -singleOption für den ersten Befehl zu verwenden. MP4Box -single 1 -raw 1 SourceMovie.mp4Erstellt nur eine Datei SourceMovie_track1.h264anstelle von zwei.
Diversenok
6

Das Ändern der Framerate im Header des Videos (Containers) hat keine Auswirkungen auf den Videostream (oder den Audiostream). Neucodierung ist die einzige Option.

Videostreams haben Zeitstempel und in den meisten Videos sind die Frames aufgrund der Interframe-Komprimierung voneinander abhängig. Einige Player können das Video beschleunigen und verlangsamen, jedoch nicht mit eingebetteten Befehlen oder Ähnlichem. Kein Spieler kann die Framerate im laufenden Betrieb ändern, wenn er von einem Containerbefehl dazu aufgefordert wird. Die Spezifikation der Videodatei wird nicht eingehalten (dh sie entspricht nicht den Standards), und 99,9% der Player lehnen die Einhaltung ab. Ohne Neukodierung ist es unmöglich, das zu tun, was Sie wollen. Natürlich können Sie mit dem Umkodieren bis zum letzten Schritt Ihrer Bearbeitung warten.

thom
quelle
1
Danke dir! Dumme Frage - warum? Verfügt jedes Bild über einen Zeitstempel, der den Player dazu zwingt, eine bestimmte Wiedergabegeschwindigkeit zu erzwingen? Ich möchte genau die gleichen Bilder, ich möchte nur, dass sie mit einer anderen Geschwindigkeit wiedergegeben werden.
EboMike
2
Hallo Mike, nein deine Frage ist nicht dumm, ehrlich gesagt ist die Art, wie du denkst, ziemlich schlau. Ich mag deine Denkweise. Ich habe meiner Antwort weitere Informationen hinzugefügt, da es zu lang war, diese in das Kommentarfeld aufzunehmen.
thom
Vielen Dank! Das ist sehr informativ. Was nun das Umkodieren betrifft - wie geht das am besten mit so etwas wie avconv? Ich habe die obige Befehlszeile verwendet, aber das führte zu einer schrecklichen Qualität - ich konnte fast jeden Makroblock sehen.
EboMike
1
Die Zeitstempel in Videostreams werden im Container gespeichert, nicht der rohe h.264-Bitstream selbst, denke ich. Solange Sie nur das Timing ändern möchten, aber nicht die Reihenfolge, in der der Frame angezeigt wird, sollten Sie keine Transcodierung benötigen, sondern nur Remux. (Und wenn Sie xcode machen, würden Sie mit schnellerer Hardware -preset langsamer oder sehr langsam verwenden, um mehr Qualität mit der gleichen Bitrate zu erzielen, anstatt nur mehr Bits auf das Problem zu werfen. Und verwenden Sie -crf 18 oder so, nicht ABR)
Peter Cordes
1
Ich kann nicht herausfinden, wie ich ffmpeg dazu bringe, eine andere Framerate auszugeben. Es sieht so aus, als ob mkvmerge / mp4box erforderlich ist, es sei denn, Sie können ffmpeg zur Ausgabe eines rohen .264-Bitstroms verwenden und dann die Option fps für den h.264-Demuxer verwenden (der -h vollständige Dokumente hat, da der Bitstrom kein Timing hat) Info, nur Bestellung.)
Peter Cordes
3

Für den Fall, dass Sie die Datei hauptsächlich in Zeitlupe wiedergeben und nicht als MP4 speichern möchten, können Sie sie mit dem MKVmerge-GUI-Tool in einen Matroska-Container umwandeln, mit dem sich die Framerate leicht ändern lässt. Remuxen ist viel besser als Neukodieren, da nur die Metadaten und nicht der Stream selbst geändert werden.

Zuerst installieren Sie das Paket

sudo apt-get install mkvtoolnix-gui

Dann starten Sie MKVmerge GUI. Sie werden mit einem solchen Fenster konfrontiert

mkvmerge gui 1

Drücken Sie einfach die Schaltfläche Hinzufügen und wählen Sie Ihre Datei aus oder ziehen Sie die Datei einfach per Drag & Drop in den Bereich "Eingabedateien". Zu diesem Zeitpunkt sollten Sie in der Lage sein, den Videostream in Ihrem Video auszuwählen. Sie können auch andere Streams löschen, da diese sowieso nur stören.

Nachdem Sie es ausgewählt haben, sollten die unteren Registerkarten aktiv werden:

Bildbeschreibung hier eingeben

Wechseln Sie zu "Spezifische Aktionen formatieren"

Bildbeschreibung hier eingeben

Sie können sehen, dass es ein Feld "FPS" gibt, in das Sie den Wert für Frames pro Sekunde eingeben können. Es sah so aus, als ob Sie vorhatten, die Geschwindigkeit viermal zu senken, also wären etwa 7 Bilder pro Sekunde Ihr Ziel. Sie können auch die Option "Strecken nach" verwenden.

Danach können Sie einfach den Namen der Ausgabedatei ändern (wenn Sie möchten) und auf "Muxen starten" klicken.

Das Programm wird ausgeführt und Sie sollten Ihre Datei haben.

v010dya
quelle
2

Ich wollte auch verlustfrei meine 120 FPS Filme auf 30 FPS verlangsamen. Ich habe ein Skript erstellt, indem ich das Sound-Tempo geändert und die FPS direkt im MP4-Container geändert habe. Folgende Werkzeuge werden benötigt:

  1. avconv , um Audio-Streams zu konvertieren
  2. sondstretch , um das Audiotempo zu verlangsamen
  3. gpac , um MP4Box zu veranlassen, die FPS zu ändern

Das für die Konvertierung verwendete Skript ist hier:

#!/bin/bash
#########################################
# Lossless slow down from 120 to 30 FPS #
#                                       #
# Use:                                  #
#                                       #
#   slow.bash <mp4_file>                #
#                                       #
#                           #-= OSi =-# #
#########################################


# Prepare basic variables
IN_FILE="$1"
NAME=$(echo "${IN_FILE}" | sed 's/\.[^.]*//')


# Clean up before start
rm -f "${NAME}.ac3" "${NAME}.wav" "${NAME}_.wav" "${NAME}" "${NAME}_track1.h264" "${NAME}_slow.mp4"


# Slow down sound
avconv -i "${IN_FILE}" -vn -acodec pcm_s16le "${NAME}_.wav"
soundstretch "${NAME}_.wav" "${NAME}.wav" -tempo=-75
avconv -i "${NAME}.wav" -vn -codec:a ac3_fixed -b:a 448k "${NAME}.ac3"


# Change video frame rate and multiplex with slowed sound
MP4Box -add "${IN_FILE}#video" -raw 1 -new "${NAME}"
MP4Box -add "${NAME}_track1.h264:fps=30" -add "${NAME}.ac3" -new "${NAME}_slow.mp4"


# Clean up when we are done
rm -f "${NAME}.ac3" "${NAME}.wav" "${NAME}_.wav" "${NAME}" "${NAME}_track1.h264"

Dieses Skript erstellt eine Kopie von MP4 mit _slow Postfix.

OSi
quelle