家里有好几个摄像头,几台小米,一些自己用 ESP32 搭的,还有多台树莓派 CSI 摄像头。之前一直在用一些云存储方案,但总觉得不放心:厂商绑定、依赖网络、费用还不少。索性自己动手,写了个 NVR 系统,就叫 MiBeeNvr。
为什么做 MiBeeNvr
说实话,我对现有的云存储方案一直不太满意。先说小米摄像头吧,默认只能通过米家 app 查看,录像存储要么靠 SD 卡(容量有限,还得经常插拔),要么就得上云。云存储每个月几十块,而且最关键的是隐私问题——你不知道厂商什么时候会把你的视频数据拿去训练 AI,或者干脆就把数据卖给了第三方。更别提厂商绑定了,想换平台都难。
ESP32 摄像头也是类似的情况。自己用 ESP32 搭了几个摄像头,录像是存 SD 卡,但查看和回放都不方便。需要一个统一的管理平台。
市面上其他开源方案我也试过:ZoneMinder 需要 LAMP 堆栈,安装部署比我整个项目还复杂;Shinobi 配置复杂得一塌糊涂;还有些小众项目基本上都没维护了。Frigate 虽然不错,但主要是针对 AI 检测,而且依赖 Docker,太重了。
说白了就是想要一个:
-
单文件二进制,下载就能跑
-
资源占用要少,树莓派都能跑
-
支持多种摄像头,特别是小米私有协议
-
Web 界面要清爽,不用折腾前端
-
自动清理旧录像,不会占满硬盘
折腾了一圈发现,现成方案都不太合适,那就自己写一个吧。
MiBeeNvr 是什么
MiBeeNvr 是一个用 Go 写的轻量级 NVR 系统,专门解决家用摄像头的本地存储问题。
整体架构
先看一张全局架构图,整个系统长这样:
接入方式
MiBeeNvr
协议桥接
摄像头端
miss
RTSP
HTTP
RTSP
RTSP
📷 小米摄像头
miss 协议
📷 ESP32 摄像头
HTTP JPEG
📷 树莓派 CSI
RTSP H.264
go2rtc
miss → RTSP
MediaMTX
CSI → RTSP
REST API
录制引擎
SQLite 存储
自动清理
HLS 直播
Web UI
WebDAV / FTP
Prometheus
三层结构:摄像头端负责采集,中间有协议桥接层处理私有协议,MiBeeNvr 核心做录制和存储,上面再挂各种访问方式。
录制流水线
视频流进入 MiBeeNvr 之后的处理流程:
存储
解码 & 封装
输入
RTSP 连接
gortsplib
HTTP JPEG
定时抓帧
RTP 解包
pion/rtp
MP4 封装
go-mp4
分段文件
30s / 10m
SQLite 元数据
磁盘
说白了就是:RTSP → RTP 解包 → MP4 封装 → 分段存储。前端用的是 Svelte 5,整个 SPA 直接编译成静态资源然后 embed 到 Go 二进制里,这样部署时只需要一个文件,连 Web 服务器都省了。
后端技术栈:
选 SQLite 是因为它单文件、纯 Go 实现、性能对家用场景完全够用、支持并发访问,最重要的是不需要额外装数据库。
设计理念
整个项目的设计哲学就是「简单粗暴」:
-
单个二进制文件,无任何外部依赖
-
支持交叉编译,AMD64/ARM64 都能跑
-
配置文件用 YAML,简单直观
-
内置 Web 界面,打开浏览器就能用
-
资源占用极少,树莓派 4 也能流畅运行
主要特性
我的实际部署
我这边是用一台 ARM64 小主机跑的,512MB 内存,2GB 存储。整个系统跑得很稳定,基本上是设置完就不管了。
接了 4 个摄像头,各有特点:
-
树莓派 CSI 摄像头 - 通过 MediaMTX 做 RTSP 桥接,把 CSI 接口的视频流转换成标准 RTSP。配置 rtsp_h264。
-
ESP32-S3 摄像头 - 自己搭的,跑 MJPEG 流,通过 HTTP 协议接入。配置 http_jpeg。
-
小米摄像头(阳台) - 通过 go2rtc 把小米私有协议转成 RTSP,2K 分辨率,配置 rtsp_h265。
-
小米摄像头(客厅) - 同上,1080P。
配置是 30 秒分段录制,保留 1 天。这个时间间隔是个权衡:太短了文件太多,太长了万一出事查起来不方便。开了 WebDAV(可读写)和 FTP,方便手机查看和备份。
Web 界面挺清爽的,摄像头管理、录像列表都有。
设置页面:
配置文件
完整的配置文件长这样,YAML 格式,一目了然:
yaml
|
server: listen: ":9090"storage: root_dir: "/mnt/data/nvr" segment_duration: "30s"cameras: - id: "rpi-csi-cam" name: "RPi CSI Camera" protocol: "rtsp_h264" url: "rtsp://10.0.1.100:8554/stream" enabled: true - id: "esp32-cam" name: "ESP32-S3 Camera" protocol: "http_jpeg" url: "http://10.0.1.101/capture" enabled: true - id: "xiaomi-balcony" name: "Xiaomi Camera" protocol: "rtsp_h265" url: "rtsp://10.0.1.102:8554/xiaomi_stream" enabled: truecleanup: retention_days: 30 disk_threshold_percent: 95auth: username: "admin" password_hash: "用 mibee-nvr hash-password 命令生成"webdav: enabled: true path_prefix: "/dav" read_write: trueftp: enabled: true port: 2121
|
小米摄像头接入
小米摄像头的协议问题是个大坑。它用自己私有的 “miss”(Mi Secure Streaming)协议,做了多层加密,不开放标准 RTSP 接口。也就是说,你就算知道摄像头的 IP,也没法用 VLC 直接拉流。
不过好在有 go2rtc 这个神器。整个接入链路是这样的:
MiBeeNvrgo2rtc小米摄像头小米云米家 AppMiBeeNvrgo2rtc小米摄像头小米云米家 App1. 账号认证 & 密钥交换2. 建立 P2P 连接3. 视频流转发loop[持续录制]4. 不再依赖米家 App用小米账号登录返回设备列表 & 加密密钥发起 miss 协议握手P2P 连接建立miss 加密视频流解密 & 转码标准 RTSP 流(H.265)MP4 分段录制Web UI / WebDAV / FTP 查看录像
整个过程不需要刷机、不需要拆摄像头、也不需要小米官方的云存储。go2rtc 帮你搞定了所有协议转换的事情。
go2rtc 部署
go2rtc 用 Docker 部署最省事:
bash
|
# 创建配置文件cat > go2rtc.yaml << EOF
streams:
xiaomi_balcony:
- xiaomi://your_account:cn@10.0.1.100?did=your_camera_did&model=isa.camera.hlc7
xiaomi_living_room:
- xiaomi://your_account:cn@10.0.1.101?did=your_camera_did&model=isa.camera.mj200
rtsp:
listen: ":8554"
EOF# 运行容器docker run -d --name go2rtc \
-p 8554:8554 \
-p 1984:1984 \
-v $(pwd)/go2rtc.yaml:/config.yaml \
alexxit/go2rtc
|
关键点:
-
xiaomi:// 协议需要小米账号和密码认证
-
did 是设备的唯一标识,model 是设备型号(在米家 app 里能找到)
-
go2rtc 会自动处理 P2P 连接和 miss 协议解密
-
最终在 8554 端口暴露标准的 RTSP 流,MiBeeNvr 当普通摄像头接入就行
然后在 MiBeeNvr 的配置里指向 go2rtc:
yaml
|
cameras: - id: "xiaomi-balcony" name: "小米摄像头" protocol: "rtsp_h265" url: "rtsp://localhost:8554/xiaomi_balcony" enabled: true
|
踩坑记录
小米摄像头的接入有不少坑:
-
首次联网:小米摄像头必须能连外网,因为需要和小米服务器做密钥交换。建立连接后,后续传输是局域网内的。
-
设备 ID 获取:每个摄像头的 did 都不同,需要用 go2rtc 的 WebUI(端口 1984)自动发现,或者在米家 app 里翻。
-
不是所有型号都支持:go2rtc 维护了一个兼容列表,买摄像头之前最好先查一下。
-
H.265 vs H.264:新款小米摄像头基本都是 H.265,MiBeeNvr 对两种编码都支持,但 H.265 省存储空间。
ESP32 摄像头项目
搞 MiBeeNvr 的时候,顺带做了几款 ESP32 摄像头固件。ESP32 摄像头这个坑踩了不少,但也挺有意思的。
三款固件定位不同:
NVR 统一管理
ESP32 摄像头固件
HTTP JPEG
HTTP JPEG / WebDAV
HTTP JPEG / FTP
MiBeeCam
ESP32-S3-A10
入门首选
AI_Thinker CAM
ESP32-CAM
性价比之王
MiBeeHomeCam
XIAO ESP32-S3
功能最强
MiBeeNvr
所有固件都设计成 MiBeeNvr 的上游采集端:摄像头负责采集视频,MiBeeNvr 负责统一存储和管理。
MiBeeCam — ESP32-S3-A10 方案
GitHub · MIT 许可证
这个是最成功的方案。ESP32-S3-A10 开发板 + OV2640 摄像头(8225N 模块),16MB Flash,ESP-IDF v5.4.3 开发。功能上 MJPEG 流、帧差法移动检测、Web 配置界面、Prometheus 指标都有。说实话有块 LCD 屏幕调试方便很多。
AI_Thinker ESP32-CAM — 经典方案
GitHub · MIT 许可证
入门级选择,AI_Thinker ESP32-CAM 开发板到处都能买到,十几块钱一块。4MB Flash + 4MB PSRAM,跑 MJPEG 流没问题。亮点是支持 SD 卡存储和 NAS 上传(WebDAV/HTTP),还做了自适应暗场景检测——晚上会自动切换红外模式。缺点是没有屏幕调试不方便,Flash 只有 4MB。
MiBeeHomeCam — XIAO ESP32-S3 Sense
GitHub · GPL v3.0
最高级的方案。XIAO ESP32-S3 Sense 板子小巧精致,带 OV2640/OV3660 双摄像头支持,8MB Octal PSRAM 充分利用。亮点是 AVI 分段录制(不是简单的截图,是真的视频录制)、FTP/WebDAV 双协议上传、看门狗防死机、芯片温度监控、批量文件管理。适合长期稳定运行的场景。
选择建议
系统服务配置
为了稳定运行,用 systemd 管理 MiBeeNvr:
ini
|
[Unit]Description=MiBee NVRAfter=network-online.targetWants=network-online.target[Service]Type=simpleUser=nvrExecStart=/mnt/data/nvr/bin/mibee-nvr -config /mnt/data/nvr/mibee-nvr.yamlWorkingDirectory=/mnt/data/nvrRestart=on-failureRestartSec=5# 安全加固NoNewPrivileges=trueProtectSystem=strictReadWritePaths=/mnt/data/nvrPrivateTmp=true[Install]WantedBy=multi-user.target
|
保存到 /etc/systemd/system/mibee-nvr.service,然后 systemctl enable --now mibee-nvr 就完事了。自动开机启动,挂了也会自动重启。
开源地址
MiBeeNvr 已经开源,欢迎 star 和贡献:
-
MiBeeNvr:https://gitee.com/Mi-Bee-Studio/MiBeeNvr (MIT 许可证)
-
MiBeeCam:https://github.com/Mi-Bee-Studio/luatos-esp32s3-a10-camera (MIT)
-
AI_Thinker ESP32-CAM:https://github.com/Mi-Bee-Studio/ai-thinker-esp32-cam (MIT)
-
MiBeeHomeCam:https://github.com/Mi-Bee-Studio/seeed-esp32s3-cam (GPL v3.0)
文档比较全,部署和配置都有详细说明。
写在最后
说实话,折腾这个项目主要是因为对现有方案都不满意。云存储太贵,开源方案太重,商业产品又太封闭。自己写一个刚好:轻量、免费、可控。
对了,项目取名 MiBeeNvr,“Mi” 代表我(Mickey),“Bee” 代表?保密,“Nvr” 自然是网络录像机了。简洁好记,又有点意思。
如果你也有家用摄像头的需求,或者对 NVR 系统有什么想法,欢迎交流。有问题可以在 GitHub 上提 issue。