Pertanyaan dasar: apa codec yang cocok untuk menyimpan / mengarsipkan data video ilmiah dengan cara lossless ?
Saya mencoba untuk membantu kelompok riset saya dengan menyimpan / mengarsipkan beberapa video yang direkam dengan mikroskop. Video (skala abu-abu) ini dalam format BGR24 (mentah video) terkompresi, 660x492 @ 61fps, dan biasanya berdurasi sekitar 1 menit. Teman-teman lab saya menjadi gila dengan ukuran file-file ini (masing-masing gigabytes). Saya menyarankan untuk mengompres mereka menggunakan codec lossless. (Kebutuhan untuk lossless di sini adalah karena video adalah data ilmiah; karenanya ada beberapa bahaya bahwa codec yang hilang dapat mengubah konten dengan cara yang buruk / tidak terduga.)
Inilah yang saya coba. Pertama, saya mengambil 10 detik pertama dari salah satu video ini dan dikonversi ke format monokrom (mentah) menggunakan FFMpeg.
ffmpeg -t 10 -i RecordedData.avi -c:v rawvideo -pix_fmt gray raw_gray.mkv
Kemudian, saya mencoba menggunakan mode lossless libx264 (dengan mengatur -crf 0
) untuk mengkompres file yang dihasilkan
ffmpeg -i raw-gray.mkv -c:v libx264 -crf 0 -pix_fmt yuv420p -color_range pc x264-yuv420p.mkv
Akhirnya, saya mengekstrak data YUV mentah dari file MKV mentah dan h264 dan membandingkannya.
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
Di sini, diff
perintah melaporkan bahwa file berbeda ketika saya berharap mereka akan sama. Kenapa ini? Apakah ini hanya sedikit kesalahan pembulatan, atau apakah saya mungkin kehilangan sesuatu setelah melakukan kompresi H264 (seharusnya lossless)? Ada beberapa konversi format piksel yang terjadi ( gray (YUV400) <-> YUV420
), tetapi saluran warna (UV) seharusnya kosong karena inputnya adalah monokrom.
Jika saya memang kehilangan sesuatu, adakah yang bisa saya lakukan untuk memperbaikinya? Apakah ada codec (lossless) lain yang mungkin lebih sesuai untuk data saya?
Pembaruan 1 : Saya menggunakan hexdump untuk membandingkan konten data YUV yang tidak terkompresi dari raw-gray.yuv
(tidak pernah dikompresi) dan x264-decompressed.yuv
(dikompresi dan kemudian didekompresi) secara lebih rinci. Berikut adalah beberapa byte pertama.
[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
Nilai-nilai dari file sebelumnya adalah 4 sampai 5 kurang dari nilai-nilai di yang terakhir. Hal yang sama ditemukan menggali sedikit lebih dalam ke dalam file.
Pembaruan 2 : Jika saya menggunakan libx264 dalam mode RGB, saya bisa mendapatkan kecocokan persis dengan aslinya dengan melakukan hal yang sama seperti di atas selain yang berikut ini.
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
Perintah terakhir melaporkan bahwa kedua file itu identik . Sayangnya, x264-bgr24.mkv
sekitar 3 kali lebih besar dari itu x264-yuv420.mkv
, jadi kompresi dalam mode RGB tidak sebaik.
Saya membaca di suatu tempat bahwa libx264 memampatkan video skala abu-abu secara efisien dalam mode YUV karena mengambil fakta bahwa hanya saluran Y yang berisi informasi nyata (saluran U dan V sama-sama nol untuk video monokrom). Dalam mode RGB, saya yakin semua saluran akan berisi info identik untuk input monokrom. Mungkin libx264rgb tidak memanfaatkan itu.
Jadi, apakah ada cara bagi saya untuk menggunakan mode YUV tanpa mengubah video, karena kompresi jauh lebih efisien dengan cara ini?
Pembaruan 3 : Saya bisa menyelesaikan masalah dengan libx264 dengan menggunakan -pix_fmt yuvj420p
alih-alih -pix_fmt yuv420p -color_range pc
. Kemudian, saya mereproduksi file asli tepat setelah kompresi / dekompresi. Dari dokumentasi FFmpeg, saya mendapat kesan bahwa dua set bendera ini setara, tetapi ini ternyata tidak terjadi. Satu-satunya masalah adalah bahwa saya mendapatkan peringatan dengan set kedua bendera: [swscaler @ 0x55b56347fe20] deprecated pixel format used, make sure you set the range correctly
. Juga, saya menemukan laporan bug ini yang mungkin terkait dengan masalah saya. Saya tidak yakin tentang cara yang "tepat" untuk melakukan sesuatu tanpa menggunakan format piksel yuvj420p yang tampaknya sudah usang.
compare
untuk membandingkannya.
hexdump
) dan menjalankan diffnya.diff
hanya akan mengatakan bahwa file-file tersebut di suatu tempat berbeda. Satu bit, satu megabyte, semuanya sama saja. Dengan memeriksa hex diff, Anda dapat memperkirakan dengan lebih baik apa yang terjadi dan apakah perlu khawatir. Juga periksa apakah operasi tidak membulatkan lebar atau tinggi video (saya punya itu terjadi pada saya).