Skip to content

v0.10.0-preview.1 — H.265 WASM 直播 · Timelapse v3 · MJPEG WebSocket · 认证现代化 · 架构大清理

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 28 Jul 05:40
466f046

v0.10.0-preview.1 — H.265 WASM 直播 · Timelapse v3 · MJPEG WebSocket · 认证现代化 · 架构大清理

0.10.0 的首个预览版(release candidate)。这是自 0.8.0 以来最大的版本,主题是H.265 全链路打通延时摄影 v3 重写MJPEG 低延迟化认证安全现代化,以及一轮贯穿 config / DI 根 / API 路由 / 前端播放器的架构清理

⚠️ 这是预览版(preview),不建议用于生产。 含破坏性变更,升级前务必阅读下方"破坏性变更"和 升级指南
英文摘要见文末 / English summary at the bottom.

54 次提交,273 个文件,+27,246 / −12,719 行(feat 9 / fix 29 / refactor 9 / test 2 / cleanup 2 / docs 2 / perf 1)。


🎬 H.265 全链路打通(直播 + 录制 + 合并 + 回放)

0.9.x 之前 H.265 直播依赖 WebCodecs(需要 HTTPS secure context),合并产物在 Edge 上经常黑屏,延时合并根本不工作。本版本端到端修复了整条 H.265 链路:

  • H.265 直播通过 libde265 WASM(纯 HTTP)#102):引入 @yume-chan/libde265 WASM 解码器,局域网普通 HTTP 也能播放 H.265 直播,不再依赖 HTTPS。前端自动探测:优先 WebCodecs(HTTPS 下硬件加速),不可用时回退 WASM
  • 自适应 Player Orchestrator#106):前端播放器抽象为可测试的状态机(web/src/lib/player/)。每摄像头候选链 + 健康状态响应(failed→立即降级,degraded→8s 防抖,ok→稳定 30s 升级)。解决了 H.265 多路网格的浏览器冻结风暴(#107/#108/#120 postmortem 详见 docs/known-issues-h265-multicam.md
  • H.265 编码持久化#112):ONVIF 相机的编码探测结果现在双写到 YAML + DB("probe once, persist forever"),消除编码元数据陈旧导致的黑屏和协议风暴
  • H.265 录制参数集时序修复#103):参数集(SPS/PPS/VPS)捕获移到 RecordEnabled gate 之前,修复 live-only 黑屏
  • H.265 回放路由#105):按运行时编解码 + 权威 MSE 探测路由,确保 H.265 走 WASM 而非错误的 MSE 路径
  • H.265 延时合并可播放#89/#92/#95):修正 hvcC box 的 numNalus;使用保守 Main-tier 默认值(不解析可能自相矛盾的 SPS,解决 Edge HEVC 扩展拒绝);周期合并现在正确检测 H.265/H.264 帧(之前只收集 JPEG,H.265 相机总是失败)

⏱️ Timelapse v3 — 灵活合并窗口 + 周期合并 DB + 连续链(#91

延时摄影系统的重大重写:

  • 移除 1h 硬上限:支持 natural-day / 8h / 12h / 24h / 7d / 30d 合并窗口(之前这些值被静默 clamp 到 1h)。默认值从 1h 改为 natural-day
  • 周期合并 DB 记录:新增 timelapse_merges 表(schema v29),每个长窗口合并输出有完整的 DB 记录(相机、窗口、时长、codec、帧数、状态)。前端通过 /api/timelapse/merges* 端点发现/播放/删除
  • codec 感知播放X-Timelapse-Codec 响应头驱动播放器选择——H.264/H.265 用 <video>,MJPEG 用 JPEG 帧轮播
  • 连续合并链:周期合并会折叠之前的中间产物,避免无限累积。可选 retain_intermediate_mp4 保留中间文件
  • repair remerge-h265 CLI#93):修复历史上 Edge 无法播放的 H.265 延时合并
  • 时区对齐#94):natural-day 窗口现在正确对齐服务器本地时区(之前 Local 时区导致窗口偏移)

📡 MJPEG 相机低延迟化(#99

ESP32 MiBeeCam 等 MJPEG 相机从 HTTP 轮询改为 WebSocket 流式传输(wsstream),大幅降低延迟和连接数。

🔐 认证现代化(#110/#113

  • 无状态签名 session token:弃用 base64 明文密码的 BasicAuth 缓存方案,改为 HMAC 签名的无状态 token。安全性提升,无需在内存缓存密码

🖥️ Surveillance 网格拖拽排序(#111/#114

监控网格支持拖拽重新排列摄像头单元,顺序持久化。

🌐 WebRTC 跨网访问(#74

新增 streaming.webrtc.ice_servers 配置(STUN/TURN 服务器列表),WebRTC 从仅局域网扩展到跨网访问。配套远程访问文档。

🏗️ 架构清理与可维护性(refactor 集中批次)

  • config.go 拆分#147):1946 行单文件拆为 155 行入口 + 13 个子系统文件(camera/merge/timelapse/transcoding/streaming/health/ingest/ai/server)。100% public API 保留,零行为变更
  • pkg/app/run.go 拆分#148):提取 helpers.go + router.go,降低 DI 组合根的单文件复杂度
  • Handler.Routes() 拆分#149):685 行 god-method 拆为 14 个按领域的路由注册器,零端点丢失
  • 0.10.0 API 带宽优化#97):gzip 压缩(~70-85%)、ETag(If-None-Match→304)、view=summary 轻量端点、录像列表 limit clamp(默认 50 / 最大 500)、CameraRow 字段 omitempty
  • Settings 信息架构重写#157/#159):左侧边栏导航 + 统一保存 + 破坏性操作确认。修复了切换分类时丢失未保存更改的回归(#162
  • 前端 merge-utils 提取#150):合并工具函数从路由组件提取到 lib/
  • 录像页移除 gallery 视图#84):默认时间轴,聚焦核心场景
  • Player Orchestrator DOM 无关:可单元测试无需 jsdom,dispatch.ts 详细记录了 Svelte 5 同步发射陷阱的解决方案

🧹 清理与测试加固

  • TUTK dtls/ 死代码删除#141):1420 行 ChaCha20Poly1305 DTLS 实现,零引用,确认死代码后删除
  • CI flake 根治#125/#144/#154):goroutine 生命周期管理(startup-bg service + backfillWg + service-layer goroutine joins),消除 TempDir 清理竞态。全量 go test ./... 一次性 0 失败
  • gzip 中间件回归套件#146):表驱动测试覆盖所有 content-type 的压缩/跳过逻辑
  • timelapse 回归测试#156):关闭 3 个缺口——时区窗口、markMergeFailed 不毒化、.h265 帧收集
  • CI 升级 Node 20→24 actions#146

🐛 关键稳定性修复(选摘)

  • AI 检测 INVALID_PROTOBUF 根因修复#109/#124):发现真正的 root cause 是 streaming-gzip 中间件给二进制响应追加了错误的 gzip trailer(而非最初以为的 CDN 截断)。4 层防御修复:中间件 root cause + 下载层 retry/Range/原子写 + Docker 预置模型 + 前端缓存自愈。详见 docs/known-issues-ai-onnx-gzip-trailer.md
  • 录像删除时合并 MP4 泄漏#117/#119):删除录像现在同时删除合并产物;新增 repair reclaim-orphan-merges CLI 清理历史泄漏
  • 录像时间线截断#115/#118):新增轻量级 /api/recordings/timeline 端点,避免全量加载
  • autodiscover 稳定化#121/#122/#123/#155):IP 漫游去重 + 未变端点 recorder 风暴 + endpoint URL 规范化(scheme/host/port/trailing-slash)——经过 4 轮修复后趋于稳定
  • 启动扫描阻塞#76):异步启动扫描 + 有界 reconcile(8 分钟阻塞→8 秒启动)
  • 合并回填积压#78):退役历史 singleton 解除回填循环阻塞(8500+ pending→排空)
  • ONVIF recording_enabled=false 静默录制#88
  • MJPEG 迁移 OOM#86):限制迁移帧数防止内存溢出
  • 平台感知 AVI 分段时长#81):≤2GB RAM→30s,>2GB→5min

📝 文档

  • 0.10.0 升级指南#145,中英双语 docs/{en,zh}/upgrade-guide.md):覆盖所有破坏性变更和迁移步骤
  • Timelapse v3 文档更新#96

⚠️ 破坏性变更(升级前必读)

完整迁移步骤见 升级指南

  1. 配置:组合协议串被拒 — 旧格式 protocol: "rtsp_h264" 在 0.10.0 启动时直接报错。必须拆分为 protocol: rtsp + encoding: h264
  2. DB schema v28→v29recordings.merged 列被删除(自动备份到 .pre-v29-backup)。< v0.9.x 不支持直升 0.10.0,必须先升级到 0.9.x
  3. API 端点移除GET /api/timelapse/{id}/thumbnail/preview 已删除(404)
  4. 默认值变化cleanup.disk_threshold_percent 95→85;timelapse.merge_duration 默认 "1h""natural-day"
  5. 升级后建议 — 跑 mibee-nvr repair reclaim-orphan-merges --dry-run 检查历史泄漏的合并 MP4

📥 安装 / Install

# 一键安装
curl -fsSL https://raw.githubusercontent.com/Mi-Bee-Studio/MiBeeNvr/main/install.sh | sudo bash

# 或下载二进制(amd64 / arm64 / armv7)
# Docker(镜像已内置 AI 模型,无需运行时下载)
docker compose --project-directory . -f deploy/docker/docker-compose.yml up -d

Full Changelog: v0.9.1...v0.10.0-preview.1


English summary

v0.10.0-preview.1 is the first release candidate of the largest release since 0.8.0. Themes: end-to-end H.265, Timelapse v3 rewrite, low-latency MJPEG, auth modernization, and a sweep of architecture cleanup across config / DI root / API routing / frontend player.

54 commits, 273 files, +27,246 / −12,719 (feat 9 / fix 29 / refactor 9 / test 2 / cleanup 2 / docs 2 / perf 1).

H.265 end-to-end — live playback via libde265 WASM on plain HTTP (#102, no longer needs HTTPS); adaptive Player Orchestrator state machine (#106, fixes multi-cam browser freeze storms); encoding persistence (#112, eliminates stale-metadata black screens); param-set capture timing (#103); playback routing by runtime codec (#105); timelapse merges now play in Edge (#89/#92/#95, conservative hvcC + codec-aware frame collection).

Timelapse v3 (#91) — removed the 1h cap (now supports natural-day/8h/12h/24h/7d/30d); periodic merges have DB records (timelapse_merges table, schema v29); codec-aware playback (<video> vs JPEG cycler); continuous merge chain; repair remerge-h265 CLI.

MJPEG low-latency (#99) — ESP32 MiBeeCam etc. now stream via WebSocket instead of HTTP polling.

Auth (#110/#113) — stateless HMAC-signed session tokens, dropping base64 password caching.

WebRTC cross-network (#74) — configurable ICE/STUN/TURN servers.

Architecture cleanupconfig.go 1946→155 lines split into 13 subsystem files (#147); run.go helpers extracted (#148); Routes() god-method split into 14 domain registrars (#149); 0.10.0 API bandwidth optimization (gzip/ETag/summary view/limit clamp) (#97); Settings IA rewrite (#157/#159); Player Orchestrator DOM-independent and unit-testable (#106).

Key stability fixes — AI INVALID_PROTOBUF root cause was the gzip middleware corrupting binary responses with a spurious trailer (#109/#124, 4-layer defense); recording-delete merge-MP4 leak (#117/#119, + reclaim-orphan-merges CLI); timeline truncation (#115/#118); autodiscover stabilization (#121-#123/#155); 8-min startup block fixed (#76); merge backlog unblock (#78).

⚠️ Breaking changes — combined protocol strings rejected at startup; DB schema v28→v29 (recordings.merged dropped, <v0.9.x must upgrade to 0.9.x first); timelapse/{id}/thumbnail and /preview API removed; disk_threshold_percent 95→85; merge_duration default 1h→natural-day. See the upgrade guide.