MIAO / 实际部署学习笔记 / 2026.10.15

从喂食器的私有视频
到 NAS 上的三天录像

目标:让慕斯喂食器直接向 NAS 提供画面,在 Frigate 中以 miao 命名,连续录像保留 3 天。电脑和手机都不参与最终运行链路。

1080p · H.265

原始视频,约 15 fps

3 天

连续录像保留配置

手机可离线

NAS 自行连接设备并录像

01 / 每一层负责什么?

喂食器摄像头压缩视频
私有 TUTK / UDP
→
miao-native认证、接收、重组
输出 H.265 码流
→
桥接 go2rtc将视频封装成 RTSP
容器 miao-bridge
→
Frigate转发、预览、录像
管理保存期限

最终部署中,桥接容器与 Frigate 通过同一个 Docker 网络通信。Frigate 自带的 go2rtc 再统一转发 miao,便于内部消费。图中将这层内部转发归入 Frigate。

02 / 为什么不能直接填摄像头地址?

本次检查没有发现设备开放常见 HTTP / RTSP TCP 服务。设备通过 TUTK 私有协议提供视频,因此需要先做一层协议适配。已验证的路径是经现有 VPN 路由直连设备的 UDP 服务。

概念在这次部署中的含义
H.265 / HEVC视频压缩格式,决定如何还原画面;不是访问地址。
TUTK / UDP设备侧会话与视频传输方式,需要认证、分包接收和帧重组。
RTSP让 Frigate 等标准客户端订阅视频的接口;实际视频以 RTP 等方式传输。
MP4 录像把压缩视频放进便于保存和回放的文件容器,通常无需重新编码。

花屏和时间不动,最后是怎么解决的?

① 帧边界:相差 8 字节就可能破坏视频

通用实现按 32 字节附加信息分割,而这台设备采用 24 字节格式。适配程序按设备格式取回原本被截走的最后 8 字节视频数据。压缩视频对字节完整性敏感,错误切分会导致花屏、参考帧缺失。

② UDP 乱序:包到了,但到达次序不一定正确

接收缓冲调整为 4 MiB,乱序窗口从 5 包扩到 64 包,给网络抖动留出重排空间。它能改善短暂乱序和突发拥堵;真正丢失的数据仍可能损伤当前帧。

③ 关键帧:重新连接后不能从任意位置开始解码

H.265 的很多帧依赖前面的参考画面。程序在启动和重连后等待关键帧,再输出可解码的视频。连续 8 秒没有视频帧会重新连接,失败后间隔 1 秒重试。

④ 标准输出:视频管道里不能混入日志文字

原生程序把视频写到 stdout,把错误信息写到 stderr。若调试文本混入视频字节流,下游解码器也可能报错。

验证结果:修正后,60 秒测试收到并解码 895 帧,缺失参考帧错误为 0。静态场景中的画面时间也持续更新,因此不是“只有物体移动才更新”。这是一段验收测试,不等于已证明无限期无中断。

03 / CPU、核显和 AI 分别做什么?

CPU:接收与搬运

处理认证、UDP 包、帧重组、RTSP 封装以及文件索引。桥接服务不解码整幅图像,负担较轻。

部署快照:桥接约 36 MiB 内存,Docker CPU 约 1.38%(约 0.014 个核心),并非长期平均值。

Intel 核显:视频解码

NAS 的 UHD 770 使用 i915 驱动,Frigate 已映射 renderD128,并为 miao 配置 QSV H.265 硬解。预览处理为 640×360、3 fps。

GPU 的媒体解码单元与普通 3D 渲染用途不同。

AI:目前没有启用

miao 没有开启物体识别、运动检测或截图。原有摄像头的 OpenVINO GPU 检测设置保留,不代表 miao 在做推理。

未来开启猫、人等识别时,才会新增相应推理负载。

录像为什么省资源?

喂食器已经完成 H.265 编码。录像支路复制压缩视频并封装落盘,保持原始 1080p、约 15 fps;不必解码后再次压缩。预览支路才需要解码与缩放。

这次没有测量插座功率,因此不能把 CPU / GPU 占用直接换算成新增多少瓦。持续写盘、硬盘是否因此无法休眠,也会影响整机功耗。

04 / 三天录像到底占多少空间?

空间主要由平均码率 × 时间决定,不由“1080p”单独决定。下面是纯视频近似值,未计索引、容器开销和文件系统余量。

公式:kbps × 1000 ÷ 8 × 86400 × 3 ÷ 10⁹ = 三天的十进制 GB。210 kbps 来自短时间静态场景样本;运动、夜视噪点等会改变码率,不能当作容量保证。

为什么多个地方都写 3 天?

现有 Frigate 的全局保留时间更长。miao 显式覆盖连续、运动、告警与检测相关保留字段,避免继承长周期设置。当前 AI 与运动检测关闭,其中部分字段属于预先约束。

# 这是 miao 相机内部的配置片段,不是完整 config.yml
record:
  enabled: true
  continuous:
    days: 3
  motion:
    days: 3
  alerts:
    retain:
      days: 3
  detections:
    retain:
      days: 3

部署时录像盘约 99% 已使用,剩余约 41 GB。三天是保留策略配置;磁盘不足时 Frigate 可能提前清理旧录像。这些容量数字是部署快照,不是实时读数。

05 / 为什么单独放一个桥接容器?

实际安装的 Frigate 默认禁止任意 exec 视频源。直接把原生取流命令写进其 go2rtc 配置会被过滤。因此将固定的取流程序放在独立的 miao-bridge 中,再给 Frigate 一个标准 RTSP 地址。

桥接容器内部:miao-native → go2rtc → :8554/miao
Frigate 的视频源:rtsp://miao-bridge:8554/miao
Frigate 内部转发:rtsp://127.0.0.1:8554/miao

容器采用只读文件系统、移除全部 capabilities、256 MiB 内存上限以及 unless-stopped 自动重启策略。没有映射新的宿主机端口,管理 API 与 WebRTC 监听关闭。内部 RTSP 没有认证,同一 Docker 网络内的其他容器也能访问。

文件或操作用途
/vol1/docker/appdata/frigate/config.ymlFrigate 主配置
/vol1/docker/appdata/frigate/miao/桥接配置、程序、Compose、源码与私有凭据
docker restart miao-bridge通过 NAS SSH 单独重启取流桥接
backups/config.before-miao-20261015-103308.yml位于 Frigate 配置目录内的原配置备份

没有画面时,按依赖顺序查

  1. NAS 是否能经 VPN 路由到达喂食器;设备地址或 UDP 端口是否改变。
  2. miao-bridge 是否运行,原生程序是否取得视频;认证失败与网络中断分开判断。
  3. RTSP 是否实际输出 H.265 视频,而不只是端口能连接。
  4. Frigate 的 miao 是否持续收到帧;再看核显解码和预览。
  5. 录像文件是否持续生成、数据库是否索引、网页是否可回放。

当前容器健康检查只测试 RTSP 端口监听。healthy 不能单独证明视频正常;部署验收还检查了真实画面、录像落盘及数据库索引。

06 / 已证明的事,与还没有证明的事

已验证尚未作为结论
手机 App 停止后仍可独立取流;NAS 已直接接入。设备彻底断开互联网后是否仍能长期运行,未做隔离验证。
生产实时画面正常,录像已落盘并索引;验收末尾记录到 21 段。连续运行数天的稳定性、真实 3 天清理周期,尚未经过相应时间验证。
H.265 1080p 约 15 fps;QSV 硬解配置及实际画面已检查。没有插座功率实测;短时负载与码率不是长期保证。

最终运行只需要喂食器、必要的网络 / VPN 路径、NAS 和存储。手机曾帮助获取自有设备连接参数;电脑曾用于研究和测试,它们现在都不是运行依赖。

依据:本次项目《使用说明.md》及 nas_config.py 的实际部署配置。此页面是可离线阅读的静态学习资料,不连接摄像头、不加载远程资源,也不包含设备密码、密钥或私有视频。部署状态以 NAS 当前实际运行情况为准。

上游实现参考:go2rtc / pkg/tutk。此处链接供继续阅读,本页原理说明依据本次实测与项目资料。