v0.10.0-preview.1 — H.265 WASM 直播 · Timelapse v3 · MJPEG WebSocket · 认证现代化 · 架构大清理
Pre-releasev0.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/libde265WASM 解码器,局域网普通 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)捕获移到
RecordEnabledgate 之前,修复 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-h265CLI(#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-mergesCLI 清理历史泄漏 - 录像时间线截断(#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
📝 文档
⚠️ 破坏性变更(升级前必读)
完整迁移步骤见 升级指南。
- 配置:组合协议串被拒 — 旧格式
protocol: "rtsp_h264"在 0.10.0 启动时直接报错。必须拆分为protocol: rtsp+encoding: h264 - DB schema v28→v29 —
recordings.merged列被删除(自动备份到.pre-v29-backup)。< v0.9.x 不支持直升 0.10.0,必须先升级到 0.9.x - API 端点移除 —
GET /api/timelapse/{id}/thumbnail和/preview已删除(404) - 默认值变化 —
cleanup.disk_threshold_percent95→85;timelapse.merge_duration默认"1h"→"natural-day" - 升级后建议 — 跑
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 -dFull 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 cleanup — config.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).
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.