Câu hỏi cơ bản: một codec phù hợp để lưu trữ / lưu trữ dữ liệu video khoa học một cách dễ dàng ?
Tôi đang cố gắng giúp nhóm nghiên cứu của mình thực hiện việc lưu trữ / lưu trữ một số video được ghi lại bằng kính hiển vi. Các video (thang độ xám) này ở định dạng BGR24 không nén (rawvideo), 660x492 @ 61fps và thường dài khoảng 1 phút. Những người bạn trong phòng thí nghiệm của tôi đang phát điên với kích thước tuyệt đối của những tập tin này (mỗi gigabyte). Tôi đề nghị nén chúng bằng cách sử dụng codec không mất dữ liệu. .
Đây là những gì tôi đã cố gắng. Đầu tiên, tôi lấy 10 giây đầu tiên của một trong những video này và chuyển đổi sang định dạng đơn sắc (thô) bằng FFMpeg.
ffmpeg -t 10 -i RecordedData.avi -c:v rawvideo -pix_fmt gray raw_gray.mkv
Sau đó, tôi đã cố gắng sử dụng chế độ lossless của libx264 (bằng cách cài đặt -crf 0
) để nén tệp kết quả
ffmpeg -i raw-gray.mkv -c:v libx264 -crf 0 -pix_fmt yuv420p -color_range pc x264-yuv420p.mkv
Cuối cùng, tôi trích xuất dữ liệu YUV thô từ cả tệp MKV thô và h264 và so sánh chúng.
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
Đây, diff
lệnh báo cáo rằng các tệp khác nhau khi tôi mong đợi chúng giống nhau. Tại sao lại thế này? Đây có phải chỉ là một số lỗi làm tròn nhẹ, hoặc tôi có thể mất thứ gì đó sau khi thực hiện nén H264 (được cho là không mất)? Có một số chuyển đổi định dạng pixel xảy ra ( gray (YUV400) <-> YUV420
), nhưng các kênh màu (UV) chỉ nên trống vì đầu vào là đơn sắc.
Nếu tôi thực sự đang mất một cái gì đó, tôi có thể làm gì để khắc phục điều này? Có một codec (lossless) nào có thể phù hợp hơn với dữ liệu của tôi không?
Cập nhật 1 :
Tôi đã sử dụng hexdump để so sánh nội dung của dữ liệu YUV không nén từ raw-gray.yuv
(không bao giờ nén) và x264-decompressed.yuv
(nén và sau đó giải nén) chi tiết hơn. Dưới đây là một vài byte đầu tiên.
[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
Các giá trị từ tệp trước ít hơn 4 đến 5 so với các giá trị trong tệp sau. Điều tương tự được tìm thấy đào sâu hơn một chút vào tập tin.
Cập nhật 2 : Nếu tôi sử dụng libx264 ở chế độ RGB, tôi có thể có được kết quả khớp chính xác với bản gốc bằng cách thực hiện tương tự như trên ngoài các thao tác sau.
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
Lệnh cuối cùng báo cáo rằng hai tệp là giống hệt nhau . Không may, x264-bgr24.mkv
lớn hơn khoảng 3 lần x264-yuv420.mkv
, do đó, nén ở chế độ RGB là không tốt.
Tôi đã đọc ở đâu đó rằng libx264 nén video thang độ xám một cách hiệu quả ở chế độ YUV bởi vì nó chỉ nhận ra thực tế là chỉ có kênh Y chứa bất kỳ thông tin thực nào (các kênh U và V đều bằng 0 đối với video đơn sắc). Ở chế độ RGB, tôi tin rằng tất cả các kênh sẽ chứa thông tin giống hệt nhau cho đầu vào đơn sắc. Có lẽ libx264rgb không tận dụng điều đó.
Vì thế, Có cách nào để tôi sử dụng chế độ YUV mà không thay đổi video không, vì cách nén này hiệu quả hơn nhiều theo cách này?
Cập nhật 3 :
Tôi đã có thể giải quyết vấn đề với libx264 bằng cách sử dụng -pix_fmt yuvj420p
thay vì -pix_fmt yuv420p -color_range pc
. Sau đó, tôi tái tạo tệp gốc chính xác sau khi nén / giải nén. Từ tài liệu FFmpeg, tôi có ấn tượng rằng hai bộ cờ này tương đương nhau, nhưng điều này rõ ràng không phải là trường hợp. Vấn đề duy nhất là tôi nhận được cảnh báo với bộ cờ sau: [swscaler @ 0x55b56347fe20] deprecated pixel format used, make sure you set the range correctly
. Ngoài ra, tôi tìm thấy điều này báo cáo lỗi điều đó có thể liên quan đến vấn đề của tôi Tôi không chắc chắn về cách "phù hợp" để làm mọi việc mà không sử dụng định dạng pixel yuvj420p rõ ràng không dùng nữa.
compare
để so sánh chúng.
hexdump
) và chạy diff trên đó.diff
sẽ chỉ đơn giản nói rằng các tập tin là một vài nơi khác nhau. Một bit, một megabyte, tất cả đều giống nhau. Bằng cách kiểm tra hex diff, bạn có thể ước tính tốt hơn những gì đã xảy ra và liệu có gì phải lo lắng không. Ngoài ra, hãy kiểm tra xem thao tác không làm tròn chiều rộng hoặc chiều cao của video (tôi đã xảy ra với tôi).