Korrigieren Sie ordnungsgemäß Videos, die mit der alten Version von x264 codiert wurden

501
videoguy

Aufgrund eines Fehlers in alten x264-Versionen, h.264-Videostreams mit den folgenden drei Eigenschaften:

  1. codiert mit x264 build 150 oder früher
  2. unter Verwendung einer 4: 4: 4-Chroma-Unterabtastung
  3. Bitstream enthält keine x264-Versionsinformationen

wird von vielen Videoplayern nicht richtig wiedergegeben. Neue Versionen des Videoplayers mpvhaben eine spezielle Option

--vd-lavc-assume-old-x264 

speziell auf dieses Problem eingehen (siehe: https://mpv.io/manual/master/ ).

Auf dem FFmpeg-Bug-Tracker wird empfohlen, dem Videostream die richtige SEI.h264 hinzuzufügen (die Informationen zur x264-Version enthält, denke ich). Ich ziehe es vor, mich nicht auf solche Hacks zu verlassen, daher lautet meine Frage: Gibt es einen "richtigen" Weg (idealerweise mit ffmpeg), um die Dateien so zu reparieren, als wären sie überhaupt mit einer neuen (festen) Version von x264 verschlüsselt worden ?

Natürlich möchte ich (mehr oder weniger) die Videoqualität und die Dateigröße beibehalten . Wenn eine Neucodierung erforderlich ist, sollte sich nichts ändern, außer das fehlerhafte Verhalten der alten x264-Implementierung zu beheben. (Weitere Informationen: Der Fehlerbericht enthält ein Beispiel für eine beschädigte Datei. Es wird vermutet, dass der Fehler im alten x264 wahrscheinlich hier eingeführt wurde .)

5
Nein. Von ffmpeg können solche Streams nicht korrekt decodiert werden, dann werden Fehler beim erneuten Codieren auftreten. Was ist falsch an der SEI-Einfügung? Gyan vor 6 Jahren 0
@Gyan: Könnten Sie bitte die Befehle angeben, die zum Einfügen des richtigen SEI erforderlich sind? cxrodgers vor 5 Jahren 0

1 Antwort auf die Frage

1
cxrodgers

Vielen Dank, dass Sie diese Frage gestellt haben, sie hat mir geholfen, die Art des Problems zu verstehen, das ich auch hatte. Ich habe eine Lösung, die zu funktionieren scheint.

In meinem Fall verwende ich ffmpeg aus den Ubuntu-Repositories. Die letzte Version, die meine libx264-Dateien decodieren konnte, war 2.8.6. Nach dem Upgrade auf 2.8.14 oder 2.8.15 hatte ich die von Ihnen beschriebenen Dekodierungsprobleme. Ich möchte meine alten Videos nicht neu kodieren, ich möchte nur den Header korrigieren, damit ffmpeg den Fehler, der während der ursprünglichen Kodierung aufgetreten ist, richtig erkennen und richtig abspielen kann.

Zuerst habe ich die statische Binärdatei heruntergeladen, die die neueste Version von ffmpeg, v4, enthält . Ich habe diese Binärdatei mit ffmpeg4meinem System verknüpft, damit ich steuern kann, welche Version ich verwende. Wir benötigen einige der neuen Funktionen, die nach 2.8 eingeführt wurden (nicht genau wissen, wann). Wenn Sie bereits eine neuere Version von ffmpeg installiert haben, verwenden Sie diese einfach und ersetzen Sie sie ffmpeg4mit ffmpegden folgenden Befehlen.

Extrahieren Sie nun den rohen Bitstream aus Ihrem defekten Video (nennen Sie es BROKEN.mkv).

ffmpeg4 -i BROKEN.mkv -vcodec copy -an -bsf:v h264_mp4toannexb raw.h264 

Ich bin nicht sicher, ob das h264_mp4toannexb-Flag erforderlich ist. Es kann für dieses Format automatisch eingefügt werden.

Legen Sie nun den Bitstream in einen neuen mp4-Container und korrigieren Sie die Informationen zum alten fehlerhaften x264-Build im SEI-Header .

ffmpeg4 -r 30 -i raw.h264 -avoid_negative_ts 1 -bsf:v h264_metadata='sei_user_data=dc45e9bde6d948b7962cd820d923eeef+x264 - core 150' -c copy FIXED.mp4 

Der Bitstream enthält keine Zeitstempelinformationen, daher werden Sie hier eine Menge Warnungen erhalten. Ich fand auch, dass ich die Framerate manuell auf 30fps ( -r 30) einstellen musste, da sonst eine variable Framerate zwischen 25 und 30fps angenommen wurde. Ich weiß nicht, wie ich die Zeitstempel richtig extrahieren oder korrekt in den neuen Container muxen kann. Bitte lassen Sie mich wissen, wenn Sie eine Lösung haben! Viele Leute empfehlen, -fflags +genptsaber das scheint mir nichts zu tun . Schließlich habe ich hinzugefügt -avoid_negative_ts 1, um den Zeitstempel des ersten Frames als nicht negativ zu erhalten.

Schließlich und dies ist optional, wenn Sie die Ergebnisse in einen MKV-Container legen möchten, können Sie dies tun

ffmpeg4 -i FIXED.mp4 -c copy FIXED.mkv 

Warum erst nach MP4 und dann nach MKV konvertieren ? Es scheint, dass sich der MKV-Container einfach weigert, ohne Zeitstempel fortzufahren, aber MP4 wird dies tun und nur Warnungen ausgeben. Dann können Sie ohne Warnungen in MKV konvertieren.

Nach all dem habe ich also MP4- und MKV-Dateien. Ich habe jedoch einige Frames untersucht und es gibt geringfügige Änderungen (Luminanzänderungen in der Größenordnung von ~ 2 Stufen). Ich verstehe nicht, warum dies passiert ist, weil dies verlustfrei hätte sein sollen. Bitte lassen Sie mich wissen, wenn Sie Vorschläge haben, wie dies besser gemacht werden kann.

Edit: Ich habe bemerkt, dass einige meiner Zeitstempel im MP4-Container negativ waren, beginnend bei -0.066667s. Nach dem Umzug in einen MKV-Container wurden alle negativen Zeitstempel zu Nullen. Durch -output_ts_offset 0.066667das Hinzufügen des Befehls wurde dieses Problem behoben und sie beginnen bei Null. Ich verstehe nicht, warum es bei -0,066667 begann.

Bearbeiten 2: Eine bessere Methode zum Entfernen negativer Zeitstempel ist die Verwendung von "-avoid_negative_ts 1" beim Codieren des mp4.

@Gyan Ich sehe, Sie haben viele tolle Antworten zu Zeitstempeln gepostet. Können Sie mir bitte vorschlagen, wie Sie die Zeitstempel im Container richtig angeben, wenn Sie einen unformatierten h264-Stream bereitstellen? danke für irgendwelche tipps !! cxrodgers vor 5 Jahren 0