在 Debian 服务器(Intel N97)上部署 Frigate NVR,替代传统 NVR 的检测功能。 涵盖 Docker Compose、go2rtc 流配置、硬件加速、HA 集成、推送通知及基于区域的告警。 VLAN 间流量经由主路由器(UCG Ultra)转发。
硬件与背景#
- 服务器: Intel N97 迷你主机(
debian.lan,10.0.10.11),Debian 13 - 摄像头: 8 台 Reolink PoE 摄像头(摄像头 VLAN,
10.0.40.0/24),2 台 Nanit 婴儿监控器(IoT VLAN,10.0.20.0/24) - 现有 NVR: 保留运行,负责持续录像;Frigate 专注于检测和事件片段
- Home Assistant: 位于 IoT VLAN(
10.0.20.10),已运行 MQTT Broker
存储设计#
录像存储在 NAS 专用共享目录,避免占用本地 NVMe。
在 Synology DSM 中:创建共享文件夹 surveillance,NFS 导出给 10.0.10.11,
权限选择 Map all users to admin(将所有 UID 映射为 admin),
避免 Frigate 容器 UID(1001)在 NAS 上找不到对应用户的问题。
在 debian 上挂载:
| |
添加到 /etc/fstab:
| |
Docker Compose#
| |
| |
密码通过环境变量注入,在 config.yml 中以 {FRIGATE_VARIABLE_NAME} 引用,
避免明文写入配置文件。
shm_size: 256mb — 帧缓冲的共享内存。8 路摄像头 5fps 检测流约需 20–30 MB,
256 MB 留有充足余量。
/dev/dri/renderD128 — Intel 核显,用于 VAAPI 硬件解码。
无需 privileged: true,直接传递设备即可。
config.yml#
MQTT 与硬件加速#
| |
ffmpeg 与检测器加速的区别: preset-vaapi 负责视频解码(H.264/H.265 → 原始帧),使用 Intel 核显的媒体引擎。OpenVINO 检测器负责推理(运行目标检测模型),使用核显的 EU 计算单元。两者共用同一块 N97 核显,但使用不同的硬件模块,互不干扰。
为什么选 OpenVINO 而非 CPU? N97 原生支持 OpenVINO,GPU 推理比 CPU 快 3–5 倍,无需额外硬件。模型(ssdlite_mobilenet_v2)完全相同,只是换了执行后端。
model: 必须放在顶层。 这是全局配置块,不能嵌套在 detectors 下面。如果把 path 写在 detectors.ov.model 内,Frigate 会读到 None 路径并在启动时崩溃。
MQTT host 填 HA 的 IP(10.0.20.10),流量经 UCG Ultra 路由转发。
录像策略#
| |
顶层没有 retain.days,意味着不做持续录像,只保存事件片段。
现有 NVR 负责 24/7 全程录像,Frigate 保存带标签的短片段,两者互补。
go2rtc 流配置——常见错误#
Frigate 内置 go2rtc 管理视频流。每台摄像头需要两个命名流: 主流(高分辨率,用于录像)和子流(低分辨率,用于检测)。 关键错误:
错误写法 — 主流和子流写在同一个流名下:
| |
go2rtc 将多个源视为备用关系,只选其中一个。
后续引用 front_sub 会返回 404。
正确写法 — 分别命名:
| |
摄像头配置中分别引用:
| |
Reolink RTSP 地址格式#
标准 Reolink 摄像头:
- 主流:
rtsp://admin:pass@IP:554/h264Preview_01_main - 子流:
rtsp://admin:pass@IP:554/h264Preview_01_sub
较新型号(如 CX810)使用 H.265:
rtsp://admin:pass@IP:554/h265Preview_01_main
Reolink Duo 有两个镜头,路径为 Preview_01 和 Preview_02。
实际使用中只有一个镜头有效,当作单摄像头处理即可。
摄像头配置#
| |
detect.enabled: true 必须显式写明。 Frigate 0.17 中默认为 false。
启动时如果视频流连接失败,Frigate 会自动禁用检测,且流恢复后不会自动重启。
务必在每台摄像头配置中显式设置。
width/height 必须与子流实际分辨率匹配。 Frigate 在送入检测模型前会将帧缩放到该分辨率。如果不匹配,画面会被拉伸,导致目标形状变形,检测准确度下降——对远距离或小目标尤其明显。用 ffprobe 探测子流实际分辨率:
| |
我的摄像头子流分辨率:
| 摄像头 | 子流分辨率 | 备注 |
|---|---|---|
| Reolink 标准型(front、backyard、side_a/b、cx810) | 640×360 | 16:9 |
| Reolink E1 | 640×360 | PTZ,不设 zone |
| Reolink 门铃 | 480×640 | 竖屏——宽高互换 |
| Reolink Duo(duo_a) | 1536×576 | 超宽 8:3;检测配置为 1280×480 |
检测参数调优#
默认阈值:min_score: 0.5,threshold: 0.7。
threshold 是跟踪窗口内的置信度滑动平均值——间歇性低置信度检测可能达不到该阈值。
对于广角或远距摄像头,降低阈值、提高检测分辨率有明显效果:
| |
区域与告警#
Frigate 0.17 将事件分为 alerts(告警) 和 detections(检测) 两类。 默认情况下,画面任何位置的 person 和 car 均触发告警。区域配置可限制这一行为。
工作原理#
- 区域多边形在 Frigate UI 中绘制(可视化编辑器),自动写入
config.yml - 区域的
objects列表限定哪些类别可激活该区域 loitering_time要求目标在区域内停留 N 秒后才触发required_zones写在review.alerts下,控制哪些事件升级为告警
required_zones 的正确位置:
| |
required_zones 放在 cameras.<name>.review.alerts 下——
不是 objects.filters 下(该位置不存在此键,会导致配置报错)。
效果#
| 事件 | 结果 |
|---|---|
| 车辆路过 | 仅检测,不告警 |
| 车辆在区域内停留 3 分钟以上 | 触发告警 |
| 行人路过 | 仅检测,不告警 |
| 行人在区域内停留 30 秒以上 | 触发告警 |
Home Assistant 集成#
Frigate 集成#
在 HA 中:设置 → 集成 → 添加 → Frigate
填写 Frigate 的主 LAN 地址:http://10.0.10.11:5000
推送通知#
通过 HA 自动化实现带截图的推送通知:
| |
为什么用 type == 'new' 而不是 type == 'end'?
end 触发时可以提供完整视频片段,但通知会延迟——
且如果人一直停留在画面中,end 永远不会触发。
new 立即触发;延迟 2 秒等待 Frigate 生成首帧截图。
截图 URL 使用 Frigate 的 LAN 地址(10.0.10.11),流量经主路由转发。
点击跳转 URL 使用 Tailscale 域名,支持远程访问。
踩坑总结#
go2rtc 流名称必须按分辨率分别命名。 主流和子流写在同一个名称下, 子流通过 go2rtc RTSP 服务器访问时返回 404。
Frigate 0.17 中
detect.enabled默认为 false。 必须在每台摄像头配置 中显式声明。启动时流连接失败会导致检测被自动禁用,且不会自动恢复。required_zones放在review.alerts下,不是objects.filters。 放错位置会导致配置校验报错。部分摄像头默认关闭 RTSP。 较新的 Reolink 型号(如 CX810)需要在 摄像头 Web 界面手动开启 RTSP,端口 554
connection refused即为此症状。H.265 摄像头使用不同的 RTSP 路径。 需将
h264Preview_01_main改为h265Preview_01_main。实时画面和检测是相互独立的。 浏览器通过 WebRTC 直接从 go2rtc 获取视频, 即使检测功能异常,实时画面仍然正常显示。能看到直播流不代表检测在运行。
HA↔Frigate 流量经主路由转发。 需确保 UCG Ultra 防火墙允许 IoT VLAN → 主 LAN 的 5000 和 1935 端口通行。