如何使用ffmpeg录制特定窗口?

28

我使用ffmpeg来录制窗口,代码如下:

ffmpeg.exe
-f dshow 
-y 
-i video="screen-capture-recorder":audio="virtual-audio-capturer":audio="Microphone (USB Audio Device)" 
-framerate 15 
-vcodec libx264 
-crf 0 
-preset ultrafast 
-acodec pcm_s16le 
-vf crop=Width:Height:Left:Top 
output.flv

但问题是我可能会移动窗口,这会导致记录一个不包括我想要的窗口的区域。

我如何捕捉能够移动的特定窗口?


编辑:我也使用gdigrab来捕捉我的窗口(例如Skype),而不是dshow

ffmpeg.exe
-y
-f dshow
-i audio="virtual-audio-capturer":audio="Microphone (USB Audio Device)"
-f gdigrab
-draw_mouse 0
-i title="Skype"
-framerate 30
-vcodec libx264
-crf 0
-preset ultrafast
-acodec pcm_s16le
output.flv

但是会议已经被取消了...


3
如果您仍然希望使用屏幕录制器,请为其提交一个问题(我维护它)。 - rogerdpack
你可以使用dshow和一种编程语言来动态传递偏移量!你使用了裁剪滤镜,效果很好,你可以使用一个程序创建边框,当你拖动该边框时,它会动态地改变你的滤镜偏移量。 - SdSaati
请访问此链接以获取可工作的FFMPEG C++ MP4格式屏幕录制应用程序:https://dev59.com/JGsy5IYBdhLWcg3wyxCi#43464269。 - Abdullah Farweez
10个回答

15

我也在网上寻找解决方案,但对我找到的答案不满意。我现在已经在Linux上拼凑出这个非常简单的解决方案:

ffmpeg -f x11grab -framerate 25 \
    $(xwininfo | gawk 'match($0, /-geometry ([0-9]+x[0-9]+).([0-9]+).([0-9]+)/, a)\
      { print "-video_size " a[1] " -i +" a[2] "," a[3] }') \
    $(date +%Y-%m-%d_%H-%M_%S).mp4
  • 执行此命令后,可以使用鼠标指针选择窗口。

  • 目标文件名将采用YYYY-mm-dd_hh_mm_ss.mp4格式保存在当前目录中。

  • awk魔法只是解析窗口信息。它比较丑陋,只能在gnu awk下工作,但我还没有找到更好的方法来将窗口几何形状解析为自定义格式。

记录屏幕上特定矩形的语法是:

-video_size [width]x[height] -i [x],[y]

我相信这也应该可以在Windows下使用,并且与dshow兼容。


不知道为什么我总是运行xwininfo,然后寻找我需要的数据。你在这里使用的方法很棒。 - MatrixManAtYrService
似乎如果有窗口边框,x、y位置包括边框,但宽度和高度仅为边框内的窗口大小。因此,a[2]和a[3]应该加上边框宽度。这使得问题更加复杂。 - Lu Xu
我已经运行了您的命令,但当我点击特定窗口时,它不仅记录该特定窗口,而是记录整个当前屏幕。请问如何选择特定窗口? - Abdul ahad

13

这个示例对我有效:

ffmpeg -f gdigrab -framerate 30 -i title="german.avi - VLC media player" -b:v 3M  germ.flv

“title”指目标窗口的实际标题。

希望这能有所帮助。


每当我运行此命令时,我都会收到以下错误: 未知的输入格式:'gdigrab' 请问您能告诉我如何解决这个问题吗? - Abdul ahad
尝试使用 x11grab 而不是 gdigrab - tyler.frankenstein
@Abdulahad 不确定这是否是您的问题,但值得指出的是 gdigrab 仅适用于 Windows。每个平台的替代方案可以在此处找到:https://trac.ffmpeg.org/wiki/Capture/Desktop。 - Chris Pavs

4

它在这里提到:

默认情况下,它捕获主桌面监视器的“全屏幕”(所有窗口,重叠的,如果是vista+则为aero,如果不是aero,则没有透明窗口)。要进行不同的配置,请运行提供的“配置设置实用程序/快捷方式”或在启动运行之前调整注册表设置(仅限高级用户):HKEY_CURRENT_USER\Software\screen-capture-recorder,使用DWORD键来表示start_XXX等等。 (请参见包含的文件{installdir}\configuration_setup_utility\setup_screen_tracker_params.rb以获取可用的完整注册表键值列表,或参见https://github.com/rdp/screen-capture-recorder-to-video-windows-free/blob/master/configuration_setup_utility/setup_screen_tracker_params.rb#L9)。例如:查看configuration_setup_utility\incoming.reg文件(尽管请注意这些值是十六进制的,因此编辑该文件有点繁琐-我总是使用regedit或配套的脚本实用程序,并且不手动编辑它)。要“重置”值,请删除其键。

您可以在这里看到这些注册表选项:

  • capture_height
  • capture_width
  • start_x
  • start_y
  • default_max_fps
  • stretch_to_width
  • stretch_to_height
  • stretch_mode_high_quality_if_1
  • hwnd_to_track
  • disable_aero_for_vista_plus_if_1
  • track_new_x_y_coords_each_frame_if_1
  • capture_mouse_default_1
  • capture_foreground_window_if_1
  • dedup_if_1
  • millis_to_sleep_between_poll_for_dedupe_changes
  • capture_transparent_windows_including_mouse_in_non_aero_if_1_causes_annoying_mouse_flicker
  • hwnd_to_track_with_window_decoration

3

ffmpeg -rtbufsize 1500M -f dshow -i audio="virtual-audio-capturer" -f gdigrab -framerate 30 -draw_mouse 1 -i title=RecordWindow -pix_fmt yuv420p -profile:v baseline -y Huangbaohua.mp4

"RecordWindow"是指定窗口的标题。


3
对于那些能够自己编译ffmpeg的人,这实际上是完美无缺的。我将添加更加晦涩的参数,这些参数对于下载预编译的ffmpeg二进制文件的人永远不会起作用。若要使用nVidia的h265硬件编码,请使用ffmpeg -rtbufsize 1500M -f dshow -i audio="virtual-audio-capturer" -f gdigrab -framerate 30 -draw_mouse 1 -i title="Record Window" -c:v hevc_nvenc -preset slow -rc vbr_2pass -2pass 1 -qmin 3 -cq 27 -y Huangbaohua.mp4 - Anubioz

3

我改进了MaxC的答案中的命令。

该命令存在一个问题,即区域位置不考虑多监视器布局。 geometry 行中的 x 和 y 是相对于当前监视器的,因此它无法记录其他监视器中的窗口。

信息从各个行中解析出来。并且考虑了窗口边框。还添加了倒计时以让用户准备好。以下是脚本:

#!/bin/sh
xwininfo | {
    while IFS=: read -r k v; do
        case "$k" in
        *"Absolute upper-left X"*) x=$v;;
        *"Absolute upper-left Y"*) y=$v;;
        *"Border width"*) bw=$v ;;
        *"Width"*) w=$v;;
        *"Height"*) h=$v;;
        esac
    done
    for i in 3 2 1; do echo "$i"; sleep 1; done
    ffmpeg -y -f x11grab -framerate 30 \
           -video_size "$((w))x$((h))" \
           -i "+$((x+bw)),$((y+bw))" screenrecord.mp4
}

我有两个不确定的问题:

  • 绝对或相对于左上角的X/Y坐标(参见xwininfo的输出)?
  • 所有WM / DE是否始终一致地提供窗口边框信息,即x和y是否总是指向窗口边框外部的点?

2
为了录制窗口程序,需要使用"gdigrab"元素及其"title"补充,这是窗口在任务管理器>>详细信息中显示的名称,在Windows系统中。请参考以下截图:enter image description here
ffmpeg -f gdigrab -rtbufsize 150M -i title="VisorATSC1" -s 480x360 -r 15 -b 2000k -minrate 2000k -maxrate 2000k -vcodec h264_nvenc -gpu 0 -f flv rtmp://x.x.x.x:1935/live/YASV

0

我无法评论,所以在这里写下来。
Brian Huang的答案对我来说出现了这个错误:

width not divisible by 2 (603x585)
Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height

但是在添加所需分辨率的-vf scale=1280:720后,无论高度和宽度都是偶数,这个错误就会消失,屏幕录制将正常工作。即使被其他窗口覆盖,也不会出现在录制文件中。


0

ffmpeg -f x11grab -framerate 25
$(xwininfo | gawk 'match($0, /-geometry ([0-9]+x[0-9]+).([0-9]+).([0-9]+)/, a)
{ print "-video_size " a[1] " -i +" a[2] "," a[3] }')
$(date +%Y-%m-%d_%H-%M_%S).mp4

这在Windows上不起作用,因为xwininfo返回几何尺寸的“大小”部分是字符单元而不是像素(例如终端窗口)。要解决此问题,需要从xwininfo响应的Width:和Height:字段中提取大小。


0
我用这个来记录提示。
ffmpeg -rtbufsize 1500M -f dshow -i audio="Microfono (8- Logitech USB Headset)" -f gdigrab -framerate 30 -draw_mouse 1 -i title="Prompt dei comandi" -pix_fmt yuv420p -profile:v baseline -y output\output3_xp.mp4
pause

但它只适用于100x20(列x行)的提示符或其他可被整除的屏幕尺寸,否则会出现错误,如下:

[libx264 @ 0000027c7ed66200] width not divisible by 2 (269x432)
Error initializing output stream 0:0 -- Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height
Conversion failed!

附言:我在其他宽度或高度不均匀的窗口也遇到了这个问题。我用Python的tkinter创建了一个窗口,然后出现了错误,接着我给窗口设定了一些几何属性(300x500),然后它就正常工作了...

奇怪的是,鼠标有点偏移...


[libx264 @ 0000027c7ed66200] 宽度不是2的倍数 (269x432) 初始化输出流0:0时出错--打开输出流#0:0的编码器时出错--可能是由于比特率、速率、宽度或高度等参数不正确 转换失败! - PythonProgrammi
1
当输出yuv420p时,libx264要求宽度和高度可被2整除。许多答案在这里展示了如何使用缩放过滤器自动处理它。 - llogan

0

在 Ubuntu 上,你可以使用以下脚本:

#!/usr/bin/env bash

echo "Please select the window that you want to record."

win_info="$(xwininfo)"
x="$(echo "$win_info" | grep -i 'absolute upper-left x' | sed 's/^[^0-9]*\([0-9]\+\)$/\1/g' )"
y="$(echo "$win_info" | grep -i 'absolute upper-left y' | sed 's/^[^0-9]*\([0-9]\+\)$/\1/g' )"
width="$(echo "$win_info" | grep -Ei '^\W+width:' | sed 's/^[^0-9]*\([0-9]\+\)$/\1/g' )"
height="$(echo "$win_info" | grep -Ei '\W+height:' | sed 's/^[^0-9]*\([0-9]\+\)$/\1/g' )"
now="$(date +%Y-%m-%d_%H-%M_%S)"

echo "
executing:

> ffmpeg -f x11grab -framerate 25 -video_size ${width}x${height} -i +${x},${y} "window_recording_${now}.mp4"

[press ctrl+c in this terminal to stop the recording]

"

ffmpeg -f x11grab -framerate 25 -video_size ${width}x${height} -i +${x},${y} "window_recording_${now}.mp4"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接