我正在尝试使用 ffmpeg 在 6700 XT 上使用硬件加速来无损(或以接近无损的质量)录制屏幕。我正在使用5.14.14-051414-generic
内核运行 Linux Mint。
我试过了:
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 fps 的速度录制,但录制的内容不稳定且颜色略有偏差。我假设颜色问题来自颜色格式 nv12,但是rgb
orrgb8
给出了错误。
我也尝试过使用 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 wiki 表示 VAAPI 仅部分支持 AMD GPU。
但我怀疑您目前可能正在使用 CPU 的集成 GPU,这可能会导致性能问题:
如果同一台机器上有多个可用设备(例如 Intel 集成 GPU 和 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)。 ...
在大多数现代硬件上,编码器的速度应该足够快,以便在没有任何帧丢失的情况下进行记录,甚至为其他应用程序留出足够的 CPU 空间。
如果您要存档录音或担心文件大小,请再次无损地重新编码,但使用较慢的预设。 ...
答案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
对我来说,在带有 ffmpeg 5.1 的 Debian Bookworm 上工作(我只更改了大小以匹配我的显示器),没有颜色问题和 60 fps,在相同的 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 时会中断,但它可以工作,并且您的命令行对我来说也运行良好。
另请注意,在至少 ffmpeg 5.1 之前,使用 kmsgrab 同时录制音频会导致音频/视频同步问题:
https://trac.ffmpeg.org/ticket/8377
如果您想使用它,您可能需要升级到 ffmpeg 6,根据我的经验,它解决了最后一个问题。
答案3
昨天有人问过这个问题,答案仍然是一样的:硬件视频编解码器不支持更改量化因子,即crf
更多,因此它们不支持无损编码。
从https://trac.ffmpeg.org/wiki/Hardware/VAAPI
libx264 的映射选项
目前不支持类似 CRF 的模式。唯一的恒定质量模式是 CQP(恒定量化参数),它对场景内容没有适应性。然而,它确实允许对不同的帧类型进行不同的质量设置,通过在未引用的 B 帧上花费更少的比特来提高压缩 - 请参阅 (i|b)_q(factor|offset) 选项。 CQP 模式不能与最大比特率或缓冲区大小结合使用。