硬件:kabylake HD630 GPU
我对ffmpeg相当陌生,我正尝试使用vaapi加速(没有它,太慢了)来捕获我的网络摄像头和屏幕。我想使用ffmpeg在右下角覆盖网络摄像头。我需要使用kmsgrab
,因此我可以在Linux上录制Wayland会话。
我要解决此问题的方法只是使用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 -threads $(nproc) - | 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
到目前为止,我已经尝试将网络摄像头作为第二输入添加到截屏视频并使用:
-filter_complex '[1] scale=w=320:h=240,hwupload,format=nv12 [tmp]; \
[0][tmp] overlay=x=1580:y=795,hwmap=derive_device=vaapi,scale_vaapi=w=1920:h=1080:format=nv12' \
但是我得到了错误:
Impossible to convert between the formats supported by the filter 'Parsed_hwupload_1' and the filter 'auto_scaler_0'
Error reinitializing filters!
Failed to inject frame into filter network: Function not implemented
一时],这可能是不可能的。
我似乎是ffmpeg
的vaapi后端的限制。我注意到英特尔的QuickSync后端有一个overlay_qsv
过滤器,但是没有等效的overlay_vaapi
;它没有过滤器。一旦使用hwdownload
进行编码以利用软件hevc_vaapi
过滤器,可能会有一种机制将硬件表面下载到overlay
到软件缓冲区中,但是我对ffmpeg
的过滤器图的了解已经开始上我现在将其保持打开状态,看看是否有人可以为此目的进行工作。
使用QuickSync构建并尝试使用it后,似乎缺乏从kmsgrab
设备派生表面的功能,导致从function not implemented
产生ffmpeg
错误。