使用ffmpeg的kmsgrab设备录制Linux Wayland/DRM屏幕,并叠加网络摄像头。

7

安装Linux,使用kabylake iGPU的ffmpeg。

我正在使用kmsgrab设备捕获运行中的sway实例,这需要使用硬件后端来在我的硬件上一致处理图像。只有VA API符合此要求。我想在编码过程中在右下角叠加网络摄像头。然而,尝试操作过滤器图以完成此操作并未成功。最终是为了Twitch/Tube流。

现在,我实际上正在将网络摄像头捕获到sdl窗口,并使用独立的ffmpeg实例记录屏幕。这并不能解决我的问题,因为窗口很容易被工作区切换或其他窗口掩盖。

这是解决方法:

#!/usr/bin/env zsh

# record webcam and open it in sdl window
ffmpeg -v quiet -hide_banner \
  -re -video_size 640X480 -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -i /dev/video0 \
  -vf 'format=nv12,hwupload' -c:v hevc_vaapi -f hevc - \
  | ffmpeg -v quiet -i - -f sdl2 - &

# wait for webcam window to open
until swaymsg -t get_tree | grep 'pipe:' &>/dev/null; do
  sleep 0.5
done

# position webcam in the bottom right corner of screen using sway
swaymsg floating enable
swaymsg resize set width 320 height 240
swaymsg move position 1580 795
swaymsg focus tiling

#screencast
ffmpeg -format bgra -framerate 60 -f kmsgrab -thread_queue_size 1024 -i - \
  -f alsa -ac 2 -thread_queue_size 1024 -i hw:0 \
  -vf 'hwmap=derive_device=vaapi,scale_vaapi=w=1920:h=1080:format=nv12' \
  -c:v h264_vaapi -g 120 -b:v 3M -maxrate 3M -pix_fmt vaapi_vld -c:a aac -ab 96k -threads $(nproc) \
  output.mkv

kill %1

作为进一步的解决方法,您可以通过窗口管理器将显示网络摄像头内容的窗口始终保持在最上层。 - xuiqzy
谢谢,那是我尝试的第一件事。不幸的是,从man页面中我找不到sway没有这样的功能。我长期使用xmonad,但最近转换到sway,因为qutebrowser是wayland本地化的。 - nrdxp
1个回答

4

此时可能是不可能的。

这似乎是ffmpeg的vaapi后端的限制。我注意到Intel的QuickSync后端有一个overlay_qsv滤镜,但没有等效的overlay_vaapi

理论上,一旦使用hevc_vaapi编码,就可以使用hwdownload滤镜将硬件表面下载到软件缓冲区,以便在编码的最后阶段使用软件overlay滤镜进行叠加。我现在会保留这个问题,看看是否有人可以帮助解决这个问题或者对这个主题了解更多。

关于QuickSync的说明:

在构建支持QuickSync并尝试使用它之后,似乎缺少从kmsgrab设备派生表面的能力,导致ffmpeg出现function not implemented错误。


顺便说一下,我在使用x11grab时也遇到了同样的问题。我尝试通过vaapi解码+vaapi缩放+qsv编码来欺骗它,但是没有希望。不知何故,它无法解析“hwmap”过滤器。 - DrSensor
你好 @DrSensor,能否在这里分享一下你的FFmpeg命令?我可以看一下并加以处理。 - Dennis Mungai
在FFmpeg中有一个Vulkan的覆盖过滤器,让我看看能做些什么来使这样的命令生效。 - Dennis Mungai

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