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 ffmpeg4
meinem 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 ffmpeg4
mit ffmpeg
den 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 +genpts
aber 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.066667
das 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.