Настройки h264 для больших плоских областей с медленно меняющимся цветом

Я делаю анимацию для проекционного мэппинга, который имитирует солнце, отбрасывающее тени на строение, когда оно движется по небу. По сути, это просто большие плоские области цвета, которые меняются примерно за пять минут по мере восхода и захода «солнца» (в другой проекции). Он воспроизводится с помощью устройства воспроизведения Brightsign, и я использую основной профиль h.264 в качестве кодека в mp4.

Проблема, с которой я сталкиваюсь, заключается в том, что кодировка не очень хорошо справляется с контентом. Несмотря на то, что цвет абсолютно плоский, когда все пиксели меняют значение с течением времени, я получаю полосы шума и появляются блоки. Они тонкие, но они раздражают.

Есть ли какая-либо настройка, которую я могу сделать с помощью libx264, чтобы оптимизировать ее для больших плоских областей цвета, где все пиксели одновременно меняются с течением времени? В кадре абсолютно нет движения, просто меняется цвет всей области, причем довольно медленно.

Моя текущая команда ffmpeg довольно общая:

ffmpg -i input.mov -c:v libx264 -preset slow -profile main -crf 20 -pix_fmt yuv420p -an output.mp4
Пожалуйста, включите полный ffmpegвывод консоли. Можете ли вы предоставить краткий образец ввода? Помогает ли уменьшение -crfдо ~ 18? Имеет ли -tune animationзначение? Если ничего не помогает, вы можете изучить использование gradfunвидеофильтра при воспроизведении.

Ответы (3)

Полосы, о которых вы говорите, вполне могут быть просто ограничением 8-битного цветового пространства.

Теоретически способ решить эту проблему заключается в использовании 10- или 12-битного цветового пространства на каждом этапе от рендеринга до редактирования и мастеринга, до вывода и даже на экране или проекторе. Однако ваш окончательный вывод, вероятно, будет отображаться в 8-битном пространстве на канал, нравится вам это или нет.

Таким образом, практичный способ сделать это — выполнить рендеринг с 10- или 12-битным цветом и дизерингом до 8-битного от мастера. Дизеринг предотвратит визуальное появление полос при отображении 8 бит на канал.

Обратите внимание, что это ограничение не для h.264 или любого кодировщика, а для используемого цветового пространства и бесшумного характера визуализируемой анимации; если бы реальная жизнь была такой свободной от шума, она также показывала бы эти полосы в 8-битных цветовых пространствах. Маловероятно, что в вашем кодировщике есть какие-либо настройки, чтобы решить эту проблему. Для подтверждения выполните рендеринг в несжатый формат, и вы, вероятно, все равно увидите полосатость.

Примечание: дизеринг из 10- или 12-битного рендеринга — это не то же самое, что просто добавить немного шума к существующему 8-битному дизерингу — хотя это может немного замаскировать полосатость, просто сделав ее менее отчетливой, это не решает ее. . Но вы могли бы сделать это в крайнем случае.

спасибо, но это, вероятно, не ограничения 8-битного вывода. Полосатость происходит с градиентами. Это плоские области цвета, в которых каждый пиксель имеет одинаковое значение. Сжатие вводит полосы, поскольку пиксели изменяются во времени.
В таком случае вы играли с более низкими значениями CRF? 20 может быть непрозрачным в основном плоских цветных областях с анимацией. С визуализированной анимацией вы сможете обойтись гораздо более низкими значениями CRF (например, 16). Вы можете протестировать что-то очень высокое качество, например 10 или даже без потерь, просто в качестве точки устранения неполадок, чтобы увидеть, является ли квантование фактором вообще.

В зависимости от того, как было создано содержимое, полоса может появиться при преобразовании содержимого из цветового пространства RGB в YUV. Вы можете попытаться сделать h264, сохраняя цветовое пространство RGB, хотя я читал, что это непросто. Можно ли использовать другой кодек?

Первое, что я бы попробовал, это добавить -force_key_framesк исходной команде, удалить предустановку и уменьшить -crfзначение. В следующем примере ключевой кадр задается каждую секунду.

ffmpg -i input.mov -c:v libx264 -profile main \
    -force_key_frames expr:gte(t,n_forced*1) \
    -crf 15 -pix_fmt yuv420p -an output.mp4

В качестве второго средства я бы использовал серию изображений png (вместо mov) в качестве входных данных и использовал очень низкий crf. Таким образом, вы действительно можете убедиться, что во входных данных нет полос, а в конечном материале высочайшее качество. Если вы не можете напрямую выполнить рендеринг в png, конвертируйте исходный материал.

Вот пример:

# turn the original into pngs
ffmpeg -i input.mov -f image2 -threads 0 /tmp/%05d.png

# turn the pngs back into mp4 (assuming 25 fps)
ffmpeg -ar 48000 -ac 2 -f s16le -i /dev/zero -r 25/1 -f image2 \
  -i /tmp/%05d.png -c:a libfdk_aac -c:v libx264 \ 
  -profile main -vf "fps=fps=25" -force_key_frames expr:gte(t,n_forced*1) \
  -crf 10 -threads 0 -pix_fmt yuv420p output.mp4

пс. Вы должны иметь привычку включать беззвучную звуковую дорожку для воспроизведения мультимедийного устройства из-за проблем с синхронизацией.