
Aufgrund eines Fehlers in alten Versionen von x264 werden h.264-Videos mit den folgenden drei Eigenschaften gestreamt:
- kodiert mit x264 Build 150 oder früher
- mit 4:4:4 Chroma-Subsampling
- Bitstream enthält keine x264-Versionsinformationen
wird von vielen Videoplayern nicht richtig wiedergegeben. Neuere Versionen des Videoplayers mpv
haben eine spezielle Option
--vd-lavc-assume-old-x264
speziell auf dieses Problem eingegangen wird (siehe:https://mpv.io/manual/master/).
Auf derFFmpeg-FehlertrackerEs wird empfohlen, dem Videostream die richtige SEI.h264 hinzuzufügen (die vermutlich die x264-Versionsinformationen enthält). Ich verlasse mich lieber nicht auf solche Hacks, daher lautet meine Frage:Gibt es eine „richtige“ Möglichkeit (idealerweise mit ffmpeg), die Dateien so zu reparieren, als wären sie ursprünglich mit einer neuen (korrigierten) Version von x264 codiert worden??
Natürlich möchte ich (mehr oder weniger) Video bleibenQualitätUndDateigröße. Wenn eine Neukodierung notwendig ist, sollte sich dadurch nichts ändern, außer dass das fehlerhafte Verhalten der alten x264-Implementierung behoben wird. (Weitere Informationen:Der Fehlerberichtzeigt ein Beispiel einer beschädigten Datei. Es wird vermutet, dass der Fehler im alten x264 wahrscheinlichhier vorgestellt.)
Antwort1
Vielen Dank für das Posten dieser Frage. Sie hat mir geholfen, die Natur meines Problems zu verstehen. 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 dekodieren 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, sondern nur den Header reparieren, damit ffmpeg den Fehler, der während der ursprünglichen Kodierung aufgetreten ist, richtig erkennen und sie richtig abspielen kann.
Also zunächst einmal ichhabe die statische Binärdatei heruntergeladen, die die neueste Version von ffmpeg, v4, enthält. Ich habe diese Binärdatei mit ffmpeg4
auf meinem System verknüpft, damit ich kontrollieren kann, welche Version ich verwende. Wir brauchen einige der neuen Funktionen, die nach 2.8 eingeführt wurden (ich bin mir nicht sicher, wann genau). Wenn Sie bereits eine neuere Version von ffmpeg installiert haben, verwenden Sie einfach diese und ersetzen Sie sie ffmpeg4
durch ffmpeg
in den folgenden Befehlen.
Extrahieren Sie nun den Roh-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 Flag h264_mp4toannexb notwendig ist,es kann automatisch eingefügt werdenfür dieses Format.
Nun packen wir 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 habe auch festgestellt, dass ich die Bildrate manuell auf 30 fps ( -r 30
) einstellen musste, da sonst eine variable Bildrate zwischen 25 und 30 fps vermutet wurde. Ich weiß nicht, wie ich die Zeitstempel richtig extrahieren oder sie richtig in den neuen Container muxen kann. Bitte lassen Sie mich wissen, wenn Sie eine Lösung haben! Viele Leute empfehlen es, -fflags +genpts
aber das funktioniert nichtscheinen etwas zu tunfür mich. Schließlich habe ich hinzugefügt, -avoid_negative_ts 1
damit der Zeitstempel des ersten Frames nicht negativ ist.
Wenn Sie die Ergebnisse schließlich in einen MKV-Container packen möchten (optional), können Sie dies tun
ffmpeg4 -i FIXED.mp4 -c copy FIXED.mkv
WarumKonvertieren Sie zuerst in MP4 und dann in MKV? Es scheint, dass der MKV-Container ohne Zeitstempel einfach die Fortsetzung verweigert, MP4 jedoch schon und gibt lediglich Warnungen aus. Dann können Sie ohne Warnungen in MKV konvertieren.
Nach all dem habe ich also funktionierende MP4- und MKV-Dateien. Ich habe jedoch einige Frames überprüft und es gibt geringfügige Änderungen (Luminanzänderungen in der Größenordnung von ~2 Stufen). Ich verstehe nicht, warum das passiert ist, denn es hätte verlustfrei sein sollen. Bitte lassen Sie es mich wissen, wenn Sie Vorschläge haben, wie dies besser gemacht werden kann.
Bearbeiten: Mir ist aufgefallen, dass einige meiner Zeitstempel im MP4-Container negativ waren und bei -0,066667 s begannen. Nach dem Wechsel in einen MKV-Container wurden alle negativen Zeitstempel zu Nullen. Durch Hinzufügen -output_ts_offset 0.066667
zum Befehl wurde dies behoben und sie beginnen bei Null. Ich verstehe jedoch nicht, warum es bei -0,066667 begann.
Bearbeitung 2: Eine bessere Möglichkeit, negative Zeitstempel zu entfernen, besteht darin, beim Kodieren der MP4-Datei „-avoid_negative_ts 1“ zu verwenden.