v0.6.0 把延时摄影管道搭起来之后,社区反馈很快就指出了几个硬伤:JPEG 序列要吃掉太多存储、H.265 摄像头生成的延时片段播放不了、双摄小米设备只能抓到主镜头、偶尔还会出现 H.265 HLS 直接 panic 的崩溃。这些都不是边缘场景——双摄 CW500 和室外摄像头 4 在国内出货量很大,H.265 已经是中高端摄像头的事实标准。v0.7.0 的主线就是围绕这些反馈展开的。
这一版把延时摄影管道整体重写成了 v2:用纯 Go 实现的 H.264/H.265 NAL→MP4 muxer 取代了之前依赖 FFmpeg 的合并路径,关键帧文件自包含 SPS/PPS,合并出来的就是可直接播放的 H.264/H.265 视频,不再生成中间 JPEG 序列。小米双摄支持通过通道选择接入,CW500、室外摄像头 4 这类设备能指定镜头;H.265 HLS 的 panic 被 StreamHub 重构和 muxer 自动恢复彻底治住了。转码模块也借这版做了一次分层重构——硬件探测、编码器抽象、任务管道拆成独立层,新增编码器和硬件后端不再牵动整个管道。前端 Dashboard 则做了轮大整理:AI 模块移除、摄像头管理简化、延时和普通录像合并到统一列表。
发布前在真实摄像头环境下充分验证了这些改动,包括 CW500 双摄、H.265 摄像头的 HLS/延时录制、以及 Docker 部署的存储路径与 GPU 直通场景。三个自研摄像头项目也跟着同步更新——一个改了名(MiBeeHomeCam → MiBee Cam,新增 ONVIF 自动发现)、一个换了仓库和定位(rpi-cam → mibee-eye-raspi,覆盖所有 libcamera 兼容主板)、一个修了上版的遗留 bug,文末单开一节讲。更早一轮(v0.6.0 同期)的三个项目细节见 camera-test-machines。完整变更列表见 GitHub Release Notes。
延时摄影 v2 管道
v2 的核心变化是合并路径不再经过 FFmpeg,关键帧直接以 H.264/H.265 NAL 单元的形式进入自研 muxer,封装成自包含的 MP4:
RTSP/小米源h264/h265关键帧抽取器SPS/PPS缓存H.264/H.265关键帧序列滚动合并纯Gomuxer自包含MP4可直接播放
v0.6.0 的管道在 JPEG 序列上做合并,合并阶段必然要重新编码,CPU 开销和文件体积都下不来。v2 的关键帧抽取器在第一帧就把 SPS/PPS 缓存下来,之后每个关键帧的 NAL 单元都带着这份参数集一起落盘,合并时只需要把 NAL 单元按序封装进 MP4 容器——纯 mux、零编码。
双模式关键帧抽取
v2 抽取器支持两种工作模式,由每个摄像头独立配置:
interval 模式: 按 config.timelapse.interval 抽帧 (默认 30s)
IDR 模式: 直接复用 RTSP 流中的 IDR 帧,不做时间间隔过滤
interval 模式适合 MJPEG 源或需要降低帧率的高频 RTSP 流;IDR 模式适合 H.264/H.265 流——摄像头本身的 GOP 决定了关键帧间隔,直接复用 IDR 帧可以完全跳过解码,抽取器只做 NAL 单元过滤和 SPS/PPS 缓存,开销几乎为零。
滚动合并的合并时长
合并不再是固定的「每日一次」,而是提供了 8h / 12h / 24h / 自然天 / 7d / 30d 几档可选。滚动合并管理器按合并时长切分时间窗口,窗口结束后触发合并任务;用户也可以在前端通过 retry-merge API 手动触发合并。
延时录像现在和普通录像一起出现在统一的录像列表里,前端不再需要单独的延时入口。每个摄像头的延时配置(间隔、帧源、合并模式)都可以在摄像头配置编辑器里单独设置。
纯 Go muxer vs FFmpeg 合并
| 对比维度 | v2 纯 Go muxer | v0.6 FFmpeg 合并 |
|---|---|---|
| 依赖 | 无 | 需要 FFmpeg |
| 合并方式 | NAL 单元直接封装为 MP4 | JPEG 重新编码为 H.264 |
| 编码开销 | 零(仅 mux) | 高(编码) |
| 输入帧源 | H.264 / H.265 关键帧 | JPEG 序列 |
| 适用场景 | 长期存档、实时预览 | 已废弃 |
v2 的 muxer 同时支持 H.264 和 H.265——这对 H.265 摄像头是关键改进,v0.6 的 JPEG 路径没法生成 H.265 延时片段。
转码架构优化
v0.6.0 的转码管道是按 Wave 1/2/3 三波快速堆出来的——队列、轮询、回填各自独立,硬件探测和编码器选择还混在任务执行路径里。v0.7.0 把整个转码模块做了一次分层重构,目标是让新增编码器、新增硬件后端不再动到任务管道。
设备可用设备不可用任务队列SQLite持久化Worker池并发消费硬件探测层V4L2M2M/VAAPI/NVENC硬件编码vaapi/h264_v4l2m2m/h264_nvenc软件回退libx264/libx265编码器抽象层统一命令构造FFmpeg子进程进度回调+超时控制
分层重构
重构把转码拆成了三层,各司其职:
-
任务管道层:SQLite 持久化的任务队列 + Worker 池。Worker 池按并发度消费任务,每个任务的生命周期(pending → running → done/failed)由队列管理,和具体编码器无关。
-
硬件探测层:在转码引擎初始化阶段一次性完成,结果缓存。VAAPI 探测会检查
/dev/dri/renderD*是否存在;V4L2M2M 探测会枚举/dev/video*的编码节点;NVENC 探测走 FFmpeg 的-encoders输出。探测不到的硬件后端直接关闭该能力,运行时不再重复探测。 -
编码器抽象层:把硬件编码器、软件编码器收敛到统一的命令构造接口。新增编码器只需要实现这个接口,任务管道和 Worker 池完全不用动。
分层之前,编码器选择和硬件探测散落在任务执行的多个分支里,加一个新编码器要改四五处。重构后新增 libx265 软编码、新增硬件后端都只动编码器抽象层。
能力加强
在架构基础上,这版补了几个之前缺的能力:
-
libx265 软编码:v0.6.0 的软件回退只有 libx264,H.265 摄像头转码时无硬件编码器就只能转成 H.264。补上 libx265 后,H.265→H.265 的纯软件转码路径打通,ARM 平台(树莓派、香蕉派)在没有硬件编码器时也能保持编码格式不变。
-
转码与延时摄影共享探测/编码器:v2 延时管道的 H.265 muxer 复用了转码模块的 SPS/PPS 解析和硬件探测结果——延时录像需要重新编码时(比如 JPEG 序列转 H.264 用于长期存档),直接走转码的编码器抽象层,不再各自维护一套 FFmpeg 调用。
-
MJPEG 输入的软件编码:之前 MJPEG 输入源在 ARM 上被错误地禁用了软件编码,修复后 MJPEG 输入也能走 libx264/libx265。
可靠性
任务管道的可靠性也做了加强:失败任务的重试不再丢上下文(Worker 重启后从 SQLite 恢复队列状态),FFmpeg 子进程的超时和进度回调独立监控,避免单个转码任务卡死拖垮整个 Worker 池。加上前面提到的 VAAPI 设备校验和 FFmpeg 状态测试隔离,转码在 Docker、虚拟机、ARM 板子上的稳定性都明显改善。
小米双摄支持
双摄小米设备(CW500、室外摄像头 4 等)的两组镜头共用一个设备 ID,go2rtc 这类上游项目在处理时存在通道限制。v0.7.0 在小米云集成里加了通道选择,用户在添加摄像头时可以指定镜头。
双摄设备小米云MiBeeNvr用户双摄设备小米云MiBeeNvr用户单独的 recorder 实例独立录制与转码添加摄像头 + 选择镜头解析设备流地址 (did + channel)返回指定通道的 MISS URLmiss connect (指定通道)该镜头的 RTP 流
通道选择作用于 MISS URL 解析阶段——小米云返回的是设备级地址,MiBeeNvr 在建立 recorder 时把 channel 参数带上,拿到的就是指定镜头的流。每个镜头对应一个独立的 recorder 实例,录制、转码、延时管道都各自独立,和单摄摄像头在数据流上没有区别。
另外修了 test-connection 里的 RTSP URL 凭证处理:之前带特殊字符的密码会把 URL 拼错,导致连接测试一直失败,实际录制却正常——这种「测试失败但能跑」的状态最容易让人困惑。
H.265 HLS 封装改进
#20 报告的 H.265 HLS panic 是这一版的重点修复。崩溃发生在 muxer 还没初始化时,HLS 写入路径直接走到了未初始化的 muxer 指针上:
已初始化未初始化RTP帧StreamHub路由Muxer正常写入自动恢复重新初始化Muxer恢复后继续写入
根因是 StreamHub 在多路径分发时没有统一处理 muxer 的生命周期——H.265 流的首帧到达时 muxer 可能还没建好,但写入路径没有这层防护。重构后的 StreamHub 集中管理 muxer 状态:写入前检查 muxer 是否就绪,未就绪则触发自动恢复流程,重新初始化 muxer 后再继续写入,而不是直接 panic。
#18 报告的小米摄像头反复重连也是同一类问题在连接层的体现。小米 CS2 设备的 UDP miss connect 在网络抖动时会超时,之前的退避策略固定 1 分钟,且 PONG 响应处理不当——PONG 丢失后连接状态机卡住,导致看起来像是设备掉线、反复触发重连。修复包括:PONG 响应的健壮性处理、退避时间加随机抖动、CS2 缓冲区在重连时主动丢弃残留数据,避免旧数据污染新连接。
发布加固
这一版在稳定性、CI 和打包上做了不少加固工作,主要受 #15 的 Docker 部署反馈驱动。转码模块的 VAAPI 设备校验和 FFmpeg 状态测试隔离归在前面的转码架构优化里讲,这里说其余几项。
WebSocket 解码器背压:多路同时播放时,Worker 到 ConnectionManager 的 WebSocket 解码器没有背压控制,背压上来直接丢帧或卡死。修复把背压信号从 Worker 一路接到 ConnectionManager,多路播放稳定性明显改善。
Docker 存储路径:#15 反馈的容器重启报 mkdir /var/lib/mibee-nvr: permission denied,根因是 entrypoint 里的默认存储路径和实际数据卷路径不一致。修复对齐了路径,重启不再丢权限。
Dashboard UX 大改
v0.6.0 到 v0.7.0 之间,前端 Dashboard 做了一轮比较大的整理。驱动力有两个:一是 v2 延时管道产出的录像需要和普通录像统一展示,旧的「录像」和「延时」分两个入口已经讲不清;二是浏览器端的 AI 检测模块一直没做完,留在界面上反而误导用户。
v0.7.0v0.6.0摄像头管理含Enabled开关录像列表延时入口(独立)AI检测(半成品)摄像头管理简化,移除Enabled统一录像列表普通+延时转码历史页AI模块移除
-
移除 AI 模块:浏览器端的目标检测只做了识别、没做跟踪,实际用处不大还占资源。v0.7.0 直接从前端移除,后端
internal/ai/的 ONNX Runtime 推理框架保留,作为未来独立功能(实时目标检测)的基础,不再在 Dashboard 里暴露半成品入口。 -
摄像头管理重构:移除了
Enabled字段。之前每个摄像头有个「启用/禁用」开关,但这个状态和录制、流媒体、转码的状态机交织在一起——禁用的摄像头偶尔还会因为事件总线触发录制,行为不一致。重构后摄像头的启停统一走录制器生命周期,配置里不再有这个容易踩坑的开关。 -
统一录像列表:延时录像和普通录像合并到同一个列表,前端按类型筛选。之前延时录像要进单独的页面才能看,v2 管道产出 H.264/H.265 MP4 后,延时片段和普通录像在播放体验上没有差别,没必要分两个入口。
-
转码历史页:转码任务的状态(pending/running/done/failed)、重试按钮、历史记录分页清理都收进了一个独立页面,之前是散在录像详情里的。
社区反馈与已关闭 Issue
这一版关闭了 4 个社区 issue,都是在真实使用中暴露出来的:
-
#14 多镜头设备支持与视频画质优化 — 小米 CW500 双摄和室外摄像头 4 双摄只能抓到主镜头,且录制画质偏糊。v0.7.0 通过通道选择接入双摄的第二镜头,转码管道支持 H.264/H.265 互转,画质可以通过转码参数调整。
-
#15 5.0 新版本 Docker 测试报告 — Docker 部署的存储路径权限问题、设置页保存入口、H.265 的 HLS/HTTP-FLV/LL-HLS 播放兼容性、以及实时画面时间戳错乱。逐条修复,Docker 路径对齐、设置入口简化、HLS 时间戳回放循环问题定位到 muxer。
-
#18 小米摄像头反复重连 — 小米 CS2 设备 UDP miss connect 频繁超时,重连退避固定 1 分钟,PONG 响应处理不当导致状态机卡住。修复了 PONG 健壮性、退避加抖动、CS2 缓冲区重连清理。
-
#20 H.265 error — H.265 HLS 在 muxer 未初始化时直接 panic。StreamHub 重构统一管理 muxer 生命周期,写入前检查就绪状态,未就绪触发自动恢复。
Bug 修复
-
转码 VAAPI 设备校验 — 硬件探测在选 VAAPI 编码器前检查
/dev/dri/renderD*,GPU 不可用时降级 libx264/libx265。 -
FFmpeg 状态测试隔离 — 测试不再因本机装了系统 FFmpeg 而失败,CI 解锁。
-
WebSocket 解码器背压 — 背压信号从 Worker 接到 ConnectionManager,多路播放稳定。
-
滚动合并兼容所有录制器类型 — H.264、H.265、MJPEG 三种录制器的关键帧都能正确合并。
-
关键帧抽取器缓存 SPS/PPS — 关键帧文件自包含,不依赖外部参数集。
-
摄像头 H.265 编码检测 — 运行时录制器类型用于关键帧抽取器,不再用静态配置判断。
-
录像帧列表接口 — 列表包含 H.264/H.265 延时帧,前端能正确展示。
-
i18n 缺失翻译键 — 补全延时协议、转码历史操作相关文案。
升级
配置向后兼容,直接替换二进制即可:
# Docker
docker pull ghcr.io/mi-bee-studio/mibeenvr:latest
# 或下载二进制
wget https://github.com/Mi-Bee-Studio/MiBeeNvr/releases/latest/download/mibee-nvr-$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
升级后建议检查 config.example.yaml 中的新配置项(timelapse v2 的合并时长、双摄通道选择、转码硬件探测等),按需补充到自己的配置文件中。小米双摄用户需要在摄像头配置里重新选择镜头。
摄像头项目同步更新
和 v0.6.0 一样,v0.7.0 的测试也依赖三个自研摄像头项目提供真实环境。这一轮它们自己也有不少变化——一个改了名、一个换了仓库和定位、一个修了上版的遗留 bug。
MiBeeHomeCam → MiBee Cam(v0.3.0)
基于 Seeed Xiao ESP32-S3 Sense 的固件改了产品名:MiBeeHomeCam → MiBee Cam,固件、文档、配置里的引用全部同步更新。改名是为了和 MiBee 体系下的命名统一,原来的 HomeCam 后缀容易和家居摄像头混在一起。
v0.3.0 的重点是 ONVIF 接入,让这个 MCU 摄像头能被主流 NVR 自动发现:
-
ONVIF WS-Discovery 自动发现:固件实现了 WS-Discovery 的 UDP 多播响应,Synology Surveillance Station、Milestone XProtect 这类支持 ONVIF 的 NVR 不用再手动填 IP,局域网内自动出现。
-
ONVIF SOAP 服务:Probe、DeviceInfo、GetProfiles、StreamURI 等,返回 HTTP MJPEG URI。
-
MJPEG 独立端口:MJPEG 流从原来的 HTTP 80 端口挪到独立的 TCP 81 端口,由单独的服务任务承载——之前 MJPEG 流和 Web UI 共用一个 HTTP server,流任务一忙就把配置页卡死。
-
帧广播器(Frame Broadcaster):彻底解决了 v0.6.0 测试时反复出现的帧缓存(FB)争用——camera FB 拿到后立即拷贝到 PSRAM 归还,录制和流任务各自持拷贝,互不阻塞。这正是 camera-test-machines 里详细写过的 PSRAM 双缓冲方案的正式落地。
另外补了 Prometheus /metrics(堆内存、PSRAM、温度、录制统计等 15+ 项)、摄像头初始化失败时的优雅降级(无摄像头也能启动,Web UI 显示离线),以及把最小延时摄影间隔降到了 1 秒。RTSP 相关代码整个移除——ONVIF + HTTP MJPEG 覆盖了原来 RTSP 的场景。
rpi-cam → mibee-eye-raspi(仓库迁移 + 定位扩展)
树莓派的 Go ONVIF 摄像头服务 rpi-cam 做了一次比较大的调整:仓库从 raspberrypi-camera 迁到了 mibee-eye-raspi,定位也从「树莓派摄像头」扩展为「所有支持树莓派摄像头模组的主板」。
mibee-eye-raspiGoONVIF摄像头服务ARM64主板树莓派3B/4/5香蕉派BPI-M5(RK3588)香橙派5(RK3588)其它libcamera兼容主板
关键点是这些主板都走 libcamera 栈——rpi-cam 的数字 PTZ(基于 libcamera 的 ScalerCrop)、成像控制、H.264 推流本来就是基于 libcamera 实现的,所以在香蕉派 M5(RK3588)、香橙派 5 这类同样支持 libcamera 的 ARM64 板子上的行为完全一致。RK3588 这类板子还能用上硬件 H.265 编码,性能比树莓派 3B 强不少。
改名和迁仓库是为了把这个事实体现出来——它不再是「树莓派专用」,而是「任何能跑 libcamera 的 ARM 板」都能用的 ONVIF 参考实现。功能本身和 v0.2.0 一致(HLS 直播、Web Admin UI、SPS/PPS 缓存快照),主要是定位和分发渠道的变化。
MiBeeCam(v0.2.2)
基于 Luatos ESP32-S3 A10 模块的紧凑型摄像头,这版主要修了 camera-test-machines 里提到的那个调试遗留 bug——wifi_start_sta() 里硬编码的测试 WiFi 凭证,参数被 (void) 抑制后完全忽略。v0.2.2 移除了硬编码凭据,函数参数正常生效。同时把 ESP-IDF 版本引用更新到 v5.5.4,补了 WiFi STA 故障排查文档。
相关链接
-
MiBeeNvr GitHub
-
MiBeeNvr v0.7.0 Release Notes
-
MiBeeNvr v0.6.0 技术帖
-
camera-test-machines: 同期更新的三个摄像头项目
-
MiBee Cam v0.3.0 (原 MiBeeHomeCam)
-
mibee-eye-raspi (原 rpi-cam / raspberrypi-camera)
-
MiBeeCam v0.2.2
296

被折叠的 条评论
为什么被折叠?



