Feeding content of an X-Window to a virtual camera

492 views Asked by At

I want to feed a virtual webcam device from an application window (under Linux/Xorg). I have so far just maximised the window and then used ffmpeg to grab the whole screen like this:

ffmpeg \
    -f x11grab -framerate 15 -video_size 1280x1024 -i :0+0,0 \
    -f v4l2 -vcodec rawvideo -pix_fmt yuv420p /dev/video6

where /dev/video6 is my v4l2loopback device. This works and I can use the virtual camera in video calls in chrome. This also indicates that the v4l2loopback module is correctly loaded into the kernel.

Unfortunately, it seems that ffmpeg can only read the whole screen, but not an application window. gstreamer on the other hand can. Playing around with gst-launch-1.0, I was hoping that I could get away with something like this:

gst-launch-1.0 ximagesrc xid=XID_OF_MY_WINDOW \
    ! "video/x-raw" \
    ! v4l2sink device=/dev/video6

However, that complains that Device '/dev/video6' is not an output device.

Given that ffmpeg seems happy to write to /dev/video6 I also tried piping the gst output to ffmpeg like this:

gst-launch-1.0 ximagesrc xid=XID_OF_MY_WINDOW \
    ! "video/x-raw" \
    ! filesink location=/dev/stdout \
    | ffmpeg -i - -codec copy -f v4l2 -vcodec rawvideo -pix_fmt yuv420p /dev/video6

But then ffmpeg complains about Invalid data found when processing input.

This is running inside an xvfb headless environment, so mouse interactions will not work. This rules out obs as far as I can see.

I'm adding the chrome tag, because I see that chrome in principle would also provide a virtual camera via the --use-fake-device-for-media-stream switch. However, it seems that this switch only supports a static file rather than a stream.

Although I don't see why, it might be relevant that the other "application window" window is simply a second browser window. So the setup is google meet (or similar) in one browser window and the virtual camera gets fed vrom a second browser window.

1

There are 1 answers

2
SeB On

You may try adding identity before v4l2sink:

# Better restart kernel module
sudo rmmod v4l2loopback
sudo modprobe v4l2loopback <your_options>

# Got window id from xwininfo
gst-launch-1.0 ximagesrc xid=0x3000010 ! videoconvert ! video/x-raw,format=YUY2 ! identity drop-allocation=1 ! v4l2sink device=/dev/video6

You should be able to display with:

gst-launch-1.0 v4l2src device=/dev/video6 ! videoconvert ! xvimagesink

No idea for your case, but for some browser on some targets/os/versions you may have to set exclusive_caps=1 into options when loading v4l2loopback kernel module.

Also note that this may not support any source window resizing.