【思兼】Klipper 网页使用摄像头比较全指南
前言
原创文章,转载引用请务必注明链接。水平有限,如有疏漏,欢迎指正交流。
本文分为两部分:一是针对我出售的 Klipper 免驱摄像头的专有内容,二是关于使用摄像头的通用内容。
文章如有更新请访问 DFRobot社区 或者 cnblogs博客园(排版更好)。
欢迎对 Klipper 固件感兴趣,以及对改版 CNC 加工的 Voron 三叉戟、v0、v2.4 感兴趣的朋友加群交流(QQ Group:490111638)
一、专有内容 | Exclusive Content
请结合视频了解如何快速入门:思兼的 Klipper 免驱摄像头快速使用指南,做这个主要是解决以下问题:
- 上位机支持什么样的摄像头/哪些摄像头免驱?
- 哪种摄像头价格便宜,成像质量好?
- 如何在 Fluidd/Mainsail/Octoprint 中设置使用摄像头?
- 众多摄像头选项,如何配置和选择?
- 为什么我步骤都对,就是没有图像,如何排除故障?
- 除了监控,摄像头还有没有其他玩法?
其实预算足够,可以考虑购买这篇文章 Best Cameras for OctoPrint of 2021 推荐的,比如 罗技C270 等。
1、关于 Klipper 使用摄像头的一些问题
- 除了树莓派,大部分上位机都不支持视频的硬件解码
- 大多数上位机使用 CPU 软件解码,如果性能不足会出现卡滞现象,可以适当降低分辨率和帧率
- Fluidd 默认的 640x480@10fps 多能满足需求
- 高性能 CPU 酌情使用 800x600 分辨率,并根据使用目的设置帧率
- 请为上位机提供稳定供电,5V@2A 以上比较稳妥
- 和 Windows 下一样,最大分辨率用于静态拍照,视频录制模式无法达到最大分辨率
- MJPG-Streamer 比较吃 CPU 资源,KlipperScreen 比较吃内存资源
- 使用过程中建议为上位机 CPU 增加主动散热,摄像头芯片可以贴一个小散热片
- 安装此 USB 摄像头时,请确保没有正在执行打印任务,避免意外中断通讯
- 在低性能 CPU 上如果摄像头移动过快超出 CPU 处理能力,可能会导致图像卡死,可以尝试使用
µStreamer
或者重启 webcamd
服务,并尽量固定摄像头位置
2、安装使用 Klipper 摄像头
2.1 安装摄像头软件依赖
# 使用一键脚本,第一种方式会导致 kiauh 报无效参数错误,原因暂未知。
# 脚本默认策略是不相信本地软件环境,会备份并删除旧文件:.gitconfig、klipper_config/webcamd.txt、kiauh
# curl -fsSL http://klipper.7130404.xyz:8001/enable_webcam.sh | bash
bash <(curl -fsSL http://klipper.7130404.xyz:8001/add_webcam.sh)
2.2 安装 MJPG-Streamer
如视频中所示,在出现的 KIAUH 助手中删除并重新安装 MJPG-Streamer:
2.3 添加摄像头
添加摄像头,设置如下,刷新主面板即可看到摄像头内容:
- MJPEG Stream | 传统方式,Fluidd 被动接收 上位机上的 MJPEG 服务以 webcamd.txt 中 配置好的分辨率和帧率 推送来的视频流(连续的图片序列),此种方式多数情况下占用大量带宽,并且网络不稳定时会出现问题。
- MJPEG Adaptive | 推荐方式,Fluidd 主动拉取 单帧图片组成视频流,因此你可以设置合适的帧率,此种方式更稳定,占用网络带宽也更小。
- IP Camera| 实验性选项,仅支持 HTML5 视频,具体未测试。
- HTTP Page |(内嵌网页,支持更多视频来源)
- U4VL (Mainsail)
3、修改基本参数:分辨率和帧率
# 修改 ~/klipper_config/webcam.txt 最下面一行
camera_usb_options="-r 640x480 -f 10 -y -d /dev/v4l/by-id/usb-Etron_Technology__Inc._USB2.0_Camera-video-index0"
# -r (resolution, 分辨率):640x480 修改为你想要的分辨率如 800x600
# -f (fps,帧率):10 修改为 25
重启生效:sudo systemctl restart webcamd
二、通用内容 | Generic Content
2.1 启用简单安全认证 | Enable Authentication
# 修改 ~/klipper_config/webcam.txt 下面几行
-#camera_http_options="-n"
+camera_http_options="-n -c [username]:[password]"
默认使用http访问时,密码传输采用明文,存在一定安全隐患,如需更严格的安全保护,请参考 Secure Webcam streaming with MJPG-Streamer on a Raspberry Pi。
2.2 启用多摄像头 | Enable Multiple Cameras
参考链接如下,注意是有先后传承顺序的,即使是使用 Fluidd,KIAUH 下载使用的摄像头依赖软件和配置文件也是来源于 Mainsail,所以我常说 Fluidd 有问题可以去看 Mainsial 文档:
主要操作就是
- 复制一份
webcam1.txt
配置文件
- 更改监听端口:8080~8083,受限于 nginx 默认设置,目前最多支持四个摄像头。
- 更改捕获的视频设备地址,注意相同设备的话,所以配置文件都要更改,可以使用 by-path
- 重启服务
- 新的视频地址为
webcam2/?action=stream
对应 8081
对应 webcam1.txt
- aka 配置文件从 0 开始,摄像头地址从 1 开始,fluidd 的文档错了
# 复制一份配置文件
cp ~/klipper_config/webcam.txt ~/klipper_config/webcam1.txt
# 更改监听端口
sed -i '/#camera_http_options=/a camera_http_options="-n -p 8081"' ~/klipper_config/webcam1.txt
# 由于同一摄像头其 id 相同,所以我们用 path 来进行区分,此处类似 klipper 的 serial 地址查找方法:
ls /dev/v4l/by-path/*
# 地址分别对应不同的USB接口,选择 index0 地址修改所有 webcam*.txt,使每个配置文件中的设备号不同。例如
camera_usb_options="-r 640x480 -f 10 -y -d /dev/v4l/by-path/platform-xhci-hcd.3.auto-usb-0:2:1.0-video-index0"
# 重启服务生效
sudo systemctl restart webcamd.service
2.3 启用延时摄影 | Enable Timelapse
上次研究这个还是在去年 8 月份,现在该组件已经合并到 Mainsail 里面了,话说 Mainsail 功能是真的丰富,不排除有一天切换到它。
-
项目地址,项目镜像地址
-
安装指南
# 安装 ffmpeg 用于合成视频
sudo apt install ffmpeg
# 下载并安装 moonraker timelapse 组件
cd ~/ && git clone https://hub.0z.gs/mainsail-crew/moonraker-timelapse.git
bash ~/moonraker-timelapse/install.sh
-
配置参考
修改 printer.cfg
如下
# printer.cfg
[include timelapse.cfg]
修改 moonraker.cfg
如下
# moonraker.conf
[timelapse]
## 以下为默认设置,如果需要更改请取消注释
#output_path: ~/timelapse/
## 存储生成的延时摄影视频目录
#frame_path: /tmp/timelapse/
## 存储临时图像的目录
#ffmpeg_binary_path: /usr/bin/ffmpeg
## ffmpeg 所在路径
snapshoturl: http://localhost:8080/?action=snapshot
## 摄像头快照访问地址,如果有多个摄像头可以设置具体的端口号
新版组件采用 moonraker API 来进行修改参数,具体查看上面的文档,也可以手动设置参数,调整分辨率在 webcam.txt
中修改。可以手动在控制台输入 TIMELAPSE_TAKE_FRAME
拍摄图片。
注意:
>
> 即使网页没有添加摄像头,图像和视频也是可以通过上述被访问的,但是即使没有显示,系统资源也会被占用
> 延时摄影相关宏 不支持密码访问 的摄像头
> * 用作延时摄影的摄像头可以采用高分辨率低帧率,如 1600x1200@7fps
-
优化:创建软链接,方便直接在网页查看图片和下载视频
mkdir /home/pi/gcode_files/timelapse/
ln -s /tmp/timelapse/ /home/pi/gcode_files/timelapse/tmp
ln -s /home/pi/timelapse/ /home/pi/gcode_files/timelapse/video
2.4 使用人工智能自动检测打印失败
可以借助 The Spaghetti Detective (TSD) 服务来自动检测炒面,免费服务受限颇多,可以 自己搭建服务器 使用,我手里有一台 Jetson Nano 可以用于测试。
combines improved webcam streaming with AI-driven print failure detection. You can access your printer’s webcam feed from any device, and time-lapses of all your past prints are available on your TSD dashboard. An additional beta feature is a secure tunnel through which you can access your entire OctoPrint interface from any device.
TSD 免费版限制:
- Limited to 1 printer.
- Basic Streaming is at 0.1fps (1 frame per 10 seconds).
- The stream is on only when the printer is printing.
-
10 free Detective Hours/month included
- 50MB / month Tunneling
- Detective Hour is sometimes abbreviated as DH.
2.5 使用 µStreamer 替代 MJPG-Streamer
虽然此实验版 MJPG-Streamer 使用 libjpeg-turbo 而非普通的 libjpeg 库进行编译,编解码速度有所提升,但是还是有优化空间。这里介绍另一个类似的改进项目:µStreamer,它是这么自我介绍的:µStreamer - Lightweight and fast MJPEG-HTTP streamer
也就是更轻量更快速的 MJPG-Streamer 替代服务。我测试下来优点明显,比如:
- 代码配置更简洁
- 支持多线程 JPEG 编码
- 支持树莓派的硬件编码,基于 V4L2 M2M
- 支持断线重连后信号恢复,而无需重启服务
- 支持控制 GPIO 输出
- 支持 WebRTC 串流,降低网络带宽占用,借助 Janus 和 H.264
- 兼容 mjpg-streamer API
但是性能不如 mjpg-streamer,不知道是不是我参数设置不正确。好处是几乎可以完全替代后者,后面会持续关注它。
创建 systemd 服务请参考:init.d and systemctl scripts,µStreamer 不需要 webcamd 和 webcam.txt。
2.6 降低系统和带宽占用 (TBD)
目的是研究如何优化性能、提高流畅度,以下项目需要整理、测试、验证。硬件加速基本就限定树莓派了。
- Fluidd
HTTP Page
:Add camera iframe option with height option
Uses less bandwidth and runs with hw accel in your browser but needs to be setup as a simple web page
基于 pi-h264-to-browser |RPi Cam Pi H264 To Browser is a simple Python application designed to stream hardware encoded h.264 from a Raspberry Pi equiped with a V1, V2, or HQ camera module, directly to a browser. 以及 h264
- webrtc-streamer
I set up webrtc-streamer to get a very low latency (and low bandwidth) camera feed from my printer into a browser, sadly fluidd's options do not allow me to embed that at all.
./webrtc-streamer -vvv v4l2:///dev/video1
https://www.cnblogs.com/savorboard/p/webrtc-rtsp.html
https://community.octoprint.org/t/js-help-needed-better-webcam-streaming-webrtc/4969/10
-
h264rcam | This project was inspired by pi-h264-to-browser ,h264rcam provides an easy way to get a Raspberry Pi Camera stream inside web browser.
https://askubuntu.com/questions/881305/is-there-any-way-ffmpeg-send-video-to-dev-video0-on-ubuntu
-
U4VL | https://www.jianshu.com/p/c08d68a1a505
2.7 远程监控
关于这部分我没有需求,简单说说。
- 建议使用萤石等家用监控摄像头进行监控,自带远程访问功能
- 有访问条件的可以使用 telegram-bot
- 基本方法就是暴露 8080 端口,做强加密;或者使用 VPN
- 还可以推流到 B 站
- 另外家用宽带如果上行下行不对等,上行带宽较小时效果可能不好
- 如果想要进行远程控制打印机,安全起见建议只暴露 moonraker 7125 端口,不要暴露 80 端口(运营商可能也不愿意),可以访问
app.fluidd.xyz
或者 my.mainsail.xyz
访问。如果是自有域名,一是可以创建用户,二是可以修改 cors_domains
策略。
三、其他摄像头方案
3.1 树莓派摄像头 | RPi Cam
注意:树莓派官方以及一些优质厂商提供的摄像头质量很不错,但是也有一些兼容树莓派引脚的劣质摄像头存在,注意甄别。
树莓派官方摄像头出了 3 代,1代支持自动对焦;2代不支持自动对焦,但是性能更好;3代这里就不介绍了。
我们这里都以 Raspberry Pi OS Bullseye
为例,使用方法很简单,说是新版会自动侦测并启用,但是对于 RPi3 等老型号,还需要设置以启动硬件加速: sudo raspi-config
——> Advanced Options
——> Glamor
——> Yes
,重启生效。
然后配置文件修改分辨率帧率即可。更多内容可以查看 官方文档。不过最好购买官方的摄像头,很多很便宜的摄像头显示质量很差。
3.2 手机作为摄像头使用
前面讲过旧手机可以充当 KlipperScreen 的显示触摸屏,其实旧手机的摄像头也可以为我所用。最初尝试我常用的由 沈垚
开发的 IP摄像头
,下图黄黑色图标,只能以 http page
方式使用;于是搜索下载安装了第二款国外开发的黑灰色图标的 IP摄像头
(下文称为 IP Webcam) 测试成功。xapk 安装器 下载地址。注意如果是 32bit 老安卓手机,要找到老版本 APK 的下载。
灰色摄像头软件的界面如下图所示功能强大,免费版功能就够用了。
https://www.dev47apps.com/
https://wolicheng.com/womic/
【图 】IP Webcam APP 界面,支持读取传感器数据,所以有无可能根据陀螺仪做视频后处理,或者 GoPro 那种自稳视频效果?
【图 】IP Webcam 网页管理界面,支持多种操作,以及开启 LED 闪光灯等功能,还可以设置熄屏和网页管理,美滋滋。
其他值得关注的软件还包括:
四、进阶知识
4.1 获取 USB-Camera 参数
# 安装所需工具包
sudo apt install v4l-utils usbtop
# 查看已连接的摄像头设备
v4l2-ctl --list-devices
# 如果没有识别到相应设备,请检查设备是否连接良好,以及 lsusb、dmesg 等命令查看是否被系统识别
# 查看对应摄像头的支持格式
v4l2-ctl -d [/dev/video1] --list-formats-ext
v4l2-ctl --device=/dev/video* --all
# 查看并设置摄像头支持的控制参数
v4l2-ctl -d /dev/video0 --list-ctrls
# v4l2-ctl -d /dev/video1 --set-ctrl=zoom_absolute=170
# 部分参数如果启用了自动控制,需要先关闭,比如白平衡(色温)
由上图我们就可以获得所需的配置:
- 摄像头设备地址为:
/dev/video0
,非 video1
或者 media0
- 此摄像头支持的最大分辨率和对应的帧率为
1600×1200
,亦即 1080P, 纵横比为 4:3。
- 用于 Fluidd/Mainsail 网页前端使用时,可以选择
800×600@25fps
以获取较好的显示兼容性和较低的系统占用,减少 CPU 发热,降低打印管理进程被干扰的可能。
- 编码方法为
YUYV
,在配置参数中添加 -y
选项。此外有的摄像头还支持 MJPG
等编码方式。
番外:
- 通过
lsusb
命令获取设备 Vendor ID
和 Device ID
可以查询到相关设备信息。
继而可以从以下网址查询相关信息:
-
图形化设置摄像头参数工具:v4l2ucp
-
获取更多 mjpg_streamer 选项,可以通过查看 octoprint文档 也可以查看帮助文件
udevadm info --attribute-walk /dev/bus/usb/[Bus]/[Device]
cd ~/mjpg_streamer
./mjpg_streamer -i "input_uvc.so --help"
./mjpg_streamer -o "output_http.so --help"
4.2 固定摄像头设备地址
在有多个 video 设备时,插拔摄像头后,其 /dev/video[num]
编号可能会发生改变,从而导致摄像头配置文件失效,这也是为什么很多人原来用的好好的,插拔之后不能用的原因。
此外有些设备自带 /dev/video0 设备,而 webcamd 会默认读取第一个 video 设备,应该访问 video1 却访问了 video0。
4.2.1 Method 1:创建 udev 规则(不推荐)
参考 Archwiki ,创建 udev 规则:
# /etc/udev/rules.d/83-webcam.rules
KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ATTRS{idVendor}=="1e4e", ATTRS{idProduct}=="0109", ATTR{index}=="0", SYMLINK+="video-cam1"
-
使用 sudo udevadm control --reload
命令可以强制重载生效 udev 规则,重新插拔 USB 摄像头即可看到新的 video-cam1
设备
-
同时修改 webcamd.txt
指定设备地址 -d /dev/video-cam1
,重启 webcamd 服务生效
-
注意设备名称必须以 video
开头,以被 v4l 使用
-
比较奇怪的是 ls -al /dev/video-cam1
可以看到链接到 video2(不显示参数那个),但是手动修改 webcamd.txt
又只能用 video1
才行
-
发现 mjpg_streamer 仅支持 video[0-9],不支持上述命名格式,webcamd.log 看到会自动忽略
-
如果制定的设备地址无效,会自动调用第一个 video 设备,从而有可能出错
-
更多信息可以参考 Webcam ordering is not persistent in Linux
4.2.2 Method 2:使用 v4l 设备地址
这个很像 Klipper 获取 serial 设备地址的方法,不会出现重新插拔后出错的问题,导致 ttyAMA0
等设备无法对应,klipper 读取的是 /dev/serial/by-id/*
,摄像头读取的是 /dev/v4l/by-id/*
,同样也面临一个问题,比如 CH340 设备的 id 相同,此时多个 MKS Gen L 等主板无法区分,此问题同样也出现在这里,解决方法是使用 /dev/v4l/by-path/*
,此路径与USB接口绑定。
4.3 为什么一个物理摄像头,有多个 video 设备?
参考这个回答:Multiple /dev/video for one physical device ,可知第一个用于传递图像,第二个用于传递 V4L MetaData
,包含时间戳以及图像捕捉参数等信息。
The second device provides metadata about the video data from the first device.
4.4 将摄像头图像输出到屏幕
参考 Viewing an mjpeg stream with mplayer
sudo apt install -y mplayer
mplayer -nolirc -vo fbdev2 -zoom -x 320 -y 240 test.mpg
mplayer -fps 4 -demuxer lavf http://localhost:8080/?action=stream
4.5 查看带宽、数据吞吐量
-
nethogs | 用于查看网络带宽吞吐量,优化调试使用。可以看到 jpeg 质量对带宽占用影响很大
sudo nethogs
# 使用 r 和 s 键来排序传入和传出的实时及累计数据量
-
usbtop | 用于查看 USB 接口数据吞吐量,也可以观察上位机一带多情况
# 列出所有可用的USB总线
usbtop --list
# 监控特定USB总线上的带宽流量
sudo usbtop --bus [usbmon1]