ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

树莓派图传监控系统实战:从硬件选型到HLS部署与优化

树莓派图传监控系统实战:从硬件选型到HLS部署与优化 简介基于树莓派的图传监控系统项目包面向物联网爱好者与需要低成本远程监控方案的DIY用户。内容围绕摄像头采集、动态监控软件配置、网络流媒体传输及远程访问展开涵盖硬件准备、系统设置、安全加固与功能扩展可应用于家庭安防、农场监控、仓库管理等场景。压缩包共9个文件其中2个Python脚本负责智能检测与联动控制2张JPG与1张PNG示意图展示硬件接线和操作界面另有YAML配置、Git忽略规则及License协议整体仅462KB轻量紧凑。已有158人学习特别适合初次接触树莓派视频监控的读者从零上手。通过该资源可掌握实时视频流发布、RTSP播放器访问、防火墙限制以及邮件报警等扩展思路并学习motion服务的完整配置方法同时获得可复用的代码与配置参考有效缩短项目搭建周期减少常见踩坑。1. 树莓派图传监控系统的工程边界与选型前提“基于树莓派的图传监控系统.zip”这个标题里最容易被忽略的是“系统”两个字。它不是一条命令把摄像头画面推到网页而是一套采集、编码、传输、播放、录像、告警完整打通的方案。很多人第一次做图传把画面点出来就宣布完成实际运行一周后会碰到延迟漂移、切片写满 SD 卡、WiFi 抖动导致花屏、断电后服务不回来四个问题。这套方案围绕树莓派 4B/5 和 CSI 摄像头展开场景包括临时看护、小空间安防、机器人第一视角回传适合想从“能出图”走到“能交付”的开发者。下面按协议选型、最小图传链路、监控功能增强、性能排查、进阶部署的顺序展开。2. 按图传协议选硬件摄像头、传输链路和软件栈2.1 CSI 摄像头和 USB 摄像头的稳定性差异树莓派接摄像头有两条路。CSI 接口的官方摄像头模块OV5647、IMX219、IMX477走专用数据排线传输不占 USB 总线带宽供电也由排线直接供给长时间运行比 USB 摄像头稳定得多。树莓派 4B 的 CSI 排线是 15 针树莓派 5 改成了 22 针排线不通用插反或没插到底时libcamera-hello会直接报 “no camera available”不会烧板子但很容易把人误导成软件问题。USB UVC 摄像头插上就出现/dev/video0驱动兼容性最好适合先验证后端逻辑。它的弱点是树莓派 USB 口供电有限挂多个 UVC 设备或使用长线时可能随机掉帧、断流接一个带独立供电的 USB HUB 能解决大部分问题。在长期监控场景里CSI 方案默认更稳UVC 更适合多路临时接入。对比项官方 CSI 摄像头OV5647IMX219/IMX477 CSIUSB UVC 摄像头典型分辨率1080p301080p30 / 4K30依型号而定带宽占用专用 CSI专用 CSI占用 USB 总线供电方式排线供电排线供电USB 口供电长线易掉线长时间稳定性高高中受供电和线材影响适用阶段长期监控高画质/宽动态快速验证、多路测试2.2 图传协议选型MJPEG、RTSP 与 HLS图传监控最常见的错误是先用 MJPEG 出了画面然后直接拿去公网用卡顿了再回头改协议。传输协议应该和图传目标一起定是局域网内看还是要跨网络看是看实时画面还是要录像回放MJPEG每一帧都是独立 JPEG画面延迟低一般低于 200ms浏览器img标签直接可看但带宽开销极大。720p30 的 MJPEG 码率常超过 12Mbps适合同一局域网调试不适合跨网。RTSP标准流媒体协议端到端延迟能压到 200ms 以内是机器人图传的首选但浏览器不原生支持需要 VLC、后端转 WebRTC或通过流媒体网关再分发。HLS视频切成 2-6 秒小分片播放器自动拼接。延迟较高但兼容性最好能直接走常规 HTTP 环境也便于录像归档与回看是树莓派做家庭监控的主流选择。协议端到端延迟浏览器兼容适合场景树莓派 CPU 开销MJPEG200msimg 标签直接放局域网调试低但带宽占用高RTSP100-300ms需插件或转接小车、低延迟图传低HLS2-6shls.js 等库公网监控、回放低2.3 软件栈选择libcamera 与 FFmpeg 的分工官方 Raspberry Pi OS 从 Buster 版本起相机接口统一走 libcamera 框架旧的 raspivid 已经移除。现在最省事的组合是libcamera-vid负责采集和硬件 H.264 编码FFmpeg 负责 HLS 切片或封装需要低延迟时用 GStreamer 推 RTSP需要画面分析时再把视频流接到 OpenCV。关键判断不要把 OpenCV 插到主链路的每一帧上。树莓派 4B 的 CPU 在 720p 下跑背景减除大约能到 10-15 FPS勉强能看如果再叠 HLS 切片CPU 会挤爆视频开始卡。合理做法是主链路只做编码传输分析用独立进程抽帧处理而不是全帧处理。3. 用 libcamera FFmpeg 把树莓派图传流跑起来3.1 系统准备与摄像头初始化树莓派 4B/5 建议用 Raspberry Pi OS Lite64-bit做底座不装桌面把资源全部留给视频链路。烧录并进入系统后执行sudo apt update sudo apt install -y libcamera-apps ffmpeg sudo raspi-config在raspi-config的 Interface Options 里打开 Camera树莓派 5 通常不需要手动配置 overlay4B 如果libcamera-hello探测不到摄像头在/boot/firmware/config.txt末尾加dtoverlayov5647使用官方摄像头时或dtoverlayimx219重启后再验证。验证命令libcamera-hello --list-cameras libcamera-hello -t 0第一条命令显示摄像头列表第二条会弹窗预览。SSH 无桌面环境时-t 0没有预览效果但终端会持续输出帧率统计看到 stable fps 输出说明 CSI 线和摄像头都正常。3.2 最小 HLS 图传命令常用做法是把 libcamera-vid 的 H.264 码流直接送给 FFmpeg由 FFmpeg 负责 HLS 切片命令如下mkdir -p /var/www/html/live libcamera-vid -t 0 --width 1280 --height 720 --framerate 15 \ --codec h264 --profile baseline --intra 30 \ -o - | ffmpeg -fflags nobuffer -i - \ -c copy -f hls \ -hls_time 2 -hls_list_size 5 -hls_flags delete_segments \ /var/www/html/live/stream.m3u8这条管道里libcamera-vid 不落盘直接输出到 stdoutFFmpeg 从 stdin 读取。--codec h264走树莓派 GPU 硬编CPU 占用很低--profile baseline保证老设备和 hls.js 都能解码--intra 30让关键帧间隔为 2 秒少了它 HLS 播放器可能黑屏或花屏。FFmpeg 侧-c copy不重新编码-hls_time 2每 2 秒切一个文件-hls_list_size 5只保留最近 5 个分片-hls_flags delete_segments自动删除旧分片防止 SD 卡被写满。如果开始播放时需要等好几秒把-hls_time降到 1。3.3 前端播放页面HLS 在浏览器不能直接打开 m3u8需要 hls.js。放一个最小页面video idcam controls autoplay muted/video script srchttps://cdn.jsdelivr.net/npm/hls.js1/dist/hls.min.js/script script if (Hls.isSupported()) { const hls new Hls({ liveSyncDurationCount: 2 }); hls.loadSource(http://树莓派IP/live/stream.m3u8); hls.attachMedia(document.getElementById(cam)); } /scriptliveSyncDurationCount: 2表示播放器试图保持在直播边缘之后 2 个切片处数值越小延迟越低但网络抖动时更容易卡局域网建议取 1-2公网取 3-4。muted属性避免浏览器自动播放策略拦截。3.4 需要更低延迟时的 GStreamer RTSP 管线如果需要遥控小车或手柄视角HLS 的两秒延迟不够用可以改用 GStreamer 管道gst-launch-1.0 libcamerasrc ! \ video/x-raw,width1280,height720,framerate15/1 ! \ openh264enc bitrate2000000 ! h264parse ! \ rtph264pay config-interval1 pt96 ! \ udpsink host192.168.1.100 port5600libcamerasrc是 libcamera 的 GStreamer 插件openh264enc是软件编码器树莓派上无需额外授权bitrate控制码率config-interval1让编码参数随 RTP 包下发接收端才能快速解码。UDP 目标host改成接收端 IP接收端用 VLC 打开udp://:5600即可预览。这条管线没有硬件编码器4B 在 720p 下 CPU 占用会到 30% 左右但延迟比 HLS 低一个量级。4. 给图传监控加移动检测、告警和录像4.1 移动检测读流、抽帧、背景减除移动检测是“监控系统”四个字的核心附加值。OpenCV 的背景减除MOG2在树莓派上是最常见的实现误报调节比模型选择更重要。import cv2 import time cap cv2.VideoCapture(http://127.0.0.1/live/stream.m3u8) fgbg cv2.createBackgroundSubtractorMOG2(history500, varThreshold16, detectShadowsFalse) kernel cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) n 0 while True: ok, frame cap.read() if not ok: time.sleep(1) continue n 1 if n % 2 ! 0: # 隔帧检测省 CPU continue small cv2.resize(frame, (frame.shape[1] // 2, frame.shape[0] // 2)) mask fgbg.apply(small) mask cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) cnts, _ cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for c in cnts: area cv2.contourArea(c) if area 800: continue x, y, w, h cv2.boundingRect(c) cv2.rectangle(small, (x, y), (x w, y h), (0, 255, 0), 2) cv2.imwrite(f/home/pi/monitor/snap_{int(time.time())}.jpg, small)代码逻辑是每两帧抽一帧把画面缩放一半后再做背景减除检测到目标后立即保存 JPEG。history500保留背景建模 500 帧光照缓慢变化时不会误报varThreshold16是被判定为前景的像素差值门槛太小会把树叶影子都当移动目标太大则漏掉慢速走动的人MORPH_OPEN开运算去掉孤立噪点。area 800是在缩放后的画面上计算的原始 720p 画面相当于 3200 像素能滤掉昆虫和光线抖动。4.2 告警Webhook 推送到群机器人检测到移动后最简单可靠的通知是把消息推到群机器人。企业微信群机器人只需要一个 keyPOST JSON 即可import requests import json import time def send_alert(msg): webhook https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key替换为实际key payload {msgtype: text, text: {content: msg}} requests.post(webhook, datajson.dumps(payload), headers{Content-Type: application/json}, timeout5) send_alert(监控区域检测到移动: time.strftime(%Y-%m-%d %H:%M:%S))参数边界务必加告警冷却。检测到一次移动后 60 秒内不再发送同类型告警否则一阵风吹过手机会收到十几条通知。冷却逻辑用一个全局时间戳记录上次推送时间即可。钉钉和飞书的 Webhook 结构类似改一下 JSON 字段就能复用。4.3 录像与存储规划图传监控要不要一直录像取决于要看“事后证据”还是“实时画面”。全程录像的存储成本必须提前算分辨率/帧率码率每小时占用32GB 可存720p151.5 Mbps约 0.7 GB约 45 小时720p302.5 Mbps约 1.1 GB约 29 小时1080p304 Mbps约 1.8 GB约 17 小时关键点长时间连续写入 TF 卡会明显加速磨损写入放大加上高温掉电后有可能整个分区损坏实践上把录制目录放到外置 SSD 或 U 盘TF 卡只跑系统。分段录像用-f segment比单个大文件更好恢复ffmpeg -i http://127.0.0.1/live/stream.m3u8 \ -c copy -f segment -segment_time 300 \ -strftime 1 /mnt/usb/rec/%Y%m%d_%H%M%S.mp4-segment_time 300每 5 分钟一个文件文件名取自开始录像时间。检测进程保存的关键帧图片也可以一并写到同一块外置存储。4.4 开机自启与崩溃恢复图传监控需要长时间无人值守进程退出后必须自动拉起来。常见做法是写成 systemd 服务[Unit] DescriptionRPi Video Monitor Afternetwork.target [Service] Userpi ExecStart/home/pi/monitor/run.sh Restartalways RestartSec5 EnvironmentPYTHONUNBUFFERED1 [Install] WantedBymulti-user.target把上面内容存为/etc/systemd/system/rpi-monitor.service然后sudo systemctl daemon-reload sudo systemctl enable --now rpi-monitorRestartalways让服务在进程正常退出或异常崩溃后都重启RestartSec5防止系统负载高时疯狂重启如果流服务和告警服务有依赖顺序在两个 service 之间补After和Requires。用journalctl -u rpi-monitor -f看实时日志。5. 图传延迟、卡顿与掉线的排查顺序5.1 延迟漂移先量化再追责“画面卡”和“延迟高”经常被当成同一个问题排查顺序完全不同。延迟高是链路中增加缓存导致的卡顿则多半是吞吐或丢包。把端到端延迟拆开看环节常见耗时主要变量采集与自动曝光30-80ms曝光时间、白平衡H.264 硬编码5-20ms分辨率、帧率网络传输1-5ms局域网WiFi 信号、重传HLS 切片/播放缓冲2-6shls_time、list_size、播放器采集端的自动曝光和自动白平衡在暗光下会拖慢帧率如果监控点光照稳定用--awb indoor --metering centre固定参数能省掉一大部分延迟波动。5.2 HLS 延迟收紧组合libcamera-vid -t 0 --width 1280 --height 720 --framerate 15 \ --codec h264 --profile baseline --intra 15 --awb indoor \ -o - | ffmpeg -fflags nobuffer -i - -c copy -f hls \ -hls_time 1 -hls_list_size 3 \ -hls_flags delete_segmentsindependent_segments \ /var/www/html/live/stream.m3u8--intra 15把关键帧间隔压到 1 秒-hls_time 1每 1 秒切片independent_segments让播放器不需要等所有分片都存在就能开始播放。前端把liveSyncDurationCount设为 1。这套组合在局域网稳定网络下可压到 1.5 秒左右再往下就建议换 RTSP 或 WebRTC。5.3 WiFi 干扰导致的马赛克与首画过慢树莓派用 2.4GHz 时微波炉、蓝牙和邻居 WiFi 都会造成周期性丢包HLS 对丢包不敏感但 TCP 重传会把延迟拉高。优先用 5GHz固定信道关闭网卡省电模式。码率也可以主动降--bitrate 1500000若用 RTSP over UDP把传输改成 TCPFFmpeg 加-rtsp_transport tcp虽然理论上延迟略高但能避免花屏重影。5.4 供电和过热掉线的另一个隐藏原因图传编码是树莓派少数能让 CPU 和 GPU 同时高负载的场景。供电不足时系统不会立刻关机而是先降频、随机卡死、USB 摄像头掉线。检查命令vcgencmd get_throttled # 低 4 位1欠压2限频4当前节流 vcgencmd measure_tempget_throttled返回十六进制状态低 4 位出现 1、2、4 就说明当前正处在欠压或频率受限状态0x50000 是历史标记表示曾经发生过欠压和限频需要换电源。优先换 5V/3A 以上电源和短粗 Type-C 线树莓派 5 建议用官方 27W 电源。散热以被动散热片加小风扇为主避免风扇震动影响摄像头画面。6. 多路画面与断线自愈几个直接能抄的配置6.1 多路图传CSI 与 USB 混接时的资源规划树莓派 4B 的 CSI 接口只有一个要接多路摄像头可以混用 USB UVC。多路时资源分配要先算每一路 720p15 H.264 硬编约占 10% CPU一路 OpenCV 抽帧检测约占 20% CPU4B 最多带 2-3 路 720p超过就降帧率。每路图传单独一个 systemd 服务ExecStart 里用不同端口避免一个进程崩溃拖垮全部画面。6.2 断线自愈systemd 之外的探针重启systemd 只能根据进程退出重启进程僵死时它无能为力。一个简单探针脚本放 cron 里每 2 分钟检查一次#!/bin/bash if ! pgrep -f libcamera-vid /dev/null; then systemctl restart rpi-monitor echo $(date): restart /home/pi/monitor/watchdog.log fi注意探针脚本本身要能够被 cron 调用且pgrep -f的模式不要匹配到探针自己。如果使用 GStreamer 推流把libcamera-vid换成gst-launch-1.0即可。6.3 查看端自动重连与时间基准hls.js 在 WiFi 切换、网络闪断后不会自动恢复需要监听错误事件做重试hls.on(Hls.Events.ERROR, function (event, data) { if (data.fatal) { hls.startLoad(); } });最后一个小但影响很大的技巧树莓派默认没有 RTC断电后再开机时间可能回退导致录像文件名乱序。装好系统后先执行sudo timedatectl set-ntp true并把这条写进首次启动脚本否则所有按时间命名的切片和截图都会在下次开机后排在错误的位置。本文还有配套的精品资源点击获取
返回列表