使用无损视频编解码器归档(单色)科学视频数据

Nic*_* C. 10 video compression codec ffmpeg

基本问题: 以无损方式存储/存档科学视频数据的合适编解码器是什么

我正在尝试帮助我的研究小组存储/存档一些用显微镜记录的视频。这些(灰度)视频采用未压缩(原始视频)BGR24 格式,660x492@61fps,通常时长约 1 分钟。我的实验室伙伴们对这些文件的庞大规模(每个千兆字节)感到疯狂。我建议使用无损编解码器压缩它们。(这里需要无损是因为视频是科学数据;因此有损编解码器可能会以不良/意外方式改变内容。)

这是我尝试过的。首先,我抓取了其中一个视频的前 10 秒,并使用 FFMpeg 转换为单色(原始)格式。

ffmpeg -t 10 -i RecordedData.avi -c:v rawvideo -pix_fmt gray raw_gray.mkv
Run Code Online (Sandbox Code Playgroud)

然后,我尝试使用 libx264 的无损模式(通过设置-crf 0)来压缩生成的文件

ffmpeg -i raw-gray.mkv -c:v libx264 -crf 0 -pix_fmt yuv420p -color_range pc x264-yuv420p.mkv
Run Code Online (Sandbox Code Playgroud)

最后,我从 raw 和 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
Run Code Online (Sandbox Code Playgroud)

在这里,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
Run Code Online (Sandbox Code Playgroud)

前一个文件中的值比后一个文件中的值小 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
Run Code Online (Sandbox Code Playgroud)

最后一个命令报告这两个文件是相同的。不幸的是,x264-bgr24.mkv大约比 大 3 倍x264-yuv420.mkv,因此 RGB 模式下的压缩效果不佳。

我在某处读到 libx264 在 YUV 模式下有效地压缩灰度视频,因为它发现只有 Y 通道包含任何真实信息(单色视频的 U 和 V 通道都为零)这一事实。在 RGB 模式下,我相信所有通道都会包含相同的单色输入信息。也许 libx264rgb 没有利用这一点。

那么,有没有办法让我在不改变视频的情况下使用 YUV 模式,因为这种方式压缩效率更高?


更新 3:我能够通过使用 libx264-pix_fmt yuvj420p代替-pix_fmt yuv420p -color_range pc. 然后,我在压缩/解压缩后完全复制原始文件。从 FFmpeg 文档中,我的印象是这两组标志是等效的,但显然情况并非如此。唯一的问题是我收到了后一组标志的警告:[swscaler @ 0x55b56347fe20] deprecated pixel format used, make sure you set the range correctly. 另外,我发现这个错误报告可能与我的问题有关。我不确定在不使用明显已弃用的 yuvj420p 像素格式的情况下做事的“正确”方式。

slh*_*hck 7

这不是您实际问题的直接答案,但我会考虑使用 FFmpeg 内部FFV1编解码器:

$ ffmpeg -i raw-gray.mkv -c:v ffv1 ffv1.mkv
Run Code Online (Sandbox Code Playgroud)

或者,它的第 3 版:

$ ffmpeg -i raw-gray.mkv -c:v ffv1 -level 3 ffv1.mkv
Run Code Online (Sandbox Code Playgroud)

然后:

$ 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
Run Code Online (Sandbox Code Playgroud)

使用 时yuv420p,它在无损模式下不如 libx264 有效,但它比使用 libx264 更有效bgr24(在我的测试中,数据速率介于两者之间)。国会图书馆等一些机构也承认 FFV1 是一种合适的保存格式