MiBeeNvr v0.3.0: 小米摄像头内置支持与架构演进之路
v0.2.0 发布之后又折腾了不少,这次 v0.3.0 带来了几个重量级更新:小米摄像头内置支持、归档录像功能,以及一大波安全加固。说实话,从外部依赖到内置实现的架构演进过程,比我想象的要曲折得多。
上一篇介绍了 v0.2.0 的 15 个新功能(v0.2.0 更新),没看过第一篇的可以先看 MiBeeNvr 介绍。这次 v0.3.0 主要聚焦在小米摄像头的深度集成上,完整更新列表见 GitHub Release Notes。
架构演变:从外部依赖到内置实现的曲折之路
小米摄像头支持的开发过程,是我做过最有趣的架构实验之一。整个过程经历了三个截然不同的阶段,每个阶段都有其独特的教训。
第一阶段:go2rtc 外部依赖 (v0.1.0 时代)
早期的 MiBeeNvr 完全依赖 go2rtc 来处理小米摄像头的协议转换:
graph TB
subgraph "小米摄像头"
A[Camera]
end
subgraph "外部容器"
B[go2rtc]
end
subgraph "MiBeeNvr"
C[RTSP 客户端]
D[HLS 编码]
E[存储管理]
end
A -->|"miss 协议"| B
B -->|"RTSP"| C
C -->|HLS| D
D -->|存储| E
classDef hardware fill:#e3f2fd,stroke:#1976d2
classDef process fill:#e8f5e9,stroke:#4caf50
classDef storage fill:#fff3e0,stroke:#ff9800
classDef network fill:#f3e5f5,stroke:#9c27b0
class A hardware
class B process
class C,D,E storage说实话,这个方案一开始看起来很优雅:用一个现成的 Docker 容器解决协议转换问题,主程序专心做 NVR 功能。但很快问题就来了:
- CS2 P2P 连接不稳定:小米摄像头的 P2P 连接大约 20 分钟就会超时卡死
- 调试困难:go2rtc 是独立项目,出了问题很难定位
- 运维复杂:需要管理两个 Docker 容器,端口冲突、资源争抢问题不断
归根结底,把核心功能依赖到外部容器上,本身就是个设计上的失误。
第二阶段:插件架构实验 (v0.2.0 到 v0.3.0 之间)
吸取教训之后,我决定把 go2rtc 的 Xiaomi 代码移植到 MiBeeNvr 里,做成插件系统。当时的想法很好:
- 通过 Go 接口注册实现协议解耦
- 使用
init()基础的插件机制 - 甚至实验了 gRPC 进程隔离
听起来很美好对吧?让架构变得可扩展,牺牲一点性能换来开发便利性。结果现实给了我一记响亮的耳光:
flowchart LR
subgraph "小米摄像头"
A[Camera]
end
subgraph "插件进程"
B[Plugin Process]
C[gRPC 通信]
end
subgraph "MiBeeNvr 主程序"
D[主 NVR 引擎]
E[HLS 编码]
F[存储管理]
end
A -->|"miss 协议"| B
B -->|gRPC| C
C -->|处理| D
D -->|HLS| E
E -->|存储| F
classDef hardware fill:#e3f2fd,stroke:#1976d2
classDef process fill:#e8f5e9,stroke:#4caf50
classDef storage fill:#fff3e0,stroke:#ff9800
classDef network fill:#f3e5f5,stroke:#9c27b0
class A hardware
class B,C process
class D,E,F storage实际使用中发现的问题:
- 架构过度复杂:实时预览多了好几层中间环节,性能下降明显
- 资源消耗增加:额外的进程和通信开销
- 新人门槛高:代码库变得难以理解,一个简单的功能需要跨进程通信
折腾了一圈才发现,有时候最简单的方案反而是最好的。
第三阶段:回归简洁 (v0.3.0)
最终在 v0.3.0 中,我彻底移除了插件系统,将 Xiaomi 代码迁移到内置的 internal/xiaomi/ 包中:
graph TB
subgraph "小米摄像头"
A[Camera]
end
subgraph "MiBeeNvr 核心"
B[internal/xiaomi/ 包]
C[核心 NVR 引擎]
D[HLS 编码]
E[存储管理]
end
A -->|"miss 协议"| B
B -->|直接处理| C
C -->|HLS| D
D -->|存储| E
classDef hardware fill:#e3f2fd,stroke:#1976d2
classDef process fill:#e8f5e9,stroke:#4caf50
classDef storage fill:#fff3e0,stroke:#ff9800
class A hardware
class B,C,D,E process正如 Release Notes 中所说:
“Plugin System Removed — Xiaomi migrated from gRPC plugin to built-in internal/xiaomi/ package”
“Full Xiaomi IP camera integration — no plugins, no external dependencies”
现在的架构就是一个单二进制文件,无需外部进程,无需 Docker 依赖。有时候,对于这个阶段的项目,简洁性比扩展性更重要。
小米摄像头功能详解
内置 CS2 P2P 协议
现在 MiBeeNvr 直接支持小米摄像头的 CS2 P2P 协议,不再需要 go2rtc 这个中间人。
云端认证流程
完整的认证流程包括:
- 使用小米账号登录
- 获取 passToken
- 自动发现设备列表
- 建立直连
支持的设备类型包括:
.camera.- 普通摄像头.cateye.- 猫眼摄像头.feeder.- 喂养器(HLC8 型号)
配置示例
在 mibeenvr.yaml 中添加小米摄像头配置:
| |
Web 界面
Web 界面提供了完整的账号管理功能:
- 小米账号登录页面
- 自动发现摄像头
- 一键添加功能
说实话,这个认证流程比我想象的要复杂,但最终实现出来的用户体验还算不错。
实际界面是这样的:

归档录像:独特的摄像机管理方式
归档录像功能是这次 v0.3.0 的一大亮点。这个需求的场景很简单:当你需要移除一个摄像头(坏了、搬家、升级)但又想保留历史录像时,传统 NVR 系统通常的做法是直接删除所有相关数据。
MiBeeNvr 提供了更人性化的解决方案:
flowchart LR
A[活跃摄像头] --> B[停止录制]
B --> C[合并片段]
C --> D[标记归档]
D --> E[从配置移除]
E --> F[录像保留]
classDef process fill:#e8f5e9,stroke:#4caf50
classDef storage fill:#fff3e0,stroke:#ff9800
classDef network fill:#f3e5f5,stroke:#9c27b0
class A,B,C,E process
class D,F storage三态摄像头管理
摄像头现在有三种状态:
- Active - 正在录制
- Disabled - 已暂停
- Archived - 只读(历史记录)
归档流程
归档操作很直观:
- 在摄像头列表中点击"归档"
- 弹出确认对话框
- 输入 “DELETE” 确认
- 系统自动合并片段并标记归档
- 摄像头从实时列表移除,但录像完整保留
归档后管理
归档后的录像支持:
- 播放历史录像
- 下载单个录像文件
- 删除指定录像
- 设置归档组保留期限
实际效果如下:

其他 v0.3.0 亮点
安全加固
这次 v0.3.0 包含了 15+ 个安全修复:
- 路径验证加强
- 认证机制硬化
- 速率限制优化
- 安全头设置
- SQL 注入防护
前端全面升级
前端完成了 Svelte 5 的完整迁移:
- 运行模式 (runes) 语法
- 移除所有遗留语法
- 国际化 500+ 个键值
HLS 改进
HLS 播放器优化:
- 指数退避自动重试
- 僵尸播放器检测
- 子流降级支持
总结 + 开源链接
v0.3.0 从 v0.2.0 到现在,总共 141 个提交,45 个新功能,48 个修复。从外部依赖到插件实验,再到内置简洁实现的架构演进,让我深刻体会到:
有时候,最"正确"的架构并不是最灵活的那个。对于一个当前阶段的项目,简洁性往往比扩展性更重要。
开源地址:
折腾了这么久,小米摄像头的支持终于稳定了。如果你也在折腾智能家居,不妨试试看。