mirror of
https://github.com/LCTT/TranslateProject.git
synced 2024-12-26 21:30:55 +08:00
9b42f604c7
@Pabloxllwe 本文首发地址:https://linux.cn/article-15648-1.html 您的 LCTT 专页:https://linux.cn/lctt/Pabloxllwe
265 lines
10 KiB
Markdown
265 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: "Pabloxllwe"
|
||
[#]: reviewer: "wxy"
|
||
[#]: publisher: "wxy"
|
||
[#]: url: "https://linux.cn/article-15648-1.html"
|
||
|
||
如何在 Linux 中使用旧相机作为网络摄像头
|
||
======
|
||
|
||
![][0]
|
||
|
||
> 我用 gphoto2 给我的旧单反相机带来了新的生命,把它变成了 Linux 电脑的网络摄像头。
|
||
|
||
今年,在我基本上放弃了 MacBook,转而使用 NixOS 机器之后,我开始在与人进行视频通话时被要求“打开摄像头”。这是一个问题,因为我没有网络摄像头。我考虑购买一个,但后来我意识到我有一台完好无损的 2008 年产的佳能 EOS Rebel XS 数码单反相机放在书架上。这台相机有一个 mini-USB 接口,所以我自然而然地思考:一台数码单反相机、一个 mini-USB 接口和一台台式电脑,是否意味着我能拥有一个网络摄像头?
|
||
|
||
只有一个问题。我的佳能 EOS Rebel XS 不能录制视频。它可以拍摄一些漂亮的照片,仅此而已。所以这结束了?
|
||
|
||
还是有别的办法?
|
||
|
||
恰好有一个叫做 [gphoto2](http://gphoto.org/) 的神奇的开源软件。一旦安装,它允许你从计算机控制各种支持的相机,并拍摄照片和视频。
|
||
|
||
### 支持的相机
|
||
|
||
首先,了解你的设备是否得到支持:
|
||
|
||
```
|
||
$ gphoto2 --list-cameras
|
||
```
|
||
|
||
### 拍摄图像
|
||
|
||
你可以用它拍照:
|
||
|
||
```
|
||
$ gphoto2 --capture-image-and-download
|
||
```
|
||
|
||
快门触发,图像会保存到你当前的工作目录中。
|
||
|
||
### 录制视频
|
||
|
||
我意识到了这里的潜力,所以尽管我的相机没有视频功能,我还是决定尝试 `gphoto2 --capture-movie` 命令。不知怎么,尽管我的相机不支持视频功能,`gphoto2` 仍然能够生成一个 MJPEG 文件!
|
||
|
||
在我的相机上,我需要将其置于“实时预览”模式下,然后 `gphoto2` 才能录制视频。这包括将相机设置为纵向模式,然后按下 “<ruby>设置<rt>Set</rt></ruby>” 按钮,使取景器关闭,相机屏幕显示图像。不幸的是,这还不足以将其用作网络摄像头。它仍然需要分配一个视频设备,例如 `/dev/video0`。
|
||
|
||
### 安装 ffmpeg 和 v4l2loopback
|
||
|
||
毫不奇怪,有一个开源的解决方案来解决这个问题。首先,使用你的包管理器安装 `gphoto2`、`ffmpeg` 和 `mpv`。例如,在 Fedora 、CentOS 、Mageia 和类似的 Linux 发行版上:
|
||
|
||
```
|
||
$ sudo dnf install gphoto2 ffmpeg mpv
|
||
```
|
||
|
||
在 Debian、Linux Mint 及其类似发行版:
|
||
|
||
```
|
||
$ sudo apt install gphoto2 ffmpeg mpv
|
||
```
|
||
|
||
我使用的是 NixOS,这是我的配置文件:
|
||
|
||
```
|
||
# configuration.nix
|
||
...
|
||
environment.systemPackages = with pkgs; [
|
||
ffmpeg
|
||
gphoto2
|
||
mpv
|
||
...
|
||
]
|
||
```
|
||
|
||
创建虚拟视频设备需要使用 `v4l2loopback` Linux 内核模块。在撰写本文时,该功能未包含在主线内核中,因此你需要自己下载和编译它:
|
||
|
||
```
|
||
$ git clone https://github.com/umlaeute/v4l2loopback
|
||
$ cd v4l2loopback
|
||
$ make
|
||
$ sudo make install
|
||
$ sudo depmod -a
|
||
```
|
||
|
||
如果你像我一样使用 NixOS ,你可以在 `configuration.nix` 中添加额外的模块包:
|
||
|
||
```
|
||
[...]
|
||
boot.extraModulePackages = with config.boot.kernelPackages;
|
||
[ v4l2loopback.out ];
|
||
boot.kernelModules = [
|
||
"v4l2loopback"
|
||
];
|
||
boot.extraModprobeConfig = ''
|
||
options v4l2loopback exclusive_caps=1 card_label="Virtual Camera"
|
||
'';
|
||
[...]
|
||
```
|
||
|
||
在 NixOS 上, 运行 `sudo nixos-rebuild switch`,然后重启。
|
||
|
||
### 创建一个视频设备
|
||
|
||
假设你的计算机当前没有 `/dev/video` 设备,你可以借助 `v4l2loopback` 在需要时创建一个。
|
||
|
||
运行以下命令,将 `gphoto2` 中的数据发送到 `ffmpeg`,使用设备如 `/dev/video0` 设备:
|
||
|
||
```
|
||
$ gphoto2 --stdout --capture-movie |
|
||
ffmpeg -i - -vcodec rawvideo -pix_fmt yuv420p -f v4l2 /dev/video0
|
||
```
|
||
|
||
你得到的输出是这样的:
|
||
|
||
```
|
||
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
|
||
```
|
||
|
||
要查看来自网络摄像头的视频,请使用 `mpv` 命令:
|
||
|
||
```
|
||
$ mpv av://v4l2:/dev/video0 --profile=low-latency --untimed
|
||
```
|
||
|
||
![Streaming a live feed from the webcam][2]
|
||
|
||
### 自动启动你的网络摄像头
|
||
|
||
每次想使用网络摄像头时都需要执行一次命令有点麻烦。幸运的是,你可以在启动时自动运行此命令。我将其实现为一个 `systemd` 服务:
|
||
|
||
```
|
||
# 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" ];
|
||
};
|
||
...
|
||
```
|
||
|
||
在 NixOS 上,运行 `sudo nixos-rebuild switch`,然后重新启动你的计算机。你的网络摄像头已经开启并处于活动状态。
|
||
|
||
要检查是否存在任何问题,可以使用 `systemctl status webcam` 命令。它会告诉你服务最后一次运行的时间,并提供其以前输出的日志。这对于调试非常有用。
|
||
|
||
### 迭代以使其变得更好
|
||
|
||
止步于此也许很诱人。但是,考虑到当前的全球危机,我们可能需要思考是否有必要一直开着网络摄像头。这让我感到不太理想,原因如下:
|
||
|
||
- 这浪费电。
|
||
- 这类事情涉及隐私问题。
|
||
|
||
我的摄像头有一个镜头盖,所以说实话,第二个原因并不真的让我感到困扰。当我不使用网络摄像头时,我总是可以把镜头盖上。然而,让一个耗电量大的单反相机整天开着(更不用说需要解码视频所需的 CPU 开销),对我的电费并没有任何好处。
|
||
|
||
理想情况是:
|
||
|
||
- 我一直把相机插在电脑上,但是关闭的。
|
||
- 当我想使用网络摄像头时,我按下相机的电源按钮将其打开。
|
||
- 我的计算机会检测到相机并启动 systemd 服务。
|
||
- 使用网络摄像头完成后,我再次将其关闭。
|
||
|
||
为了实现这一点,你需要使用一个自定义的 udev 规则。
|
||
|
||
udev 规则可以告诉你的计算机,当它发现某个设备已经可用时执行某个任务。这可以是外部硬盘甚至是非 USB 设备。在这种情况下,你需要通过其 USB 连接识别相机。
|
||
|
||
首先,指定 udev 规则被触发时要运行的命令。你可以用一个 shell 脚本来完成(`systemctl restart webcam` 应该可以工作)。我运行的是 NixOS,所以我只需要创建一个派生包(一个 Nix 包),它会重新启动 systemd 服务:
|
||
|
||
```
|
||
# 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''
|
||
```
|
||
|
||
接下来,实际定义 udev 规则。查找摄像头的设备和厂商 ID。使用 `lsusb` 命令可以完成此操作。该命令可能已经安装在你的发行版上,但我不经常使用它,因此我只需要根据需要使用 `nix-shell` 安装它:
|
||
|
||
```
|
||
$ nix-shell -p usbutils
|
||
```
|
||
|
||
无论你的计算机上已经安装了它,还是刚刚安装,请运行 `lsusb` :
|
||
|
||
```
|
||
$ lsusb
|
||
Bus 002 Device 008: ID 04a9:317b Canon, Inc. Canon Digital Camera[...]
|
||
```
|
||
|
||
在此输出中,厂商 ID 为 `04a9`,设备 ID 为 `317b`。这已足以创建 udev 规则:
|
||
|
||
```
|
||
ACTION=="add", SUBSYSTEM=="usb",
|
||
ATTR{idVendor}=="04a9",
|
||
ATTR{idProduct}=="317b",
|
||
RUN+="/usr/local/bin/start-webcam.sh"
|
||
```
|
||
|
||
或者,如果你使用的是 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"'';[...]
|
||
```
|
||
|
||
最后,在你的 `start-webcam` systemd 服务中删除 `wantedBy = ["multi-user.target"];` 这一行。(如果保留它,则无论相机是否开启,该服务都会在下次重启时自动启动。)
|
||
|
||
### 重复使用旧技术
|
||
|
||
我希望这篇文章能让你在放弃一些旧技术之前三思而后行。Linux 可以为技术注入活力,无论是你的电脑还是数码相机或其他外围设备等简单的东西。
|
||
|
||
--------------------------------------------------------------------------------
|
||
|
||
via: https://opensource.com/article/22/12/old-camera-webcam-linux
|
||
|
||
作者:[Tom Oliver][a]
|
||
选题:[lkxed][b]
|
||
译者:[Pabloxllwe](https://github.com/Pabloxllwe)
|
||
校对:[wxy](https://github.com/wxy)
|
||
|
||
本文由 [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
|
||
[0]: https://img.linux.net.cn/data/attachment/album/202303/21/233633z1qxdoq1shrx1xmc.jpg |