Grundlegende Frage: Was ist ein geeigneter Codec zum verlustfreien Speichern / Archivieren wissenschaftlicher Videodaten ?
Ich versuche meiner Forschungsgruppe beim Speichern / Archivieren einiger mit einem Mikroskop aufgenommener Videos zu helfen. Diese (Graustufen-) Videos haben das unkomprimierte (Rohvideo) BGR24-Format, 660 x 492 @ 61 fps und sind normalerweise etwa 1 Minute lang. Meine Laborkollegen sind verrückt nach der Größe dieser Dateien (jeweils Gigabyte). Ich schlug vor, sie mit einem verlustfreien Codec zu komprimieren. (Die Notwendigkeit für verlustfrei ist hier, weil die Videos wissenschaftliche Daten sind; daher besteht die Gefahr, dass ein verlustbehafteter Codec den Inhalt auf schlechte / unerwartete Weise verändert.)
Folgendes habe ich versucht. Zuerst habe ich die ersten 10 Sekunden eines dieser Videos aufgenommen und mit FFMpeg in ein monochromes (Roh-) Format konvertiert.
ffmpeg -t 10 -i RecordedData.avi -c:v rawvideo -pix_fmt gray raw_gray.mkv
Dann habe ich versucht, den verlustfreien Modus von libx264 (durch Einstellen -crf 0
) zu verwenden, um die resultierende Datei zu komprimieren
ffmpeg -i raw-gray.mkv -c:v libx264 -crf 0 -pix_fmt yuv420p -color_range pc x264-yuv420p.mkv
Schließlich habe ich die YUV-Rohdaten sowohl aus den Roh- als auch aus den h264-MKV-Dateien extrahiert und verglichen.
ffmpeg -i raw-gray.mkv -c:v rawvideo -pix_fmt gray raw-gray.yuv
ffmpeg -i x264-yuv420p.mkv -c:v rawvideo -pix_fmt gray x264-decompressed.yuv
diff -sq raw-gray.yuv x264-decompressed.yuv
Hier diff
meldet der Befehl, dass sich die Dateien unterscheiden, wenn ich erwartet habe, dass sie gleich sind. Warum ist das? Ist dies nur ein kleiner Rundungsfehler oder verliere ich möglicherweise etwas, nachdem ich die H264-Komprimierung (angeblich verlustfrei) durchgeführt habe? Es gibt einige Konvertierungen von Pixelformaten ( gray (YUV400) <-> YUV420
), aber die Farbkanäle (UV) sollten nur leer sein, da die Eingabe monochrom ist.
Wenn ich tatsächlich etwas verliere, kann ich irgendetwas tun, um dies zu beheben? Gibt es einen anderen (verlustfreien) Codec, der für meine Daten besser geeignet ist?
Update 1 : Ich habe hexdump verwendet, um den Inhalt der unkomprimierten YUV-Daten von raw-gray.yuv
(nie komprimiert) und x264-decompressed.yuv
(komprimiert und dann dekomprimiert) genauer zu vergleichen. Hier sind die ersten paar Bytes.
[raw-gray.yuv]
00000000 4e 50 51 53 53 52 51 50 51 51 50 4f 50 50 50 50
00000010 51 51 50 51 52 53 51 51 52 52 53 53 52 51 51 53
00000020 51 53 54 55 53 51 52 54 53 53 52 50 51 50 52 52
00000030 51 52 51 51 51 52 54 52 52 52 51 51 51 53 57 58
00000040 57 57 55 54 54 52 53 51 51 52 53 55 55 54 53 53
00000050 51 51 52 52 53 52 51 50 50 50 50 51 51 4f 4f 4e
00000060 4c 4d 4e 4d 4f 50 4f 50 51 51 51 52 52 52 52 50
00000070 50 50 52 52 53 55 55 55 57 52 53 53 53 54 56 56
[x264-decompressed.yuv]
00000000 53 55 56 57 57 56 56 55 56 56 55 54 55 55 55 55
00000010 56 56 55 56 56 57 56 56 56 56 57 57 56 56 56 57
00000020 56 57 58 59 57 56 56 58 57 57 56 55 56 55 56 56
00000030 56 56 56 56 56 56 58 56 56 56 56 56 56 57 5b 5c
00000040 5b 5b 59 58 58 56 57 56 56 56 57 59 59 58 57 57
00000050 56 56 56 56 57 56 56 55 55 55 55 56 56 54 54 53
00000060 51 52 53 52 54 55 54 55 56 56 56 56 56 56 56 55
00000070 55 55 56 56 57 59 59 59 5b 56 57 57 57 58 5a 5a
Die Werte aus der ersteren Datei sind 4 bis 5 niedriger als die Werte in der letzteren. Das gleiche wird gefunden, wenn man etwas tiefer in die Datei gräbt.
Update 2 : Wenn ich libx264 im RGB-Modus verwende, kann ich eine exakte Übereinstimmung mit dem Original erzielen, indem ich zusätzlich zu den folgenden Schritten wie oben beschrieben vorgehe.
ffmpeg -i raw-gray.mkv -c:v libx264rgb -crf 0 -pix_fmt bgr24 x264-bgr24.mkv
ffmpeg -i x264-bgr24.mkv -c:v rawvideo -pix_fmt gray x264-bgr24-decomp.yuv
diff -sq raw-gray.yuv x264-bgr24-decomp.yuv
Der letzte Befehl meldet, dass die beiden Dateien identisch sind . Leider x264-bgr24.mkv
ist etwa dreimal größer als x264-yuv420.mkv
, so dass die Komprimierung im RGB-Modus nicht so gut ist.
Ich habe irgendwo gelesen, dass libx264 Graustufenvideos im YUV-Modus effizient komprimiert, weil es die Tatsache aufgreift, dass nur der Y-Kanal echte Informationen enthält (U- und V-Kanäle sind für monochrome Videos beide Null). Im RGB-Modus würden meiner Meinung nach alle Kanäle identische Informationen für die Monochrom-Eingabe enthalten. Vielleicht nutzt libx264rgb das nicht aus.
Gibt es für mich eine Möglichkeit, den YUV-Modus zu verwenden, ohne das Video zu ändern, da die Komprimierung auf diese Weise viel effizienter ist?
Update 3 : Ich konnte das Problem mit libx264 lösen, indem ich -pix_fmt yuvj420p
anstelle von -pix_fmt yuv420p -color_range pc
. Dann reproduziere ich die Originaldatei genau nach der Komprimierung / Dekomprimierung. Aus der FFmpeg-Dokumentation hatte ich den Eindruck, dass diese beiden Flaggensätze gleichwertig waren, aber dies ist offensichtlich nicht der Fall. Das einzige Problem ist, dass ich mit den letzteren Flags eine Warnung erhalte : [swscaler @ 0x55b56347fe20] deprecated pixel format used, make sure you set the range correctly
. Außerdem habe ich diesen Fehlerbericht gefunden, der mit meinem Problem zusammenhängen könnte. Ich bin mir nicht sicher, wie ich Dinge "richtig" machen soll, ohne das anscheinend veraltete Pixelformat yuvj420p zu verwenden.
compare
und sie mit Imagemagicks zu vergleichen.
hexdump
) und das Diff darauf ausführen.diff
Ich werde einfach sagen, dass die Dateien irgendwo anders sind. Ein Bit, ein Megabyte, es ist alles das Gleiche. Wenn Sie den Hex-Diff untersuchen, können Sie besser abschätzen, was passiert ist und ob Sie sich Sorgen machen müssen. Überprüfen Sie auch, ob der Vorgang die Breite oder Höhe des Videos nicht abgerundet hat (mir ist das passiert).