I have a Canon EOS M50 digital camera, and I just got a sweet VESA mount for it, so I wanted to use it as a webcam. This is partially because I assumed it would have very high picture quality, partly because I basically never use it, and partially because I know that it ought to be theoretically possible on my linux machine, since Canon makes a (closed source, paid) webcam utility for Mac and Windows, so I wanted to see how it would work on linux, if indeed it could.
It did not take long to find Video4Linux2 (a.k.a. “v4l2”) and gPhoto (gphoto2
in Aptitude), which can --capture-image
or --capture-movie
from a supported camera1 when attacked by USB. Best of all, you can --stdout
it too, which means that movie can be piped into ffmpeg
:
gphoto2 --stdout --capture-movie | ffmpeg -i - -vcodec rawvideo -pix_fmt yuv420p -threads 0 -f v4l2 /dev/videoX
Or, even better, if you have an Nvidia GPU that supports2 hardware acceleration for video transcoding:
gphoto2 --stdout --capture-movie | ffmpeg -hwaccel nvdec -c:v mjpeg_cuvid -i - -vcodec rawvideo -pix_fmt yuv420p -threads 0 -f v4l2 /dev/videoX
where X
is the next available video device index (e.g. if you run ls /dev/video*
and the highest value for X
is 0
, like /dev/video0
, then you’ll use 1
in the command. If no video capture devices exist, use 0
, as I’ll use hereafter).
You need first only install the relevant dependencies, sudo apt install gphoto2 v4l2loopback-utils
, and load the v4l2loopback
kernel module.
To confirm this is working, you can run ffplay /dev/video0
in another terminal–if your camera is on and your lens cover is removed, you should see a very happy person on your screen!
I also found some good tips for using gPhoto here, at the very end.
Let’s see if this works:
All good so far…
Nice! Now let’s see if my video-conferencing apps will pick up the feed…
$@&#!!!
So, this is where this Github issue comment came in to save my day:
modprobe v4l2loopback devices=1 max_buffers=2 exclusive_caps=1 card_label="VirtualCam"
In fact, modprobe v4l2loopback exclusive_caps=1
works just fine, so we know that was the missing piece. Indeed, this is covered in the Arch wiki on the topic. From the official documentation:
This will enable ’exclusive_caps’ mode that only reports CAPTURE/OUTPUT capabilities exclusively. The newly created device will announce OUTPUT capabilities only (so ordinary webcam applications (including Chrome) won’t see it). As soon as you have attached a producer to the device, it will start announcing CAPTURE capabilities only (so applications that refuse to open devices that have other capabilities apart from capturing can open it too.)
“caps” = capabilities.
Viola:
Obviously, this wasn’t the craziest linux-y task, but I think it’s a good illustration of why its good to just try doing things, whether or not you think you need them and whether or not you even think they’ll work: you’ll learn something along the way. Generally, this looks like taking some kind of high-level abstraction, like “my camera can transmit live footage over a USB”, which you’ve used to deduce some other thing, like “I should be able to use such a video feed as a webcam”, and then turning it into some concrete understanding of a process, like “gPhoto can control my camera, initiating a movie capture to stdout, which ffmpeg can pick up and register as a video device at /dev/video0
, using the v4l2 kernel module, as long as the reported capabilities match those expected by my application”. Often, this will even lend itself to a bunch of interesting follow-on research projects, like understanding the specific data type and procedure used by linux to transmit live video, how devices real and synthetic are mounted, or how hls works.