我需要以一定的帧速率(至少 30 fps)捕获整个屏幕的位完美无损视频。我目前正在使用 Windows 10 和最新版本的 FFmpeg。鉴于录制视频的分辨率相当高(4K 或更高),允许真正libx264rgb
无损编码的软件编码器(例如)无法完成这项工作,因为即使使用预设,帧速率也会降至 15 fps 或更低ultrafast
。此外,为此目的将信息从 GPU 传输到 CPU 在这方面是一个瓶颈,所以如果可能的话,我想避免它。
因此,我一直在研究硬件编码器,以检查是否可以将所有工作委托给我的 GPU(RTX 4070 Ti)。经过一番研究,我意识到可以通过以下 FFmpeg 命令使用 Windows 8+ 桌面复制 API 和 HEVC NVENC 编码器有效地录制屏幕:
ffmpeg -filter_complex ddagrab=0:framerate=30:draw_mouse=0 -c:v hevc_nvenc -tune lossless output.mkv
尽管这种方法性能很好(甚至可以超过 60 fps),但颜色空间默认设置为 yuv420p,这是有损的,通过检查视频元数据后可以看出ffmpeg -i output.mkv
:
输入 #0,matroska,webm,来自‘output.mkv’:元数据:编码器:Lavf60.10.100 持续时间:00:00:04.63,开始:0.000000,比特率:2537 kb/s 流 #0:0:视频:hevc(主),yuv420p(tv,bt470bg/bt709/iec61966-2-1,渐进式),3840x2160 [SAR 1:1 DAR 16:9],30 fps,30 tbr,1k tbn 元数据:编码器:Lavc60.22.100 hevc_nvenc 持续时间:00:00:04.633000000
因此,必须对这种方法进行改进,因此我通过命令检查了该编码器可以使用哪些像素格式,ffmpeg -h encoder=hevc_nvenc
并得到了以下相关信息:
支持的像素格式:yuv420p nv12 p010le yuv444p p016le yuv444p16le bgr0 bgra rgb0 rgba x2rgb10le x2bgr10le gbrp gbrp16le cuda d3d11
但是,无论我选择哪种像素格式,例如,
ffmpeg -filter_complex ddagrab=0:framerate=30:draw_mouse=0 -c:v hevc_nvenc -tune lossless -pix_fmt bgr0 output.mkv
我总是收到以下错误:
无法在过滤器“Parsed_ddagrab_0”和过滤器“auto_scale_0”支持的格式之间进行转换 [fc#0 @ 0000018a81585c80] 配置过滤器图表时出错:功能未实现 打开输出文件 output.mkv 时出错。打开输出文件时出错:功能未实现
即使我尝试强制编码的捕获和输出视频之间的像素格式兼容,我也会得到完全相同的错误,例如使用此命令:
ffmpeg -filter_complex ddagrab=0:framerate=30:draw_mouse=0,format=bgra -c:v hevc_nvenc -tune lossless -pix_fmt bgra output.mkv
有趣的是,即使yuv420p
选择输出像素格式(实际上是视频最终默认编码的格式),该命令也会失败并抛出相同的错误。因此,这表明有某些东西阻止设置或更改像素格式。
还值得注意的是,在多次失败的组合之后,我意识到如果使用 将硬件帧下载到内存中hwdownload
,那么我就可以设置像素格式。然而,唯一真正获得无损视频的组合是使用像素格式gbrp
,即通过以下命令:
ffmpeg -filter_complex ddagrab=0:framerate=30:draw_mouse=0,hwdownload,format=bgra -c:v hevc_nvenc -tune lossless -pix_fmt gbrp output.mkv
如果我尝试使用 RGB 颜色空间中的任何其他像素格式(据称可以获得无损编码,例如bgr0
、bgra
或),则该选项将被忽略,并且输出视频的像素格式将固执地设置为。这不再相关,因为至少有一个选项有效,但这加深了上述与设置像素格式时可能出错有关的怀疑,同时也证明了编码器至少在这种情况下能够在完整的 RGB 颜色空间中完美地对帧进行位编码。rgb0
rgba
yuv420p
hevc_nvenc
然而,尽管此解决方案或补丁比使用软件编码器(例如)的性能更高,但为了能够使用适当的像素格式libx264rgb
而不得不求助于hwdownload
(它意味着瓶颈)仍然不是一种选择。此外,使用这种替代方法无法达到所需的 30 fps,因此问题总结在标题中:
有没有办法强制 hevc_nvenc 使用允许位完美无损输出的像素格式(例如gbrp
),而无需将硬件帧下载到内存(这意味着性能损失)?
非常感谢您的所有努力,如果问题不够简洁,我在此先致歉。我只是试图尽可能明确地说明我的尝试和发现,以便为所有愿意调查该问题的人节省可能的工作,以便能够朝着正确的方向调查或提出解决方案或建议。