Я создаю короткие уроки, записывая свой экран (720p30fps). Контент представляет собой просто запись использования некоторого программного обеспечения для настольных компьютеров - например, перемещение мыши и открытие диалогов, набор текста, рисование фигур и т. д. Никаких высокоскоростных действий, как в игре, никаких живых кадров, никакой говорящей головы или чего-то подобного. После базового редактирования исходной записи экрана я хочу закодировать видео в форматы webm и mp4 с точно таким же разрешением и частотой кадров, которые я записал, и я хочу, чтобы качество воспроизведения было как можно ближе к исходному качеству записи. Таким образом, после окончательного кодирования не должно быть видимых артефактов сжатия.
По поводу исходной записи: Разрешение 1280x720 пикселей. Частота кадров составляет 30 кадров в секунду. Программное обеспечение для записи — Simple Screen Recorder. Кодирование — H.264 с коэффициентом постоянной скорости 10 (достаточно близко к без потерь) в контейнере Matroska. При воспроизведении оригинала артефактов нет вообще.
Затем я добавляю несколько очень простых эффектов, таких как плавное затухание и наложение текста, к исходному MKV с помощью блендера. Затем визуализируйте в последовательность изображений (формат PNG). Я использую высококачественный экспорт изображений из Blender, и снова на выходных изображениях нет признаков артефактов сжатия.
Проблема возникает после того, как я кодирую последовательность изображений в видео mp4, используя кодировщик x264 с ffmpeg. Иногда некоторые части некоторых жестких краев/очертаний формы мерцают. Это не движущиеся объекты. Они неподвижны на заднем плане по сравнению с тем, где движется мышь. Кажется случайным. Например, у меня могут быть два желтых прямоугольника рядом, каждый с черным контуром, и только верхняя часть одного из контуров прямоугольника мерцает в течение нескольких кадров, а затем останавливается. Это немного отвлекает и уродливо для того, что должно быть действительно чистым/простым кодированием, основанным на записи экрана.
Я обычно вижу это для горизонтальных темных линий / резких краев. Иногда я видел подобное для вертикальных краев.
Я еще не заметил этой проблемы с выходными файлами webm, созданными ffmpeg, только с файлами mp4, закодированными x264. Команда ffmpeg, которую я использую, выглядит так:
ffmpeg -speed 1 -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -pix_fmt yuv420p -movflags +faststart -crf 22 -r 30 -g 300 -y myvideo.mp4
Для webm я использую ту же базовую команду и то же значение crf, но, очевидно, другой кодировщик (libvpx-vp9). Файл webm составляет около 9+ МБ для 2 минут отснятого материала. Размер mp4 составляет около 3,5 МБ. Как правило, качество между ними невозможно различить, только в те моменты, когда в mp4 мерцают некоторые сегменты жесткой линии.
Я примерно проиллюстрировал проблему ниже, используя ASCII-графику, где я пытаюсь показать один прямоугольник на четырех кадрах. Сначала это нормально, затем для некоторых кадров часть контура прямоугольника рисуется с некоторой дополнительной толщиной в некоторых частях, заставляя его немного мерцать или покачиваться. Потом снова становится идеально.
-----------------
| |
-----------------
------=====------
| |
-----------------
______=====______
| |
-----------------
-----------------
| |
-----------------
Сравните следующие изображения. Обратите внимание, что на втором изображении два нижних прямоугольника имеют дополнительную серую линию над или под частью их черной границы. Я захватил эти изображения, когда VLC воспроизводил мой mp4, закодированный x264, на 100% (без масштаба). Это не очень драматичный пример, но, надеюсь, этого достаточно, чтобы показать, что происходит. Поскольку лишние линии появляются и исчезают, создается эффект мерцания.
Ноты:
ffmpeg -speed 1 -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -coder ac -pix_fmt yuv420p -movflags +faststart -crf 22 -bf 16 -b_strategy 2 -refs 16 -direct-pred spatial -me_method umh -me_range 16 -r 30 -g 300 -y myvideo.mp4
(Легче заметить артефакты, если вы переключаетесь между двумя изображениями в исходном размере)
Как называется такой артефакт сжатия?
Какой флаг я могу передать ffmpeg, чтобы попытаться подавить его?
Много экспериментов с CRF и значениями скорости. Для CRF я снизил до 18, и это, кажется, немного уменьшает мерцание, но не устраняет его. Но этот коэффициент скорости кажется слишком низким, чтобы получить приличное кодирование контента, такого простого, как запись экрана с низким уровнем активности в 720p.
Я также пробовал вручную устанавливать b-кадры и эталонные кадры на значения от 1 до 16, варьировал размер гопов от 30 до 300 и пробовал разные значения для параметра -me_method. И я попробовал пару настроек деинтерлейса с помощью опции yadif, но я совершенно уверен, что это не имеет отношения к этой проблеме, и кажется, что это только ухудшает качество выходного видео. В итоге команды ffmpeg выглядят примерно так:
ffmpeg -speed 1 -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -coder ac -pix_fmt yuv420p -movflags +faststart -crf 22 -bf 16 -b_strategy 2 -refs 16 -direct-pred spatial -me_method umh -me_range 16 -r 30 -g 300 -y myvideo.mp4
Но до сих пор заметное влияние оказывало только изменение значения CRF. Я не хочу опускаться намного ниже, потому что это слишком сильно увеличит размер видео.
Я использовал приведенный выше пример с LibreOffice Draw и экраном 1280x720p для записи клипа продолжительностью около 47 секунд в файл MKV, закодированный H.264. Я импортировал это в Blender и сразу же экспортировал обратно в виде последовательности изображений PNG — без каких-либо эффектов или правок. Затем я пропустил последовательность изображений через ffmpeg с кодировщиком x264, чтобы создать видеофайл mp4.
Я начал изменять исходную команду ffmpeg по одному параметру за раз, чтобы увидеть разницу. В основном я сосредоточился на значении CRF, потому что это был единственный способ увидеть уменьшение артефактов сжатия. Даже с CRF, установленным на 10, я все еще мог видеть странное мерцание/полосатость по краям в нескольких местах. В конце концов я снизил значение до 5 и вообще не заметил никаких артефактов. Идеальное значение, возможно, где-то между 5 и 10 для этого контента.
Это оставило меня с видео, которое слишком велико для того, чем оно является. Повозившись со значениями B-кадра и эталонного кадра, чтобы добиться незначительного уменьшения размера файла, я, наконец, вернулся к изменению значения gop, и это оказало относительно большое влияние. Установка gop на 300 вместо 30 практически вдвое уменьшила размер файла. Итак, моя последняя команда ffmpeg была такой:
ffmpeg -speed 1 -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -movflags +faststart -crf 5 -bf 16 -refs 16 -r 30 -g 300 -me_method umh -me_range 16 -y myvideo.mp4
(Обновление: я изначально опубликовал указанную выше команду как -crf 10... теперь исправлен на -crf 5)
Основные параметры, которые я отбросил, были:
-pix_fmt yuv420p
(это может ухудшить качество)-coder ac
(Я не видел никакого положительного эффекта с этим или без него)-b_strategy 2
(это на самом деле немного увеличило размер файла в некоторых случаях)-direct-pred spatial
(абсолютно не влияет на качество/размер выходного файла, который я мог наблюдать)Если бы я доставлял выходной файл на YouTube, я бы подумал о том, чтобы вернуть -pix_fmt yuv420p
и -coder ac
и -flags cgop
только потому, что они рекомендуют их.
Эти параметры привели к незначительному улучшению/уменьшению размера файла (в долях 1 МБ):
-bf 16
-refs 16
-me_method umh -me_range 16
Вы можете увидеть изменение размера файла на экране ниже, где я назвал каждый выходной файл в соответствии с параметрами ffmpeg, которые я изменил. Все, что не содержит crf05 в имени, свидетельствует о проблеме артефактов.
Для сравнения, я выполнил аналогичную команду для создания файла webm, но с гораздо худшим/более высоким значением CRF. При значении CRF 22 результирующий файл mp4 имел размер 1,4 МБ без каких-либо заметных артефактов сжатия. Я использовал команду ffmpeg:
ffmpeg -speed 1 -framerate 30 -f image2 -i frames/%04d.png -c:v libvpx-vp9 -b:v 0 -tile-columns 2 -crf 22 -r 30 -g 300 -y myvideo.webm
Следуя предложениям stib и Mulvya, я попробовал параметры и -tune
и изменил значение от 5 до 10. Я сделал то же самое для своих собственных экспериментов с параметрами и . Выходной mp4, основанный на моем входном mkv-видео, имел видимые мерцающие артефакты сжатия в одном и том же месте, пока я не уменьшил crf до 6 при использовании и до 5 с параметрами или при использовании-trellis
crf
-me_method
-bf
-trellis
-bf -refs
-tune
. Вот снимки экрана, показывающие последние артефакты, которые я пытаюсь устранить, используя более высокие значения crf. Первый экран — входное mkv-видео, второй — образец закодированного видео в формате mp4, созданный с использованием параметра -trellis 0. Артефакты видны на верхней границе одного из прямоугольников. (На черном фоне также есть толстая серая полоса — это не артефакт сжатия, я думаю, что это диалог в процессе исчезновения после нажатия кнопки «Отмена» в моей записи демо / семпла.)
Вот команды и результирующие размеры файлов
-настроить анимацию:
ffmpeg -speed 1 -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -movflags +faststart -crf 5 -tune animation -r 30 -g 300 -y myvideo.mp4
Размер: 2 757 370
Видимые артефакты: Нет
ffmpeg -speed 1 -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -movflags +faststart -crf 6 -tune animation -r 30 -g 300 -y myvideo.mp4
Размер: 2 593 711
Видимые артефакты: Да
-решетка 0:
ffmpeg -speed 1 -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -movflags +faststart -crf 6 -pix_fmt yuv420p -x264opts trellis=0 -r 30 -g 300 -y myvideo.mp4
Размер: 2 214 534 байт
Видимые артефакты: Нет
ffmpeg -speed 1 -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -movflags +faststart -crf 7 -pix_fmt yuv420p -x264opts trellis=0 -r 30 -g 300 -y myvideo.mp4
Размер: 2 074 544 байта.
Видимые артефакты: есть (правда, мизерное количество — буквально несколько пикселей за доли секунды)
-fast_skip 0:
ffmpeg -speed 1 -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -movflags +faststart -crf 7 -pix_fmt yuv420p -x264opts fast_pskip=0 -r 30 -g 300 -y myvideo.mp4
Размер: 2 012 596 байт
Видимые артефакты: Нет
ffmpeg -speed 1 -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -movflags +faststart -crf 8 -pix_fmt yuv420p -x264opts fast_pskip=0 -r 30 -g 300 -y myvideo.mp4
Размер: 1 883 919 байт
Видимые артефакты: Да (очень маленький/небольшой объем)
-psy 0 -fast_pskip 0:
ffmpeg -speed 1 -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -movflags +faststart -crf 7 -pix_fmt yuv420p -x264opts psy=0:fast_pskip=0 -r 30 -g 300 -y myvideo.mp4
Размер: 1 886 919 байт
Видимые артефакты: Нет
ffmpeg -speed 1 -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -movflags +faststart -crf 8 -pix_fmt yuv420p -x264opts psy=0:fast_pskip=0 -r 30 -g 300 -y myvideo.mp4
Размер: 1 764 771 байт
Видимые артефакты: Да
-bf -ссылки:
ffmpeg -speed 1 -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -movflags +faststart -crf 5 -bf 16 -refs 16 -r 30 -g 300 -me_method umh -me_range 16 -y myvideo.mp4
Размер: 2 257 420 байт
Видимые артефакты: Нет
ffmpeg -speed 1 -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -movflags +faststart -crf 6 -bf 16 -refs 16 -r 30 -g 300 -me_method umh -me_range 16 -y myvideo.mp4
Размер: 2 106 439 байт
Видимые артефакты: Да (хотя и мизерное количество)
-deblock:
ffmpeg -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -movflags +faststart -preset veryslow -crf 14 -pix_fmt yuv420p -x264opts fast_pskip=0:psy=0:deblock=-3,-3 -r 30 -g 300 -y myvideo.mp4
Размер: 982 549 байт
Видимые артефакты: Нет
ffmpeg -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -movflags +faststart -preset veryslow -crf 14 -pix_fmt yuv420p -x264opts fast_pskip=0:psy=0:deblock=-3,-3 -bf 16 -refs 16 -me_method umh -me_range 64 -r 30 -g 300 -y myvideo.mp4
Размер: 961 460 байт
Видимые артефакты: Нет
Либо кодировщик vp9 намного лучше справляется с таким видеоконтентом, либо есть какой-то параметр x264, о котором я не знаю, который улучшит ситуацию. Есть ли у кого-нибудь идеи по поводу варианта, который я могу дать ffmpeg, чтобы получить лучший результат с x264/mp4? (И я не пытаюсь развязать какую-то войну кодеков — мне нужно публиковаться в обоих форматах!)
Параметр, который, по-видимому, оказывает наибольшее влияние на удаление этого артефакта (для типа контента в исходном сообщении), допуская при этом более высокие значения CRF, — это deblock
. Использование -deblock -3,-3
допустимого значения CRF 14 с полным устранением артефактов. Использование значений CRF 15 и 16 повторно вводит артефакт, хотя и в крошечных количествах и не очень заметно, если только вы не ищете его специально. Также значения деблокировки -3-1 и -3-0 работали достаточно хорошо, но не устраняли артефакт полностью на CRF 14.
Последняя команда была:
ffmpeg -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -movflags +faststart -preset veryslow -crf 14 -pix_fmt yuv420p -x264opts fast_pskip=0:psy=0:deblock=-3,-3 -r 30 -g 300 -y myvideo.mp4
Чтобы выжать еще несколько килобайт сжатия, вы можете прочитать параметры bf
refs
me_method umh
и me_range
. Но я обнаружил, что мне нужен me_range
набор на 64. Меньшие значения снова вызовут артефакт сжатия.
Примечание. У меня был некоторый успех с изменением aq-mode
и aq-strength
, но это было не так хорошо, как деблокировка для удаления артефактов.
Изменяйте значение CRF до тех пор, пока вы не увидите артефакты сжатия. При необходимости сделайте смехотворно низким, например, CRF = 5.
Увеличьте значение GOP, чтобы компенсировать больший размер выходного файла. Например, для видео с частотой 30 кадров в секунду попробуйте gop=300.
Ваша команда ffmpeg может выглядеть так:ffmpeg -speed 1 -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -movflags +faststart -crf 5 -bf 16 -refs 16 -r 30 -g 300 -me_method umh -me_range 16 -y myvideo.mp4
Редактировать: (используя правильный параметр скорости для x264, добавляя pix_fmt и другие параметры x264)
ffmpeg -framerate 30 -f image2 -i frames/%04d.png -c:v libx264 -movflags +faststart -preset veryslow -crf 5 -pix_fmt yuv420p -x264opts fast_pskip=0:psy=0 -bf 16 -refs 16 -me_method umh -me_range 16 -r 30 -g 300 -y myvideo.mp4
-pix_fmt yuv420p -x264opts fast_pskip=0:psy=0
Ответ обновлен соответствующим образом.
Доктор Мэйхем