Я пытаюсь записать свой экран без потерь (или с почти без потерь качества) с аппаратным ускорением на 6700 XT с ffmpeg. Я использую Linux Mint с ядром 5.14.14-051414-generic
.
Я пробовал:
ffmpeg -vaapi_device /dev/dri/renderD128 -f x11grab -video_size 2560x1440 -i :0 -r 60 -vf 'hwupload,scale_vaapi=format=nv12' -c:v h264_vaapi -qp 0 output.mp4
ffmpeg
говорит, что записывает на 60 кадров в секунду, но запись прерывистая и слегка искажена по цвету. Я предполагаю, что проблема с цветом из-за цветового формата nv12, но rgb
or rgb8
выдает ошибку.
Я также пробовал использовать kmsgrab:
ffmpeg -device /dev/dri/card0 -f kmsgrab -i - -vf 'hwmap=derive_device=vaapi,scale_vaapi=w=2560:h=1440:format=nv12' -c:v h264_vaapi -qp 0 output.mp4
Но выдает ошибку:
[kmsgrab @ 0x558f001c8d80] Using plane 65 to locate framebuffers.
[kmsgrab @ 0x558f001c8d80] Failed to get framebuffer 127: Invalid argument.
pipe:: Invalid argument
Число после Failed to get framebuffer
обычно равно 127
или где-то от 134
до 136
.
Я получил эти командыздесь.
решение1
Я думаю, что по-настоящему кодировать без потерь можно только программным способом, но при более высоких битрейтах может получиться достаточно хорошо.
Кроме того, в вики ffmpeg говорится, что VAAPI поддерживается только частично для графических процессоров AMD.
Но я подозреваю, что в настоящее время вы в любом случае используете встроенный графический процессор ЦП, что может привести к проблемам с производительностью:
Если на одном компьютере имеется несколько используемых устройств (например, интегрированный графический процессор Intel и дискретная видеокарта AMD), их можно использовать одновременно для декодирования разных потоков:
ffmpeg -init_hw_device vaapi=intel:/dev/dri/renderD128 -init_hw_device vaapi=amd:/dev/dri/renderD129 -hwaccel vaapi -hwaccel_device intel -i ... -hwaccel vaapi -hwaccel_device amd -i ...
Вы смотрели, доступно ли более одного устройства?
Пытатьсяls /dev/dri/чтобы увидеть, какие устройства доступны.
Независимо от того, использовали ли вы правильное устройство или нет,-qp 0Этот параметр, вероятно, не будет работать так, как задумано, поэтому попробуйте использовать точно указанные команды и посмотрите, дадут ли они лучшие результаты:
ffmpeg -vaapi_device /dev/dri/renderD128 -f x11grab -video_size 1920x1080 -i :0 -vf 'hwupload,scale_vaapi=format=nv12' -c:v h264_vaapi -qp 24 output.mp4
или
ffmpeg -vaapi_device /dev/dri/renderD128 -f x11grab -video_size 1920x1080 -i :0 -vf 'format=nv12,hwupload' -c:v h264_vaapi -qp 24 output.mp4
Изменив только разрешение, и если вы нашли другое аппаратное устройство, вы можете попробовать изменить и его.
Было бы интересно, если бы вы смогли получить хорошее качество при разумном битрейте/размере файла, поэтому, пожалуйста, дайте мне знать, если у вас это получилось.
Кстати, следующий код не использует аппаратное ускорение, а кодирует без потерь, так что вы можете попробовать и это:https://trac.ffmpeg.org/wiki/Capture/Desktop#lossless-recording
Чтобы ускорить процесс кодирования, можно использовать кодирование без потерь и отключить расширенные параметры кодировщика, например:
ffmpeg -video_size 1920x1080 -framerate 30 -f x11grab -i :0.0 -c:v libx264rgb -crf 0 -preset ultrafast -color_range 2 output.mkv
-crf 0 сообщает x264 о необходимости кодирования в режиме без потерь; -preset ultrafast советует делать это быстро. Обратите внимание на использование libx264rgb вместо libx264; последний выполнит преобразование с потерями из RGB в yuv444p (8 бит yuv444p недостаточно для сохранения 8 бит RGB, требуется 10 бит YCbCr). ...
Кодер должен быть достаточно быстрым на большинстве современных аппаратных средств, чтобы записывать без потери кадров и даже оставлять достаточно ресурсов ЦП для других приложений.
Если вы собираетесь архивировать запись или беспокоитесь о размере файла, перекодируйте ее без потерь еще раз, но с более медленной предустановкой. ...
решение2
TL,DR: Я думаю, что вы в основном столкнулись с ошибками в ffmpeg и/или других частях стека, которые, похоже, к настоящему времени исправлены.
Ваша первая команда:
ffmpeg -vaapi_device /dev/dri/renderD128 -f x11grab -video_size 2560x1440 -i :0 -r 60 -vf 'hwupload,scale_vaapi=format=nv12' -c:v h264_vaapi -qp 0 output.mp4
У меня работает на Debian Bookworm с ffmpeg 5.1 (я только изменил размер, чтобы он соответствовал моему монитору), без проблем с цветом и 60 кадров в секунду, на том же GPU (6700 XT). Так что, возможно, (в то время) где-то была ошибка в вашей версии ffmpeg или в драйверах VA-API или еще в чем-то.
Он не использует наивысшее качество, -qp 0
может выходить за пределы поддерживаемого диапазона для этого кодировщика и впоследствии игнорироваться, по-видимому, он возвращается к значению по умолчанию:
No quality level set; using default (20).
Такие низкие значения, как -qp 1
вам кажется, приемлемы и могут обеспечить достаточное качество для ваших нужд.
Что касается kmsgrab, обратите внимание, что для его использования требуется либо запуск от имени root, либо наличие установленной возможности CAP_SYS_ADMIN. Это вполне может быть причиной вашей ошибки, и исправление заключается в установке возможности на ffmpeg:
setcap cap_sys_admin=ep /usr/bin/ffmpeg
Это не идеально с точки зрения безопасности и может выйти из строя при обновлении ffmpeg, но это работает, и ваша командная строка у меня тоже работает нормально.
Обратите внимание, что использование kmsgrab при одновременной записи звука приводило к проблемам синхронизации аудио/видео до версии ffmpeg как минимум 5.1:
https://trac.ffmpeg.org/ticket/8377
Если вы хотите его использовать, вам, вероятно, следует обновиться до ffmpeg 6, которая, по моему опыту, исправила последнюю проблему.
решение3
Этот вопрос был задан вчера, и ответ остался прежним: аппаратные видеокодеки не поддерживают изменение коэффициента квантования, т.е. crf
и тем более не поддерживают кодирование без потерь.
Отhttps://trac.ffmpeg.org/wiki/Оборудование/VAAPI
Параметры отображения из libx264
В настоящее время не поддерживается режим типа CRF. Единственный режим постоянного качества — CQP (постоянный параметр квантования), который не имеет адаптивности к содержимому сцены. Однако он допускает различные настройки качества для разных типов кадров, чтобы улучшить сжатие, тратя меньше бит на нереферентные B-кадры — см. параметры (i|b)_q(factor|offset). Режим CQP нельзя комбинировать с максимальным битрейтом или размером буфера.