我在使用带有 NVENC 编解码器的最新 Windows 编译 FFmpeg 以 60FPS 录制我的桌面时遇到问题。元数据说文件是 60 fps,但是当我播放它时,我可以清楚地看到它不是60 FPS。
我使用的命令行如下:
ffmpeg -y -rtbufsize 2000M -f gdigrab -framerate 60 -offset_x 0 -offset_y 0 -video_size 1920x1080 -i desktop -c:v h264_nvenc -preset:v fast -pix_fmt nv12 out.mp4
我尝试使用实时缓冲区、使用另一个 DirectShow 设备、更改配置文件或强制比特率,但视频似乎总是在 30fps。
使用 NVIDIA 的 ShadowPlay 录制屏幕效果很好,所以我知道这在我的机器上是可行的。
使用 FFprobe 检查 ShadowPlay 的输出文件,我可以看到:
流 #0:0(und):视频:h264(高)(avc1 / 0x31637661)、yuv420p(tv、smpte170m/smpte170m/bt470m)、1920x1080 [SAR 1:1 DAR 16:9]、4573 kb/s、59.38 fps、240 tbr、60k tbn、120 tbc(默认)
但是,如果我强制我的输出具有相同的比特率和配置文件,我会得到:
流 #0:0(und):视频:h264(高)(avc1 / 0x31637661)、yuv420p、1920x1080 [SAR 1:1 DAR 16:9]、5519 kb/s、60 fps、60 tbr、15360 tbn、120待定(默认)
我可以看到tbr
并且tbn
不同,所以我知道我的输出是复制帧。
为了测试,我所有的录音都在背景上有这个 60 帧速率的测试页面,我可以清楚地看到差异。
我知道 ShadowPlay 可能比使用相同编解码器的 FFmpeg 做的更多。我知道 OBS 可以很容易地做到这一点,但我想了解我做错了什么。也许这是一些 FFmpeg 限制?
完整的控制台输出
使用 -v 跟踪命令:
[gdigrab @ 0000000002572cc0] Capturing whole desktop as 1920x1080x32 at (0,0)
[gdigrab @ 0000000002572cc0] Cursor pos (1850,750) -> (1842,741)
[gdigrab @ 0000000002572cc0] Probe buffer size limit of 5000000 bytes reached
[gdigrab @ 0000000002572cc0] Stream #0: not enough frames to estimate rate; consider increasing probesize
[gdigrab @ 0000000002572cc0] stream 0: start_time: 1467123648.275 duration: -9223372036854.775
[gdigrab @ 0000000002572cc0] format: start_time: 1467123648.275 duration: -9223372036854.775 bitrate=3981337 kb/s
Input #0, gdigrab, from 'desktop':
Duration: N/A, start: 1467123648.275484, bitrate: 3981337 kb/s
Stream #0:0, 1, 1/1000000: Video: bmp, 1 reference frame, bgra, 1920x1080 (0x0), 0/1, 3981337 kb/s, 60 fps, 1000k tbr, 1000k tbn, 1000k tbc
Successfully opened the file.
Parsing a group of options: output file out.mp4.
Applying option c:v (codec name) with argument h264_nvenc.
Applying option pix_fmt (set pixel format) with argument nv12.
Successfully parsed a group of options.
Opening an output file: out.mp4.
[file @ 0000000000e3a7c0] Setting default whitelist 'file,crypto'
Successfully opened the file.
detected 8 logical cores
[graph 0 input from stream 0:0 @ 000000000257ec00] Setting 'video_size' to value '1920x1080'
[graph 0 input from stream 0:0 @ 000000000257ec00] Setting 'pix_fmt' to value '30'
[graph 0 input from stream 0:0 @ 000000000257ec00] Setting 'time_base' to value '1/1000000'
[graph 0 input from stream 0:0 @ 000000000257ec00] Setting 'pixel_aspect' to value '0/1'
[graph 0 input from stream 0:0 @ 000000000257ec00] Setting 'sws_param' to value 'flags=2'
[graph 0 input from stream 0:0 @ 000000000257ec00] Setting 'frame_rate' to value '60/1'
[graph 0 input from stream 0:0 @ 000000000257ec00] w:1920 h:1080 pixfmt:bgra tb:1/1000000 fr:60/1 sar:0/1 sws_param:flags=2
[format @ 000000000257ffc0] compat: called with args=[nv12]
[format @ 000000000257ffc0] Setting 'pix_fmts' to value 'nv12'
[auto-inserted scaler 0 @ 00000000025802c0] Setting 'flags' to value 'bicubic'
[auto-inserted scaler 0 @ 00000000025802c0] w:iw h:ih flags:'bicubic' interl:0
[format @ 000000000257ffc0] auto-inserting filter 'auto-inserted scaler 0' between the filter 'Parsed_null_0' and the filter 'format'
[AVFilterGraph @ 0000000000e373c0] query_formats: 4 queried, 2 merged, 1 already done, 0 delayed
[auto-inserted scaler 0 @ 00000000025802c0] w:1920 h:1080 fmt:bgra sar:0/1 -> w:1920 h:1080 fmt:nv12 sar:0/1 flags:0x4
[h264_nvenc @ 0000000000e3ca20] Nvenc initialized successfully
[h264_nvenc @ 0000000000e3ca20] 1 CUDA capable devices found
[h264_nvenc @ 0000000000e3ca20] [ GPU #0 - < GeForce GTX 670 > has Compute SM 3.0 ]
[h264_nvenc @ 0000000000e3ca20] supports NVENC
[mp4 @ 0000000000e3b580] Using AVStream.codec to pass codec parameters to muxers is deprecated, use AVStream.codecpar instead.
Output #0, mp4, to 'out.mp4':
Metadata:
encoder : Lavf57.40.101
Stream #0:0, 0, 1/15360: Video: h264 (h264_nvenc) (Main), 1 reference frame ([33][0][0][0] / 0x0021), nv12, 1920x1080, 0/1, q=-1--1, 2000 kb/s, 60 fps, 15360 tbn, 60 tbc
Metadata:
encoder : Lavc57.47.100 h264_nvenc
Side data:
cpb: bitrate max/min/avg: 0/0/2000000 buffer size: 4000000 vbv_delay: -1
Stream mapping:
Stream #0:0 -> #0:0 (bmp (native) -> h264 (h264_nvenc))
Press [q] to stop, [?] for help
cur_dts is invalid (this is harmless if it occurs once at the start per stream)
Clipping frame in rate conversion by 0.000008
cur_dts is invalid (this is harmless if it occurs once at the start per stream)
[gdigrab @ 0000000002572cc0] Cursor pos (1850,750) -> (1842,741)
*** 35 dup!
[gdigrab @ 0000000002572cc0] Cursor pos (1850,750) -> (1842,741)
*** 7 dup!
[gdigrab @ 0000000002572cc0] Cursor pos (1850,649) -> (1850,649)
*** 1 dup!
[gdigrab @ 0000000002572cc0] Cursor pos (1858,535) -> (1858,535)
*** 3 dup!
[gdigrab @ 0000000002572cc0] Cursor pos (1859,454) -> (1859,454)
*** 2 dup!
[gdigrab @ 0000000002572cc0] Cursor pos (1865,384) -> (1865,384)
*** 2 dup!
[gdigrab @ 0000000002572cc0] Cursor pos (1846,348) -> (1846,348)
*** 3 dup!
[gdigrab @ 0000000002572cc0] Cursor pos (1770,347) -> (1770,347)
*** 2 dup!
[gdigrab @ 0000000002572cc0] Cursor pos (1545,388) -> (1545,388)
*** 4 dup!
frame= 69 fps=0.0 q=35.0 size= 184kB time=00:00:00.63 bitrate=2384.0kbits/[gdigrab @ 0000000002572cc0] Cursor pos (1523,389) -> (1519,378)