尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

用树莓派4B + 腾讯云轻量服务器搭建一个网络监控摄像头 MVP:踩坑全记录

用树莓派4B + 腾讯云轻量服务器搭建一个网络监控摄像头 MVP:踩坑全记录 背景与目标手头有一台树莓派 4B 和官方 CSI 摄像头imx219也就是 Camera Module 2再加一台腾讯云轻量应用服务器目标很简单让树莓派把摄像头画面推流出去能在手机/浏览器上实时看到。思路上遵循职责分离树莓派只负责采集 硬件编码 推流不做存储和分发云端服务器负责接收流 转发可选录制播放端走标准协议拉流不做定制协议。整体架构[树莓派4B 摄像头] --RTMP推流-- [腾讯云轻量服务器: SRS流媒体服务] | HLS/FLV/WebRTC拉流 | [浏览器/VLC播放]MVP 最小可行步骤定为四步树莓派推流 → 服务器收流验证 → 网页播放器接入 → 开机自启。本文记录的是前三步里踩到的坑以及每个坑的排查方法方便自己以后复盘也希望能帮到遇到类似问题的人。坑一ffmpeg 直接读/dev/video0报VIDIOC_STREAMON: Invalid argument现象用最直觉的写法ffmpeg -f v4l2 -i /dev/video0 ...推流直接报错设备存在但采集失败。原因这是树莓派官方 CSI 摄像头在新系统Bookworm/Trixie上的一个关键坑——/dev/video0在这类摄像头上往往不是可以直接喂给 ffmpeg 的成品视频流而是unicam驱动暴露的原始 Bayer 数据节点必须经过 ISP也就是 libcamera 那一套处理成 YUV/H264 才能用。而 USB 摄像头则完全不同通常只是采集参数格式/分辨率/帧率没跟v4l2-ctl --list-formats-ext里列出的对上。排查方法先用v4l2-ctl --list-devices和v4l2-ctl -d /dev/video0 --list-formats-ext确认设备到底支持什么格式用来区分是参数没对上USB 摄像头常见还是这个节点根本不是给 ffmpeg 用的CSI 官方摄像头。解决方案CSI 摄像头别走 ffmpeg 直接读 v4l2 这条路改用rpicam-vid新版本叫这个名字旧版本是libcamera-vid二者等价走硬件编码管道rpicam-vid -t 0 --width 1280 --height 720 --framerate 25 \ --codec h264 --inline --listen -o - | \ ffmpeg -re -f h264 -i - -c:v copy -f flv rtmp://服务器IP/live/stream1关键参数--codec h264让摄像头硬件直接吐 H.264避免树莓派 CPU 软编码-c:v copyffmpeg 只做 H264 裸流到 FLV 容器的封装转发不重新编码--inline每个关键帧前插入 SPS/PPS这是 RTMP 推流的硬性要求不加的话播放端大概率花屏或解不出画面。心得遇到设备明明在但采集失败这种报错第一反应不该是调参数而是先搞清楚这个视频节点的驱动层级——它到底是成品流还是原始数据节点。这条经验后来在排查延迟问题时也用上了理解链路里每一层到底在干什么比死磕报错信息本身更有效。坑二服务器上git cloneSRS 源码卡死不动现象在腾讯云轻量服务器上执行git clone -b develop https://github.com/ossrs/srs.git准备源码编译 SRS命令直接卡住不动。原因国内服务器访问 GitHub 是老问题了clone 经常卡住或者极慢不代表命令本身写错了。解决方案与其纠结网络代理不如换路子——直接用 Docker 跑现成镜像完全跳过源码编译docker run -d --name srs --restart always \ -p 1935:1935 -p 8080:8080 -p 1985:1985 -p 8000:8000/udp \ ossrs/srs:5一步到位省去了树莓派/服务器编译动辄几十分钟的等待版本也更稳定。备选方案是换 Gitee 镜像git clone -b develop https://gitee.com/ossrs/srs.git继续走源码编译但优先级明显低于 Docker。心得遇到国内网络访问境外资源慢/卡这类问题优先考虑有没有现成的容器镜像或国内镜像源可以绕过去而不是死磕当前这条路径的网络问题——这类问题往往不值得花时间深挖根因。坑三VLC 播放 RTMP 流延迟高达 10 秒以上这是本次排查耗时最长、也最有价值的一段这个坑分了好几轮排查记录一下完整的推理链条因为每一轮的结论都被下一轮的实测数据推翻这个过程本身很有参考价值。第一轮猜测VLC 播放器缓冲设置的问题现象vlc rtmp://IP/live/stream1播放延迟大。假设VLC 对 RTMP 默认的network-caching设置比较保守通常有 3-10 秒延迟怀疑只是播放端缓冲问题。尝试改小缓冲区vlc --network-caching300 rtmp://...。Mac 上的额外小坑终端直接执行vlc命令报没有找到——因为 Mac 上 VLC 的命令行工具默认没加进 PATH得用完整路径/Applications/VLC.app/Contents/MacOS/VLC --network-caching300 rtmp://IP/live/stream1或者干脆设个别名一劳永逸echo alias vlc/Applications/VLC.app/Contents/MacOS/VLC ~/.zshrc source ~/.zshrc结果改完缓冲后延迟依然固定在 10 秒左右几乎没有改善。第一轮假设被推翻。第二轮猜测GOP 设置 SRS 服务端队列缓存关键诊断点先要分清延迟是固定不变还是持续增长——这两种现象对应完全不同的根因。如果是持续增长越看延迟越大典型的 RTMP 走 TCP 的积压问题——只要瞬时网络吞吐比推流码率低一点点数据就会在某层缓冲区里越堆越多且永远追不上。根源通常在服务器 SRS 的队列设置。如果是固定不变说明是链路上几层一次性缓冲叠加的固定开销跟积压无关。实测下来是固定 10 秒左右不再增长于是把三处可能的一次性缓冲都压了一遍树莓派端缩短关键帧间隔 去掉管道/ffmpeg 层的缓冲stdbuf -o0 rpicam-vid -t 0 --width 1280 --height 720 --framerate 25 --intra 25 \ --codec h264 --inline --listen -o - | \ stdbuf -i0 -o0 ffmpeg -fflags nobuffer -flags low_delay \ -analyzeduration 0 -probesize 32 \ -f h264 -i - -c:v copy -f flv rtmp://IP/live/stream1--intra 25GOP 从默认的几秒一个关键帧改成 1 秒一个配合 25fps播放端不用等太久就能拿到完整关键帧stdbuf -o0/stdbuf -i0 -o0强制管道不做块缓冲-fflags nobuffer -flags low_delay -analyzeduration 0 -probesize 32让 ffmpeg 不攒数据分析格式直接尽快转发。服务器端SRS 配置里关掉几个会导致缓存堆积的开关vhost __defaultVhost__ { play { gop_cache off; queue_length 10; mw_latency 100; } publish { mr off; } tcp_nodelay on; }改完docker restart srs生效。这里踩了一个配置生效的坑改完配置容器没崩溃、日志也正常不代表新配置真的被加载了。容易忽略的一点是——如果配置文件是在宿主机改的但容器没有正确挂载这个文件没配 volumedocker restart只会用镜像构建时打包的旧配置改了等于白改。验证方法docker exec srs cat /usr/local/srs/conf/srs.conf | grep -A 5 __defaultVhost__确认容器内部实际生效的配置里确实包含自己改的那几行。结果确认配置生效后重新测试RTMP 延迟依然是 10 秒几乎没有改善。同时测了 http-flv理论上应该比 RTMP 更低延迟结果反而比 RTMP 还慢。第二轮假设也被推翻——这个反常结果非常关键两种协议、不同的服务端 play 配置表现却一样差说明瓶颈根本不在播放端缓冲或服务端队列策略这两层而是在更上游、两者共用的环节推流链路本身。第三轮猜测排查中树莓派上行带宽不足推理逻辑既然 RTMP 和 http-flv 这两种下游协议表现一致地差说明问题出在它们共同的上游——也就是从树莓派到服务器的推流这一段。排查方法直接看 ffmpeg 推流时输出的speed指标frame 250 fps 25 q-1.0 sizexxxxkB time00:00:10.00 bitratexxxxkbits/s speed0.98xspeed稳定在 1.0x 附近发送速度和采集速度匹配瓶颈不在带宽speed明显小于 1.0x说明编码产出速度 实际发送速度数据在某处内核 socket 缓冲区/网卡持续积压——这正是固定延迟或缓慢增长的延迟的直接成因。实测中 ffmpeg 输出的这一行整行是N/AframeN/A timeN/A bitrateN/A speedN/A这个现象本身很有信息量如果是带宽不够speed应该是一个变化中但小于 1 的数字而整行N/A更像是推流连接层面直接卡住了连接建立慢、丢包、或中间有类似 NAT/防火墙的东西在拖延排除了渐进式带宽积压这个解释。下一步验证方向是测树莓派到服务器的网络质量ping、traceroute/mtr以及树莓派实际上行速度来判断卡住的具体是网络哪一层——这部分排查在记录时间点还未完成。阶段性心得多协议交叉验证是快速定位瓶颈层的好方法。如果只测了 RTMP 延迟高就一路怀疑 RTMP 协议或播放器很容易走偏同时测 http-flv 之后发现两者表现一致直接把嫌疑范围从下游播放/服务端策略收窄到上游推流链路。改配置后一定要验证配置真的被加载了尤其是容器化部署下宿主机改文件不等于容器读到新文件。一个看似缓慢的指标比如延迟需要先区分固定还是增长再对症下药这两者对应完全不同的技术根因一次性缓冲叠加 vs. 持续积压排查方向完全不同。ffmpeg 的speed和其他运行时指标是免费的诊断信息N/A本身也是一种信号——异常的没有数据往往比异常的数字更值得警惕。坑四插曲改完 SRS 配置后 TAT 命令通道突然断开一度以为服务器炸了现象改完 SRS 配置执行docker restart srs后腾讯云的 TAT自动化助手命令通道断开没法继续用它执行命令确认配置——但服务器实例本身在控制台查询是正常的。容易踩的误区看到命令通道断了很容易第一反应就是服务器出问题了是不是刚才的操作把系统搞坏了然后开始紧张地排查系统层面的故障。实际情况TAT agent 本身是一个独立于 SSH/Docker 的进程它断开通常只是自己卡住或者服务器瞬时负载高导致没响应编译、Docker 操作时 CPU/内存吃紧时常见跟目标服务SRS 容器是否健康没有必然联系。解决方法不要死等 TAT 恢复直接换一条独立通道——网页控制台的 WebShell/VNC 直连服务器走的是完全不同的链路docker ps docker logs srs --tail 50 systemctl status tat_agent一确认 SRS 容器一直稳定运行、日志正常之前服务器炸了的担心就直接排除了。心得排查工具本身出故障不代表被排查的目标系统出故障——这两者很容易被混为一谈尤其是紧张的时候。保留至少一条独立于主要操作通道的备用访问路径比如网页控制台之于 SSH/agent能在关键时刻快速把工具坏了和系统坏了这两种可能性分开避免在错误的方向上浪费排查时间。目前的进展与待续✅ 树莓派硬件编码链路rpicam-vid验证通过能正常生成本地 H264 文件✅ 服务器端用 Docker 一键跑通 SRS避免了源码编译踩坑✅ 推流到 SRS、VLC 拉流能看到画面链路整体打通 进行中定位固定 10 秒延迟的真实根因已通过多协议交叉测试把范围收窄到推流链路本身下一步是网络质量测试ping/traceroute/mtr 树莓派实际上行带宽测试⏭️ 后续计划确认延迟根因并解决后接入flv.js网页播放器比 VLC 更适合作为最终低延迟播放方案、加开机自启脚本、视情况加运动检测触发录制和推流鉴权。
返回列表