基本的な質問: 科学的なビデオデータをロスレスで保存/アーカイブするための適切なコーデックは何ですか?
私は顕微鏡で記録されたいくつかのビデオを保存/アーカイブすることで私の研究グループを助けようとしています。これらの(グレースケール)ビデオは、非圧縮(rawvideo)BGR24形式、660x492 @ 61fpsで、通常は約1分です。私の研究室の仲間は、これらのファイルの膨大なサイズ(それぞれギガバイト)に夢中になっています。ロスレスコーデックを使用して圧縮することを提案しました。(ここでのロスレスの必要性は、ビデオが科学的なデータであるためです。したがって、非可逆コーデックがコンテンツを不適切な方法または予期しない方法で変更する危険性があります。)
これが私が試したものです。まず、これらのビデオの最初の10秒を取得し、FFMpegを使用してモノクロ(生)形式に変換しました。
ffmpeg -t 10 -i RecordedData.avi -c:v rawvideo -pix_fmt gray raw_gray.mkv
次に、-crf 0
結果のファイルを圧縮するためにlibx264の可逆モードを(を設定することにより)使用しようとしました
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)チャネルは空である必要があります。
本当に何かを失っている場合、これを修正するために私にできることはありますか?データに適した別の(可逆)コーデックはありますか?
Update 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小さくなっています。同じことが、ファイルを少し深く掘り下げた場合にも見られます。
Update 2:libx264をRGBモードで使用している場合、以下に加えて上記と同じことを行うことで、元のバージョンと完全に一致させることができます。
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
はの約3倍x264-yuv420.mkv
であるため、RGBモードでの圧縮はそれほど良くありません。
libx264はYUVモードでグレースケールビデオを効率的に圧縮するということをどこかで読んだことがあります。Yチャネルだけが実際の情報を含んでいるという事実をピックアップするからです(モノクロビデオの場合、UチャネルとVチャネルはどちらもゼロです)。RGBモードでは、すべてのチャンネルにモノクロ入力用の同じ情報が含まれていると思います。おそらくlibx264rgbはそれを利用していません。
それで、私はビデオを変更せずにYUVモードを使用する方法があります、これは圧縮の方がはるかに効率的だからです?
更新3:の-pix_fmt yuvj420p
代わりにを使用することにより、libx264の問題を解決できました-pix_fmt yuv420p -color_range pc
。次に、圧縮/解凍後の元のファイルを正確に再現します。FFmpegのドキュメントから、これら2つのフラグのセットは同等であるという印象がありましたが、明らかにそうではありません。唯一の問題は、後者のフラグのセットで警告が表示されることです[swscaler @ 0x55b56347fe20] deprecated pixel format used, make sure you set the range correctly
。また、自分の問題に関連している可能性があるこのバグレポートを見つけました。私は明らかに非推奨のyuvj420pピクセル形式を使用せずに物事を行う「適切な」方法がわかりません。
compare
を使用してそれらを比較することもできます。
ffmpeg -i RecordedData.avi
。libx264rgbはbgr24をサポートしているため、そのエンコーダーをオプションと見なすことができます。
hexdump
)、その上でdiffを実行することをお勧めします。diff
単にファイルがどこか違うと言うだけです。1ビット、1メガバイト、すべて同じです。16進数のdiffを調べることにより、何が起こったのか、そして何が心配なのかをより正確に推定できます。また、操作によってビデオの幅または高さが丸められていないことも確認してください(これは偶然起こりました)。