使用NVENC编解码器在60 fps下使用FFmpeg进行桌面抓取

问题描述:

使用NVENC编解码器使用最新的Windows编译FFmpeg在60FPS下录制桌面时出现问题。元数据说这个文件是60 fps,但是当我播放它时,我可以清楚地看到它是而不是 60FPS。使用NVENC编解码器在60 fps下使用FFmpeg进行桌面抓取

命令行我用的是以下几点:

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检查皮影的输出文件,我可以看到:

流#0:0(UND):视频:H264(高)(AVC1/0x31637661),YUV420P(电视, SMPTE170M/SMPTE170M/bt470m),1920×1080 [SAR 1:1 DAR 16:9],4573千比特/秒, 59.38帧,240 TBR,60K TBN,120 TBC(默认)

但如果我强迫我的输出到具有相同的比特率和档案我得到:

Stream#0:0(und):Video:h264(High)(avc1/0x31637661),yuv420p, 1920x1080 [SAR 1:1 DAR 16:9],5519kb/s,60fps,60tbr,15360 TBN, 120 TBC(默认)

我可以看到tbrtbn是不同的,所以我知道我的输出被复制帧。

对于测试,我的所有录音在背景上都有this 60 frame rate test page,我可以清楚地看到差异。

我知道ShadowPlay可能会比使用相同编解码器的FFmpeg做得更多。我知道OBS可以很容易地做到,但我想了解我做错了什么。也许这是FFmpeg的一些限制?

全部控制台输出

使用-v trace命令:

[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) 
+0

@rogerdpack - 你能帮忙吗? – Mulvya

假设你的DirectShow过滤器使用GDI,它极有可能整个桌面不能以60fps捕获(Windows不是很好在那)。 FFmpeg可能会使一些图像翻倍,最终达到60 fps。 DXGI应该提供更好的性能(https://msdn.microsoft.com/en-us/library/windows/desktop/hh404487(v=vs.85).aspx),但我不知道FFmpeg内置了对此的支持。然而?