v0.9.1 — i18n 全面修复 · 录像优化 · TUTK/Docker 修复 · 文档校准
v0.9.0 的 patch release。聚焦国际化完整性、录像碎片治理、用户反馈的 UX 修复,以及一轮覆盖全部公开文档的准确性校准。无破坏性变更。
英文摘要见文末 / English summary at the bottom.
🌐 i18n 全面修复(社区反馈 #68)
一次系统性的国际化完整性排查:脚本交叉比对了代码里所有 t('...') 引用和翻译字典,发现并修复了所有遗漏:
- 19 个 key 被代码引用但两个语言文件都没有——用户会看到原始 key 名(如
cameras.darkFrameFilter、cameras.passwordSet、cameras.recordingSchedule、cameras.twoWayAudioEnabled、common.close、live.retry、timeline.frameDrop(s)、xiaomi.twoWayAudio*等)。全部补全(en + zh) - 转推(Push-Out)配置整段是硬编码英文——平台选择器、转码策略下拉、整个"预设覆盖"面板(分辨率/帧率/码率/GOP/Profile/B 帧/重置)完全没接 i18n。14 个新 key + 全部硬编码字符串改接
t() - en.json / zh.json:1341 → 1377 个 key,parity 校验 0 缺失
- 排查脚本保留,后续可纳入 CI 防止再犯
💾 录像碎片治理(平台感知分段时长 + 周期回填)
针对"录像碎片太多"的根因治理(v0.9.0 的合并积压问题的后续优化):
- 平台感知分段时长上限:MP4 muxer 在分段关闭前把所有样本驻留内存(moov 最后写),所以分段越长内存占用越高。现在按可用 RAM 自动设上限:
- ≤2GB 可用内存(如树莓派 3B):上限 30s(OOM 安全)
- >2GB 可用内存(如 Banana Pi M5、x86):上限 2 分钟——直接把碎片数量减半,缓解滚动合并压力
- 超过平台上限的配置值会被静默 clamp 并告警
- 周期性回填清扫:新增
rolling_backfill_interval(默认 10m)和rolling_backfill_batch(默认 500)配置——后台周期性清扫历史 pending 分段,不再只依赖启动时的一次性回填。"0"禁用周期清扫(仅启动回填)
🐛 用户反馈修复(#64 / #68 / #70)
来自社区深度用户 @gujiangjiang 的反馈,逐项处理:
- Xiaomi TUTK 不再被添加预检拦截(#64):v0.9.0 已支持 TUTK 协议,但添加摄像头时的
check-vendor预检接口仍把 TUTK 标记为compatible: false,前端弹出"不兼容"拦截对话框。修复后 CS2 和 TUTK 都返回compatible: true - Docker 自定义端口(#64):群晖 NAS 等设备 9090 被占用。补充了 docker-compose 端口映射说明(HOST:CONTAINER 约定)和 host 模式下
server.listen配置指引;troubleshooting 新增"Docker / NAS 9090 端口冲突"章节 - Xiaomi 摄像头隐藏凭据框(#68-1):Xiaomi 走小米账号 token 认证,不走摄像头级用户名/密码。已把 Xiaomi 协议的凭据框隐藏,避免误解
- 合并策略"使用全局默认"真正生效(#68-3):根因是 DELETE 接口调
UpsertCameraMerge(nil...),但该函数用COALESCE保留原值——传 nil 等于 no-op,覆盖配置永远清不掉。新增ClearCameraMerge真正 NULL 所有字段;GET 接口返回customized标志让前端区分"有覆盖"vs"全默认" - 转推地址一键复制(#70-1):摄像头卡片的"1/1"徽章现在可点击,弹出浮层列出每个转推目标(名称/协议/启用状态/完整 URL),每个地址旁有复制按钮
📝 文档全面校准
发版前对全部公开文档(README + docs/en + docs/zh)做了一轮准确性审计,修复 9 个 CRITICAL + 3 个 MODERATE + 1 个 MINOR 问题(18 文件,+664/-809):
- xiaomi-setup.md 双向音频描述反转:文档说"仅 CS2 支持",实际代码是"仅 TUTK 支持"(CS2 会返回
two-way audio requires TUTK transport)。已修正 - timelapse.md 移除"v2"框架 + merge_duration 误导:文档推崇
8h/12h/24h/natural-day/7d/30d,但代码把这些值静默 clamp 到 1h(legacy 字符串)或校验报错(其他 >1h 值)。已准确描述 1h 上限;中文版文件原本被翻译工具污染(每行带#XX|前缀),干净重写 - transcoding.md Prometheus 指标名错误:文档列的
mibee_nvr_transcoding_*不存在,实际是nvr_transcoding_*。已对齐 metrics.md - api/xiaomi.md check-vendor 示例过时:还显示 TUTK 返回
compatible:false,已更新为 v0.9.0 后的真实行为(CS2/TUTK 均 true) - xiaomi-setup.md 型号 ID 错误:文档的 model identifier(如
isa.camera.g2h)和代码常量(lumi.camera.gwagl01)不符。已对齐internal/xiaomi/legacy/client.go - troubleshooting.md 补全 repair 子命令:之前只文档了
repair duration,补充repair merge-status和repair fragments(含--reset-fake-merged/--max-duration标志) - configuration.md / deployment.md 补平台感知分段说明:≤2GB→30s,>2GB→最高 2m
- 删除 docs/zh/timelapse-dual-mode.md:引用未发布的 v2,且无英文对应版
- README 移除 AGENTS.md 死链(gitignored,公开用户看到死链);deployment.md 版本示例 v0.2.0 → v0.9.0;README Xiaomi 描述更新为"CS2 + legacy TUTK (7 models)";README.zh 补"即插即用自动发现"卖点
🔧 树莓派营销定位弱化
项目已从"树莓派专属 NVR"演进为"跨平台轻量 NVR"(x86 服务器 / Banana Pi / 群晖 NAS / 树莓派等都是目标平台)。README 头部把树莓派从"旗舰定位"降为"支持的低功耗 ARM 平台之一":
- badge:
Raspberry Pi→ 通用ARM - hero slogan:
Turn any Raspberry Pi...→Turn any low-power ARM device... - 卖点:
Raspberry Pi 3B Ready→Low-Power ARM Ready(RPi 3B 保留为括号里的验证基准) - docs/deployment.md 章节标题:
Running on Raspberry Pi→Running on ARM SBCs (e.g. Raspberry Pi)
技术约束文档(RPi 3B 作为最低端验证基准)全部保留。
⚠️ 已知问题(后续版本跟进)
- TUTK 摄像头反复重连(#68-7):根因已定位(我们的 TUTK worker 有 go2rtc 没有的 30s idle timeout),但修复涉及协议层改动,需真实 TUTK 设备验证环境,暂缓。临时可用 go2rtc 转推绕过。详情见 issue #68 回复
- 录像页进度条点击重载闪烁(#68-6):涉及播放器架构,已记录跟进
- 转推鉴权(#70-2):已记录跟进
📥 安装 / Install
# 一键安装
curl -fsSL https://raw.githubusercontent.com/Mi-Bee-Studio/MiBeeNvr/main/install.sh | sudo bash
# 或下载二进制(amd64 / arm64 / armv7)
# Docker
docker compose --project-directory . -f deploy/docker/docker-compose.yml up -dFull Changelog: v0.9.0...v0.9.1
English summary
v0.9.1 is a patch release focused on i18n completeness, recording-fragment governance, community-reported UX fixes, and a full public-docs accuracy audit. No breaking changes.
i18n (issue #68) — a systematic audit cross-referenced all t() calls against the dictionaries: fixed 19 keys referenced in code but missing from BOTH dictionaries (users saw raw keys), and wired the entire Push-Out config section (previously hardcoded English) to i18n. en/zh grew from 1341 → 1377 keys, parity verified 0 missing.
Recording fragments — platform-aware segment-duration cap (≤2GB RAM → 30s, >2GB → up to 2m; the MP4 muxer holds all samples in RAM until segment close, so available RAM bounds the safe max) + a periodic backfill sweep (rolling_backfill_interval / rolling_backfill_batch) so historical pending segments don't accumulate.
Community fixes (#64/#68/#70) — Xiaomi TUTK no longer blocked by the pre-add vendor gate; Docker custom-port docs (Synology 9090 conflict); Xiaomi credential fields hidden (uses cloud-account token, not per-camera user/pass); merge-config "use global default" now actually clears (was a COALESCE no-op); push-out URL copy-to-clipboard popover.
Docs audit — 9 CRITICAL + 3 MODERATE + 1 MINOR fixes (18 files, +664/-809): xiaomi two-way-audio description was reversed; timelapse "v2" framing + merge_duration misrepresentation removed; transcoding Prometheus metric names corrected; check-vendor example updated; xiaomi model identifiers aligned with code; repair merge-status/repair fragments documented; platform-aware segment_duration cap documented; dead AGENTS.md link removed; version examples bumped.
Known issues (deferred) — TUTK reconnect flapping (#68-7, root-caused, needs real-device validation); recording progress-bar flicker (#68-6); push-out auth (#70-2).