mirror of
https://github.com/LCTT/TranslateProject.git
synced 2025-01-07 22:11:09 +08:00
261 lines
10 KiB
Markdown
261 lines
10 KiB
Markdown
[#]: subject: "How I use my old camera as a webcam with Linux"
|
||
[#]: via: "https://opensource.com/article/22/12/old-camera-webcam-linux"
|
||
[#]: author: "Tom Oliver https://opensource.com/users/tomoliver"
|
||
[#]: collector: "lkxed"
|
||
[#]: translator: " "
|
||
[#]: reviewer: " "
|
||
[#]: publisher: " "
|
||
[#]: url: " "
|
||
|
||
How I use my old camera as a webcam with Linux
|
||
======
|
||
|
||
This year after largely abandoning my MacBook in favor of a NixOS machine, I started getting requests to "turn my camera on" when video calling people. This was a problem because I didn't have a webcam. I thought about buying one, but then I realized I had a perfectly good Canon EOS Rebel XS DSLR from 2008 lying around on my shelf. This camera has a mini-USB port, so naturally, I pondered: Did a DSLR, mini-USB port, and a desktop PC mean I could have a webcam?
|
||
|
||
There's just one problem. My Canon EOS Rebel XS isn't capable of recording video. It can take some nice pictures, but that's about it. So that's the end of that.
|
||
|
||
Or is it?
|
||
|
||
There happens to be some amazing open source software called [gphoto2][1]. Once installed, it allows you to control various supported cameras from your computer and it takes photos and videos.
|
||
|
||
### Supported cameras
|
||
|
||
First, find out whether yours is supported:
|
||
|
||
```
|
||
$ gphoto2 --list-cameras
|
||
```
|
||
|
||
### Capture an image
|
||
|
||
You can take a picture with it:
|
||
|
||
```
|
||
$ gphoto2 --capture-image-and-download
|
||
```
|
||
|
||
The shutter activates, and the image is saved to your current working directory.
|
||
|
||
### Capture video
|
||
|
||
I sensed the potential here, so despite the aforementioned lack of video functionality on my camera, I decided to try `gphoto2 --capture-movie`. Somehow, although my camera does not support video natively, gphoto2 still manages to spit out an MJPEG file!
|
||
|
||
On my camera, I need to put it in "live-view" mode before gphoto2 records video. This consists of setting the camera to portrait mode and then pressing the **Set** button so that the viewfinder is off and the camera screen displays an image. Unfortunately, though, this isn't enough to be able to use it as a webcam. It still needs to get assigned a video device, such as `/dev/video0`.
|
||
|
||
### Install ffmpeg and v4l2loopback
|
||
|
||
Not surprisingly, there's an open source solution to this problem. First, use your package manager to install `gphoto2`, `ffmpeg`, and `mpv`. For example, on Fedora, CentOS, Mageia, and similar:
|
||
|
||
```
|
||
$ sudo dnf install gphoto2 ffmpeg mpv
|
||
```
|
||
|
||
On Debian, Linux Mint, and similar:
|
||
|
||
```
|
||
$ sudo apt install gphoto2 ffmpeg mpv
|
||
```
|
||
|
||
I use NixOS, so here's my configuration:
|
||
|
||
```
|
||
# configuration.nix
|
||
...
|
||
environment.systemPackages = with pkgs; [
|
||
ffmpeg
|
||
gphoto2
|
||
mpv
|
||
...
|
||
```
|
||
|
||
Creating a virtual video device requires the `v4l2loopback` Linux kernel module. At the time of this writing, that capability is not included in the mainline kernel, so you must download and compile it yourself:
|
||
|
||
```
|
||
$ git clone https://github.com/umlaeute/v4l2loopback
|
||
$ cd v4l2loopback
|
||
$ make
|
||
$ sudo make install
|
||
$ sudo depmod -a
|
||
```
|
||
|
||
If you're using NixOS like me, you can just add the extra module package in `configuration.nix`:
|
||
|
||
```
|
||
[...]
|
||
boot.extraModulePackages = with config.boot.kernelPackages;
|
||
[ v4l2loopback.out ];
|
||
boot.kernelModules = [
|
||
"v4l2loopback"
|
||
];
|
||
boot.extraModprobeConfig = ''
|
||
options v4l2loopback exclusive_caps=1 card_label="Virtual Camera"
|
||
'';
|
||
[...]
|
||
```
|
||
|
||
On NixOS, run `sudo nixos-rebuild switch` and then reboot.
|
||
|
||
### Create a video device
|
||
|
||
Assuming your computer currently has no `/dev/video` device, you can create one on demand thanks to the `v4l2loopback`.
|
||
|
||
Run this command to send data from `gphoto2` to `ffmpeg`, using a device such as `/dev/video0` device:
|
||
|
||
```
|
||
$ gphoto2 --stdout --capture-movie |
|
||
ffmpeg -i - -vcodec rawvideo -pix_fmt yuv420p -f v4l2 /dev/video0
|
||
```
|
||
|
||
You get output like this:
|
||
|
||
```
|
||
ffmpeg version 4.4.1 Copyright (c) 2000-2021 the FFmpeg developers
|
||
built with gcc 11.3.0 (GCC)
|
||
configuration: --disable-static ...
|
||
libavutil 56. 70.100 / 56. 70.100
|
||
libavcodec 58.134.100 / 58.134.100
|
||
libavformat 58. 76.100 / 58. 76.100
|
||
libavdevice 58. 13.100 / 58. 13.100
|
||
libavfilter 7.110.100 / 7.110.100
|
||
libavresample 4. 0. 0 / 4. 0. 0
|
||
libswscale 5. 9.100 / 5. 9.100
|
||
libswresample 3. 9.100 / 3. 9.100
|
||
libpostproc 55. 9.100 / 55. 9.100
|
||
Capturing preview frames as movie to 'stdout'. Press Ctrl-C to abort.[mjpeg @ 0x1dd0380] Format mjpeg detected only with low score of 25, misdetection possible!
|
||
Input #0, mjpeg, from 'pipe:':
|
||
Duration: N/A, bitrate: N/A
|
||
Stream #0:0: Video: mjpeg (Baseline), yuvj422p(pc, bt470bg/unknown/unknown), 768x512 ...
|
||
Stream mapping:
|
||
Stream #0:0 -> #0:0 (mjpeg (native) -> rawvideo (native))[swscaler @ 0x1e27340] deprecated pixel format used, make sure you did set range correctly
|
||
Output #0, video4linux2,v4l2, to '/dev/video0':
|
||
Metadata:
|
||
encoder : Lavf58.76.100
|
||
Stream #0:0: Video: rawvideo (I420 / 0x30323449) ...
|
||
Metadata:
|
||
encoder : Lavc58.134.100 rawvideoframe= 289 fps= 23 q=-0.0 size=N/A time=00:00:11.56 bitrate=N/A speed=0.907x
|
||
```
|
||
|
||
To see the video feed from your webcam, use `mpv`:
|
||
|
||
```
|
||
$ mpv av://v4l2:/dev/video0 --profile=low-latency --untimed
|
||
```
|
||
|
||
![Streaming a live feed from the webcam][2]
|
||
|
||
### Start your webcam automatically
|
||
|
||
It's a bit annoying to execute a command every time you want to use your webcam. Luckily, you can run this command automatically at startup. I implement it as a `systemd` service:
|
||
|
||
```
|
||
# configuration.nix
|
||
...
|
||
systemd.services.webcam = {
|
||
enable = true;
|
||
script = ''
|
||
${pkgs.gphoto2}/bin/gphoto2 --stdout --capture-movie |
|
||
${pkgs.ffmpeg}/bin/ffmpeg -i - \
|
||
-vcodec rawvideo -pix_fmt yuv420p -f v4l2 /dev/video0
|
||
'';
|
||
wantedBy = [ "multi-user.target" ];
|
||
};
|
||
...
|
||
```
|
||
|
||
On NixOS, run `sudo nixos-rebuild switch` and then reboot your computer. Your webcam is on and active.
|
||
|
||
To check for any problems, you can use `systemctl status webcam`. This tells you the last time the service was run and provides a log of its previous output. It's useful for debugging.
|
||
|
||
### Iterating to make it better
|
||
|
||
It's tempting to stop here. However, considering the current global crises, it may be pertinent to wonder whether it's necessary to have a webcam on all the time. It strikes me as sub-optimal for two reasons:
|
||
|
||
- It's a waste of electricity.
|
||
- There are privacy concerns associated with this kind of thing.
|
||
|
||
My camera has a lens cap, so to be honest, the second point doesn't really bother me. I can always put the lens cap on when I'm not using the webcam. However, leaving a big power-hungry DSLR camera on all day (not to mention the CPU overhead required for decoding the video) isn't doing anything for my electricity bill.
|
||
|
||
The ideal scenario:
|
||
|
||
- I leave my camera plugged in to my computer all the time but switched off.
|
||
- When I want to use the webcam, I switch on the camera with its power button.
|
||
- My computer detects the camera and starts the systemd service.
|
||
- After finishing with the webcam, I switch it off again.
|
||
|
||
To achieve this, you need to use a custom [udev rule][3].
|
||
|
||
A udev rule tells your computer to perform a certain task when it discovers that a device has become available. This could be an external hard drive or even a non-USB device. In this case, you need it to [recognize the camera through its USB connection][4].
|
||
|
||
First, specify what command to run when the udev rule is triggered. You can do that as a shell script (`systemctl restart webcam` should work). I run NixOS, so I just create a derivation (a Nix package) that restarts the systemd service:
|
||
|
||
```
|
||
# start-webcam.nix
|
||
with import <nixpkgs> { };
|
||
writeShellScriptBin "start-webcam" ''
|
||
systemctl restart webcam
|
||
# debugging example
|
||
# echo "hello" &> /home/tom/myfile.txt
|
||
# If myfile.txt gets created then we know the udev rule has triggered properly''
|
||
```
|
||
|
||
Next, actually define the udev rule. Find the device and vendor ID of the camera. Do this by using the `lsusb` command. That command is likely already installed on your distribution, but I don't use it often, so I just install it as needed using `nix-shell`:
|
||
|
||
```
|
||
$ nix-shell -p usbutils
|
||
```
|
||
|
||
Whether you already have it on your computer or you've just installed it, run `lsusb`:
|
||
|
||
```
|
||
$ lsusb
|
||
Bus 002 Device 008: ID 04a9:317b Canon, Inc. Canon Digital Camera[...]
|
||
```
|
||
|
||
In this output, the vendor ID is 04a9 and the device ID is 317b. That's enough to create the udev rule:
|
||
|
||
```
|
||
ACTION=="add", SUBSYSTEM=="usb",
|
||
ATTR{idVendor}=="04a9",
|
||
ATTR{idProduct}=="317b",
|
||
RUN+="/usr/local/bin/start-webcam.sh"
|
||
```
|
||
|
||
Alternatively, if you're using NixOS:
|
||
|
||
```
|
||
# configuration.nix[...]let
|
||
startWebcam = import ./start-webcam.nix;[...]
|
||
services.udev.extraRules = ''
|
||
ACTION=="add", \
|
||
SUBSYSTEM=="usb", \
|
||
ATTR{idVendor}=="04a9", \
|
||
ATTR{idProduct}=="317b", \
|
||
RUN+="${startWebcam}/bin/start-webcam"'';[...]
|
||
```
|
||
|
||
Finally, remove the **wantedBy = ["multi-user.target"];** line in your `start-webcam` systemd service. (If you leave it, then the service starts automatically when you next reboot, whether the camera is switched on or not.)
|
||
|
||
### Reuse old technology
|
||
|
||
I hope this article has made you think twice before chucking some of your old tech. Linux can breathe life back into technology, whether it's your [computer][5] or something simple like a digital camera or some other peripheral.
|
||
|
||
--------------------------------------------------------------------------------
|
||
|
||
via: https://opensource.com/article/22/12/old-camera-webcam-linux
|
||
|
||
作者:[Tom Oliver][a]
|
||
选题:[lkxed][b]
|
||
译者:[译者ID](https://github.com/译者ID)
|
||
校对:[校对者ID](https://github.com/校对者ID)
|
||
|
||
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
|
||
|
||
[a]: https://opensource.com/users/tomoliver
|
||
[b]: https://github.com/lkxed
|
||
[1]: https://opensource.com/article/20/7/gphoto2-linux
|
||
[2]: https://opensource.com/sites/default/files/2022-12/streaming-webcam.png
|
||
[3]: https://opensource.com/article/18/11/udev
|
||
[4]: https://opensource.com/article/22/1/cameras-usb-ports-obs
|
||
[5]: https://opensource.com/article/22/4/how-linux-saves-earth
|
||
|