Использование видеокодека без потерь для архивирования (монохромных) научных видеоданных

9

Основной вопрос: какой кодек подходит для хранения / архивирования научных видеоданных без потерь ?

Я пытаюсь помочь моей исследовательской группе в хранении / архивировании некоторых видео, записанных под микроскопом. Это видео (в градациях серого) в несжатом (rawvideo) формате BGR24, 660x492 при 61 кадр / с и обычно длиной около 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-файлов и сравнил их.

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), но цветные (УФ) каналы должны быть просто пустыми, потому что вход является монохромным.

Если я действительно что-то теряю, могу ли я что-нибудь сделать, чтобы это исправить? Есть ли другой (без потерь) кодек, который может быть более подходящим для моих данных?


Обновление 1 : я использовал hexdump для более подробного сравнения содержимого несжатых данных YUV из raw-gray.yuv(никогда не сжатых) и x264-decompressed.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 : если я использую 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

Последняя команда сообщает, что два файла идентичны . К сожалению, 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.

Ник С.
источник
1
Поскольку данные распакованы, вам будет лучше, если вы преобразуете их в текстовый формат (например, с помощью hexdump) и запускаете diff. diffпросто скажу, что файлы где-то разные. Один бит, один мегабайт, это все то же самое. Изучив шестнадцатеричный дифференциал, вы сможете лучше оценить, что произошло и стоит ли беспокоиться. Также убедитесь, что операция не округляет ширину или высоту видео (у меня такое было со мной).
LSerni
1
Одним из возможных источников нарушения может быть другое зажимание Y-канала (согласно CCIR-601). Проверьте, случайно ли вы потеряли значения Y ниже 16 и выше 240. См. Также video.stackexchange.com/questions/16840/…
LSerni
1
Вы также можете использовать ffmpeg, чтобы разложить два видео на отдельные изображения и использовать imagemagickcompare для их сравнения.
ксеноид
1
Хороший способ сравнить потери без потерь - использовать хеш- муксер. Показать полный вывод ffmpeg -i RecordedData.avi. libx264rgb поддерживает bgr24, поэтому вы можете рассмотреть этот кодировщик как вариант.
Илоган
1
Просто закодируйте их без потерь, используя режим RGB x264 (пропустите преобразование формата пикселей).
Гьян

Ответы:

6

Это не прямой ответ на вашу реальную проблему, но я хотел бы рассмотреть возможность использования внутреннего FFV1кодека FFmpeg :

$ 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

Он не так эффективен, как libx264 в режиме без потерь при использовании yuv420p, но он более эффективен, чем использование libx264 с bgr24(в моих тестах скорость передачи данных была где-то посередине). Некоторые учреждения, такие как Библиотека Конгресса, также признают FFV1 подходящим форматом сохранения .

slhck
источник
Это ответ на мой первоначальный основной вопрос, который я отредактировал, чтобы прояснить. С FFV1 проблем не возникало. Фактически, FFV1 достиг примерно той же степени сжатия, что и libx264 (w / -crf 0 -preset medium) для моего конкретного видео, и это было быстрее. Более того, он напрямую поддерживает grayформат пикселей. Действительно, это кажется отличным решением.
Ник С.