MiBeeNvr v0.5.0: ONVIF 全协议支持 + 硬件转码 + rpi-cam 协同开发
v0.4.0 发布不到一周,又肝了 31 个提交。v0.5.0 是一个功能密度很高的版本:ONVIF 全协议支持(Device/Media/PTZ/Imaging/Event 五大服务全覆盖)、硬件转码(H.265 → H.264)、录制器重连优化。127 个文件变更,+24,509 / -730 行。完整更新列表见 GitHub Release Notes。
没看过之前版本的可以先看 MiBeeNvr 介绍 和 v0.4.0 技术帖。
ONVIF 全协议支持
v0.4.0 已经有了 ONVIF 设备发现和流地址获取,但那只是 ONVIF 协议的冰山一角。v0.5.0 补全了 ONVIF Profile S 的核心服务:
| ONVIF 服务 | 功能 | 状态 |
|---|---|---|
| Device Service | WS-Discovery、能力查询、Profile 列表 | ✅ |
| Media Service | 流地址获取、媒体配置 | ✅ |
| PTZ Service | 连续/相对/绝对移动、预置位、归位 | ✅ 新增 |
| Imaging Service | 亮度/对比度/饱和度/锐度/聚焦(原始 SOAP) | ✅ 新增 |
| Event Service | PullPoint 订阅,实时摄像头事件 | ✅ 新增 |
| Snapshot | GetSnapshot JPEG 抓图 | ✅ 新增 |
ONVIF 交互流程
一个典型的 ONVIF 摄像头从发现到控制的完整流程:
sequenceDiagram
participant NVR as MiBeeNvr
participant CAM as ONVIF 摄像头
Note over NVR,CAM: ① WS-Discovery 发现设备
NVR->>CAM: Probe (Multicast)
CAM-->>NVR: ProbeMatch (XAddr)
Note over NVR,CAM: ② 获取设备能力
NVR->>CAM: GetCapabilities
CAM-->>NVR: Device/Media/PTZ/Imaging URI
Note over NVR,CAM: ③ 获取媒体配置
NVR->>CAM: GetProfiles
CAM-->>NVR: 编码/分辨率/帧率
Note over NVR,CAM: ④ 获取流地址
NVR->>CAM: GetStreamUri
CAM-->>NVR: rtsp://host:port/stream
Note over NVR,CAM: ⑤ PTZ 控制
NVR->>CAM: ContinuousMove / AbsoluteMove
CAM-->>NVR: PTZ 响应
Note over NVR,CAM: ⑥ 图像参数调节
NVR->>CAM: GetImagingSettings / SetImagingSettings
CAM-->>NVR: 当前/更新后的参数
Note over NVR,CAM: ⑦ 事件订阅
NVR->>CAM: PullPoint Subscribe
CAM-->>NVR: 实时事件通知前端集成
v0.5.0 在前端完整接入了 ONVIF 所有服务:
- DeviceManagement — 设备信息展示、能力查询
- ImagingPanel — 亮度、对比度、饱和度、锐度实时滑块调节
- PresetManager — PTZ 预置位创建、调用、删除
- ONVIFEvents — 实时事件订阅和展示
- DeviceCapabilities — LiveView 中显示设备能力信息
UI 大改版
v0.5.0 的前端有了比较大的变化,ONVIF 相关功能全部融入了 LiveView 和设置页面:
- ONVIF 设备管理面板 — 在摄像头详情页可以看到设备信息、能力查询结果,直接管理 ONVIF 连接

- PTZ 控制摇杆 + 预置位管理 — LiveView 中直接操作云台,创建和管理预置位,一键归位
- 图像参数实时调节 — 滑块控制亮度、对比度、饱和度、锐度,调完即时生效
- ONVIF 事件流 — 实时展示摄像头上报的事件(移动检测、报警等)
- 转码状态监控 — 新增监控页面,展示转码任务状态和性能指标

连接缓存
ONVIF 的 SOAP 请求开销不小——每次操作都要建立 HTTP 连接、解析 WSDL、组装 XML。v0.5.0 对每个摄像头维护了一个 ONVIF 客户端连接池,避免重复建连。对于需要频繁调 PTZ 或调参数的场景,响应速度明显提升。
为什么要造 rpi-cam
ONVIF 协议开发有一个很现实的问题:需要一个能跑的 ONVIF 服务端来调试。光看协议文档和抓包是不够的,客户端实现到底对不对,得有个对端实际交互才知道。
我手边有一台树莓派 3B + OV5647 摄像头,之前跑着 MediaMTX 推 RTSP 流。但 MediaMTX 没有 ONVIF 服务端模式(GitHub issue #1402),NVR 发现不了它。
找了一圈现成方案:
- Python 写的 — 性能不行,内存占用高
- 功能不完整 — 只支持 Device 服务,缺 Media/PTZ/Imaging
- 需要 CGO — 交叉编译太麻烦
而且有个关键优势:MiBeeNvr 的 ONVIF 客户端用的是 0x524a/onvif-go 库,如果服务端也用同一个库,客户端和服务端就是完全兼容的,调试起来特别方便。
于是就造了 rpi-cam(也叫 raspberrypi-camera)。
rpi-cam 是什么
rpi-cam 是一个用 Go 写的轻量级树莓派 ONVIF 相机服务,专门为资源受限的 ARM 设备设计。核心特性:
- 完整的 ONVIF Profile S — Device/Media/PTZ/Imaging 四大服务 + WS-Discovery
- RTSP 流媒体 — 使用和 MediaMTX 同样的 gortsplib 库
- RTMP 推流 — 支持推到阿里云、腾讯云等云服务
- 相机参数控制 — 亮度、对比度、饱和度、锐度实时调节
- 数字 PTZ — 通过软件裁剪实现平移、缩放
- 零 CGO — 纯 Go,交叉编译无压力
- 15-25 MB 内存 — 替换掉 MediaMTX 后内存占用降了一半
flowchart LR
subgraph "树莓派"
CAM["CSI/USB 相机"]
RPC["rpi-cam"]
end
subgraph "MiBeeNvr"
ONVIF["ONVIF 客户端"]
REC["录制器"]
end
subgraph "云服务"
CLOUD["RTMP 推流"]
end
CAM --> RPC
RPC -->|"ONVIF Profile S"| ONVIF
RPC -->|"RTSP"| REC
RPC -->|"RTMP"| CLOUD
classDef cam fill:#E3F2FD,stroke:#1565C0,color:#1565C0
classDef app fill:#FFF3E0,stroke:#E65100,color:#BF360C
classDef ext fill:#E8F5E9,stroke:#2E7D32,color:#1B5E20
class CAM cam
class RPC,ONVIF,REC app
class CLOUD ext客户端 + 服务端协同开发
rpi-cam 和 MiBeeNvr 的 ONVIF 实现使用的是同一个 onvif-go 库。这意味着:
- 协议兼容性零成本 — 客户端的 SOAP 请求格式和服务端的解析逻辑完全一致
- 双向验证 — 发现问题可以同时排查客户端和服务端
- 快速迭代 — 改完客户端立刻能在 rpi-cam 上验证,不需要等真实摄像头响应
实际开发过程中,ONVIF 的 PTZ、Imaging、Event 服务都是同时在 MiBeeNvr(客户端)和 rpi-cam(服务端)两端开发的。写完一个服务的客户端调用代码,立刻用 rpi-cam 验证,发现问题当场修。这种开发效率是用真实 IP 摄像头调试做不到的——真实设备可能不支持某些操作,返回的错误信息也不够明确。
实测对比
在树莓派 3B(905MB 内存)上,rpi-cam 替换 MediaMTX 之后的对比:
| 指标 | rpi-cam | MediaMTX |
|---|---|---|
| 内存占用 | 15-25 MB | ~45 MB |
| ONVIF 服务端 | ✅ Profile S 完整支持 | ❌ 不支持 |
| 相机参数控制 | ✅ 亮度/对比度等 | ❌ 无 |
| RTMP 推流 | ✅ 内置 | ❌ 需额外配置 |
| CGO 依赖 | 零 | 需要 |
rpi-cam 已经在树莓派上稳定运行了几个月,没掉过线。感兴趣可以看 rpi-cam GitHub 和之前的 介绍文章。
硬件转码系统
另一个重要特性是硬件加速转码(H.265 → H.264)。很多摄像头只输出 H.265,但浏览器直接播放 H.265 还是比较困难。v0.5.0 的转码系统可以自动检测输入编码,在需要时进行硬件加速转码:
- 自动检测 — 识别摄像头编码格式,按需启动转码
- 硬件加速 — 利用设备 GPU 进行转码,降低 CPU 开销
- 冻帧防闪 — 转码过程中的冻帧防闪处理,流更平滑
配合新增的监控页面,可以实时查看转码状态和性能指标。
硬件转码对设备有要求
转码依赖硬件的视频编解码能力。当前的主力设备树莓派 3B 的 VideoCore IV GPU 不支持 H.265 硬件解码,遇到 H.265 摄像头只能靠 CPU 软解,905MB 内存 + Cortex-A53 @ 1.2GHz 的算力实在捉襟见肘。
接下来我会引入 Banana Pi BPI-M5 来完善转码和视频存储能力。BPI-M5 搭载的 Amlogic S905X3 芯片内置 Mali-G31 MP2 GPU,支持 H.265/HEVC 4K@60fps 硬件解码,更适合做 NVR 的转码节点。
| 参数 | 树莓派 3B | Banana Pi BPI-M5 |
|---|---|---|
| SoC | Broadcom BCM2837 | Amlogic S905X3 |
| CPU | Cortex-A53 × 4 @ 1.2GHz | Cortex-A55 × 4 @ 1.8GHz |
| GPU | VideoCore IV | Mali-G31 MP2 |
| RAM | 1GB LPDDR2 | 4GB DDR4 |
| H.265 解码 | ❌ 不支持 | ✅ 4K@60fps |
| H.264 解码 | ✅ 1080p@30fps | ✅ 1080p@60fps |
| 有线网络 | 100Mbps | 1000Mbps |
| USB | 2.0 × 4 | 3.0 × 4 |
| 存储 | microSD | eMMC + microSD |
BPI-M5 在 CPU 性能、内存、H.265 硬解、千兆网口、USB 3.0 全面碾压树莓派 3B。NVR 场景下,千兆网口意味着更多摄像头并发不卡,4GB 内存可以缓存更多实时流,H.265 硬解让转码不再是瓶颈。后续转码功能的完善会在 BPI-M5 上进行。
录制器重连优化
v0.5.0 重构了录制器的重连策略。之前用指数退避,但实际场景中固定间隔的重试更可控。新的分级退避策略:
| |
每一级都有随机抖动,避免多个摄像头同时断连后同时重连造成雪崩。RTSP 连接超时也加入了配置项,可以根据网络环境调整。
Bug 修复
v0.5.0 修复了几个影响稳定性的问题:
- CS2 缓冲区溢出 — 丢弃最旧帧而不是触发完整 P2P 重连,小米摄像头稳定性显著提升
- Docker 首次启动崩溃 — autoInitConfig 调用 ApplyDefaults(),HLS 字段在验证前正确填充
- 健康告警误报 — 修正阈值、增加防抖、支持每摄像头覆盖
- UI 认证跳转 — 修复 hash 同步问题导致的导航死循环
- ONVIF ContinuousMove — 提供默认超时
- ONVIF PTZ 预置位 — 补全缺失的 HTTP 端点
社区反馈已解决
v0.4.x 和 v0.5.0 期间收到了不少社区反馈,以下是 GitHub Issues 中已关闭的问题:
Docker 部署问题
#6 数据库打开失败 — Docker 首次启动时 db open: unable to open database file (14)。原因是 DB 初始化在存储管理器创建目录之前执行。已在代码中增加 os.MkdirAll 确保目录存在。
#8 绿联云 NAS 权限错误 — 绿联云 NAS 上 Docker 部署权限不匹配。解决方案:Docker 设置 user:0:0,文件管理器将 data 目录权限设置为普通用户。
#13 Docker 首次启动配置缺失 — Docker 首次启动自动生成配置时,HLS 默认值未正确填入,导致 hls.segment_count must be between 3 and 10, got 0 错误。v0.5.0 的 autoInitConfig 调用了 ApplyDefaults() 确保 HLS 字段在验证前填充。
小米摄像头连接稳定性
#10 / #11 小米摄像头频繁断连 — 摄像头在"录制"和"重连中"之间循环,日志出现 cs2: pop buffer is full 和 cs2: EOF。
v0.5.0 做了三层修复:
- 缓冲区溢出不再重连 — 满时丢弃最旧帧并推入新帧,而不是触发完整 P2P 重连。对视频流来说丢一帧远比重建整个会话代价小
- 重连策略改为分级退避 — 前 5 次 1s、5-9 次 5s、10-19 次 10s、20+ 次 60s,成功连接后重置计数
- CS2 连接挂起修复 — 修复了约 20 分钟后连接挂起的问题,消除了 UDP 写入的数据竞争
#5 重启容器后摄像头不可用 — 部分摄像头使用 TUTK 协议(而非 CS2),代码中仍向小米云请求了 TUTK 参数导致误导性报错。已从云请求中移除 TUTK,仅支持 TUTK 的摄像头在添加时会给出明确提示。
设备兼容性
#9 小米智能室外摄像机 4 Pro 三摄变焦版 — 该型号使用 TUTK 传输协议(非 CS2),需要商业授权,目前不在支持范围内。如果摄像头支持 RTSP,推荐用 RTSP 方式接入。
如果你遇到了类似问题,先升级到最新版本试试。如果问题仍然存在,欢迎到 GitHub Issues 提交并附上日志,我会跟进排查。
关于 ONVIF 兼容性
ONVIF 协议虽然号称标准,但实际上不同厂商的实现差异很大。rpi-cam 作为开发调试工具保证了 MiBeeNvr 自身的 ONVIF 实现是正确的,但对接真实的商用 IP 摄像头时,可能还会遇到各种边界情况。
ONVIF 的完整兼容性还需要时间验证。目前主要在 rpi-cam(自研服务端)和少量真实摄像头上测试通过,覆盖的品牌和型号还有限。如果你在用 MiBeeNvr 对接 ONVIF 摄像头时遇到问题——比如发现不了设备、PTZ 控制不响应、参数调节失败——请到 GitHub Issues 提交,附上摄像头型号和具体现象,我会跟进排查。
升级
| |
配置向后兼容,直接替换二进制即可。