web-dev-qa-db-ja.com

ロスレスビデオコーデックを使用して(モノクロ)科学ビデオデータをアーカイブする

基本的な質問:ロスレス方式で科学ビデオデータを保存/アーカイブするための適切なコーデックは何ですか?

私は顕微鏡で記録されたいくつかのビデオを保存/アーカイブすることで私の研究グループを助けようとしています。これらの(グレースケール)ビデオは、非圧縮(rawvideo)BGR24形式、660x492 @ 61fpsで、通常は約1分です。私の研究室の仲間は、これらのファイルの膨大なサイズ(それぞれギガバイト)に夢中になっています。ロスレスコーデックを使用して圧縮することを提案しました。 (ここでのロスレスの必要性は、ビデオが科学的データであるためです。したがって、損失のあるコーデックがコンテンツを不適切な方法または予期しない方法で変更する危険性があります。)

これが私が試したものです。まず、これらのビデオの最初の10秒を取得し、FFMpegを使用してモノクロ(生)形式に変換しました。

_ffmpeg -t 10 -i RecordedData.avi -c:v rawvideo -pix_fmt gray raw_gray.mkv
_

次に、libx264のロスレスモードを使用して(_-crf 0_を設定して)、結果のファイルを圧縮しようとしました

_ffmpeg -i raw-gray.mkv -c:v libx264 -crf 0 -pix_fmt yuv420p -color_range pc x264-yuv420p.mkv
_

最後に、未加工のYUVデータとh264 MKVファイルの両方から未加工のYUVデータを抽出して比較しました。

_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
_

ここで、diffコマンドは、ファイルが同じであると予想していたのに、ファイルが異なると報告しています。これはなぜですか?これはほんのわずかな丸め誤差ですか、それともH264(おそらくロスレス)圧縮を実行した後に何かを失う可能性がありますか?ピクセル形式の変換が行われていますが(gray (YUV400) <-> YUV420)、入力がモノクロであるため、カラー(UV)チャネルは空である必要があります。

本当に何かを失っている場合、これを修正するために私にできることはありますか?データに適した別の(可逆)コーデックはありますか?


更新1:hexdumpを使用して、_raw-gray.yuv_(圧縮されていない)と_x264-decompressed.yuv_(からの非圧縮YUVデータの内容を比較しました圧縮してから解凍します)。ここに最初の数バイトがあります。

_[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
_

前者のファイルの値は、後者の値よりも4〜5小さくなります。同じことが、ファイルを少し深く掘り下げた場合にも見られます。


アップデート2:RGBモードでlibx264を使用している場合、以下に加えて上記と同じことを行うことで、元のファイルと完全に一致させることができます。

_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
_

最後のコマンドは、2つのファイルが同一であることを報告します。残念ながら、_x264-bgr24.mkv_は_x264-yuv420.mkv_の約3倍であるため、RGBモードでの圧縮はあまり良くありません。

Libx264はYUVモードでグレースケールビデオを効率的に圧縮するということをどこかで読みました。これは、Yチャネルのみが実際の情報を含んでいるという事実をピックアップするためです(モノクロビデオの場合、UチャネルとVチャネルはどちらもゼロです)。 RGBモードでは、すべてのチャンネルにモノクロ入力用の同じ情報が含まれていると思います。多分libx264rgbはそれを利用していません。

したがって、この方法で圧縮を行う方がはるかに効率的であるため、ビデオを変更せずにYUVモードを使用する方法はありますか?


更新3:_-pix_fmt yuvj420p_の代わりに_-pix_fmt yuv420p -color_range pc_を使用することにより、libx264の問題を解決できました。次に、圧縮/解凍後の元のファイルを正確に再現します。 FFmpegのドキュメントから、これらの2つのフラグセットは同等であるという印象がありましたが、明らかにそうではありません。唯一の問題は、後者のフラグセット__[swscaler @ 0x55b56347fe20] deprecated pixel format used, make sure you set the range correctly_で警告が表示されることです。また、私はこれを発見しました バグレポート これは私の問題に関連している可能性があります。私は明らかに廃止されたyuvj420pピクセル形式を使用せずに物事を行う「適切な」方法がわかりません。

9
Nick C.

これは実際の問題に対する簡単な答えではありませんが、FFmpegの内部FFV1コーデックの使用を検討します。

$ ffmpeg -i raw-gray.mkv -c:v ffv1 ffv1.mkv

または、そのバージョン3:

$ ffmpeg -i raw-gray.mkv -c:v ffv1 -level 3 ffv1.mkv

次に:

$ ffmpeg -i ffv1.mkv -c:v rawvideo -pix_fmt gray raw-gray.yuv
$ diff -sq raw-ffv1.yuv raw-gray.yuv
Files raw-ffv1.yuv and raw-gray.yuv are identical

yuv420pを使用すると、ロスレスモードのlibx264ほど効率的ではありませんが、bgr24でlibx264を使用するよりも効率的です(私のテストでは、データレートはその中間にありました)。米国議会図書館のような一部の機関も、FFV1を 適切な保存形式 として認識しています。

6
slhck