Frigate 快照(Snapshots)完全指南:最佳帧选取、按需渲染与保留策略
【免费下载链接】frigateNVR with realtime local object detection for IP cameras项目地址: https://gitcode.com/GitHub_Trending/fr/frigate
快照(Snapshot)是 Frigate 为每一个被追踪目标保存的一张"最佳瞬间"静态图片,它捕获的是目标穿越画面时最清晰的一帧。本文以官方配置文档docs/docs/configuration/snapshots.md为主线,结合 Frigate 源码(快照配置模型、目标跟踪与写入流程、最佳帧评分算法、事件快照 API)系统讲解快照的启用方式、全部配置项、帧选择机制、磁盘存储与请求时渲染模型,帮助你在部署中正确配置快照并理解其底层工作方式。
快照是什么
快照与录像(recordings)不同:录像是连续视频,而快照是每个被追踪目标在追踪结束后保存的一张代表性图片。简单说,Frigate 在跟踪某个目标的全过程中持续评估每一帧,选出"最清晰"的一帧,等目标离开画面(追踪结束)后再写入磁盘。
启用快照后,Frigate 会为每个被追踪对象在/media/frigate/clips目录保存一张名为<camera>-<id>-clean.webp的图片。其中-clean的含义是始终不带任何注释(没有时间戳、没有边框、没有裁剪),保证你拥有一份原始帧的未修改副本;而边框、时间戳等注释是在通过 HTTP API 请求快照时按需叠加的(见下文 渲染模型)。
需要记住的几点
- 快照按被追踪对象保存,因此即使录像开启,只要摄像头没有检测到任何对象,也不会产生快照;
- 快照与录像在配置与保留策略上是相互独立的,启用其中一项不会自动启用另一项;
- 快照可以在 UI 的 Explore 面板中查看,并支持一键提交到 Frigate+ 服务进行模型优化训练;
- 如果只想保存进入特定区域的对象的快照,请参考区域(Zones)文档中"restricting snapshots to specific zones"(限制快照到特定区域)一节;
- 通过 MQTT 发送的快照是独立的,需要到camera 的 MQTT 设置下单独配置,不属于本节
snapshots配置的范畴。
启用快照
快照默认是关闭的(源码中enabled的默认值为False)。可以全局启用,也可以针对单个摄像头覆盖默认设置。
全局启用(作用于所有摄像头)
- UI 方式:进入
Settings > Global configuration > Snapshots,将Enable snapshots打开; - YAML 方式:
snapshots: enabled: True为指定摄像头覆盖
- UI 方式:进入
Settings > Camera configuration > Snapshots选择对应摄像头,打开Enable snapshots; - YAML 方式:
cameras: front_door: snapshots: enabled: True在源码层,无论全局还是相机级,最终都落到同一个配置模型上。相机级的SnapshotsConfig会覆盖全局配置,Frigate 读取实际生效配置时始终以self.config.cameras[camera].snapshots为准(见 object_processing.py),这一机制同样支撑了配置 profile 对快照开关的动态切换(例如 runtime_state.py 中snapshots状态与 MQTT 的ON/OFF联动,参见 mqtt.py)。
快照选项详解
下列设置控制快照的渲染方式与存储方式,同时构成通过 API 请求快照时的默认渲染参数。
- UI 方式:进入
Settings > Global configuration > Snapshots,可配置字段如下:
| 字段 | 说明 |
|---|---|
| Enable snapshots | 启用或禁用为被追踪对象保存快照 |
| Timestamp overlay | 通过 API 获取快照时叠加时间戳 |
| Bounding box overlay | 通过 API 获取快照时为被追踪对象绘制检测边框 |
| Crop snapshot | 通过 API 获取快照时按检测框裁剪到对象区域 |
| Snapshot height | 快照缩放的目标高度(像素);留空表示保留原始尺寸 |
| Snapshot quality | 保存快照的编码质量(0-100) |
| Required zones | 对象必须进入的区域列表,否则不保存快照 |
- YAML 完整示例:
snapshots: enabled: True timestamp: False bounding_box: True crop: False height: 175 required_zones: [] quality: 60各选项在源码中的默认值与约束
以上 YAML 项与配置模型SnapshotsConfig一一对应,定义在 frigate/config/camera/snapshots.py:
| 配置项 | 类型 | 默认值 | 说明(取自源码描述) |
|---|---|---|---|
enabled | bool | False | 为所有摄像头启用/禁用保存快照,可在单个摄像头覆盖 |
timestamp | bool | False | 通过 API 返回的快照叠加时间戳 |
bounding_box | bool | True | 通过 API 返回的快照绘制检测边框 |
crop | bool | False | 通过 API 返回的快照裁剪到检测框 |
required_zones | list[str] | [] | 对象必须进入的区域,满足条件才保存快照 |
height | int | None | None | API 快照缩放高度(像素),None表示保留原尺寸 |
quality | int | 60 | 保存快照的编码质量(0-100),源码约束ge=0, le=100 |
retain | RetainConfig | 见下节 | 快照保留策略 |
注意bounding_box默认是True,而timestamp、crop默认都是False,且这些参数只影响"从 API 请求渲染"的结果——磁盘上的-clean.webp永远不带注释。
快照保留策略
快照在磁盘上的保留时长独立于录像。可以设置统一的默认保留天数,也可以为特定对象类型单独设置更长的保留天数。
- UI 方式:进入
Settings > Global configuration > Snapshots:
| 字段 | 说明 |
|---|---|
| Snapshot retention > Default retention | 快照保留天数(默认:10) |
| Snapshot retention > Object retention > Person | 按对象类型覆盖保留天数(例如让person快照保留 15 天) |
- YAML 示例:
snapshots: enabled: True retain: default: 10 objects: person: 15源码中RetainConfig定义于 frigate/config/camera/snapshots.py:default是浮点型天数,默认 10;objects是dict[str, float],即"对象标签 → 覆盖保留天数"的映射。磁盘上快照与事件缩略图都遵循各自目录的保留策略,Frigate 的清理任务会按这些天数定期淘汰过期文件(相关清理逻辑可见 frigate/events/cleanup.py 与 frigate/util/camera_cleanup.py,两者均参与-clean.webp快照文件的生命周期管理)。
帧选择:Frigate 如何选出"最佳帧"
Frigate不会保存每一帧,而是为每个被追踪对象挑选一张"最佳"帧,判定依据包括:
- 检测置信度(detection confidence):分数越高越好;
- 对象尺寸(object size):面积越大越好;
- 关键属性是否存在:例如人脸、车牌等对识别有价值的属性会显著加分;
- 是否触碰画面边缘:目标贴在画面边缘的帧会被降低优先级(deprioritized)。
当追踪结束时,这个最佳帧才被写入磁盘。也就是说,整个追踪过程是对帧的持续"评审",最终只落盘一次。
评分算法的源码级实现
帧的优劣由 frigate/util/image.py 中的is_better_thumbnail()函数决定,具体规则如下:
- 属性优先:遍历该对象类型配置的"非 logo 属性"(如人脸、车牌等,来自模型
attributes_map,见 tracked_object.py),若新帧出现了当前最佳帧没有的关键属性,直接判定为更优;若当前帧已具备某属性而新帧没有,则不更新(除非新帧在该属性上得分更高); - 边缘惩罚:如果新帧的目标框在画面边缘、而当前最佳帧不在边缘,则不更新;
- 分数显著提升:新帧得分比当前最佳帧高出 5% 以上(
new_obj["score"] > current_thumb["score"] + 0.05)则更新; - 面积显著变大:新帧的目标面积比当前最佳帧大 10% 以上(
new_obj["area"] > current_thumb["area"] * 1.1)则更新。
每一帧在 tracked_object.py 的update()流程中调用该函数,胜出的帧连同box、area、score、attributes、recognized_license_plate等信息被存入thumbnail_data,作为后续渲染快照的素材。
快照何时写入磁盘
当对象追踪结束时,跟踪流程(object_processing.py)会依次执行:
- 重新计算
has_snapshot(调用should_save_snapshot); - 若需要快照或录像,先写事件缩略图(
write_thumbnail_to_disk); - 若需要快照,再调用
write_snapshot_to_disk()将 clean 图写入磁盘。
其中should_save_snapshot()(object_processing.py)的判定条件非常关键:
- 目标是误检(
false_positive)→ 不保存; - 摄像头快照未启用 → 不保存;
- 目标从未改变过位置(
position_changes == 0)→ 不保存(静止/误检目标不会产生快照); - 配置了
required_zones且目标从未进入这些区域 → 不保存; - 全部通过 → 保存。
实际写盘动作write_snapshot_to_disk()位于 tracked_object.py:它调用get_clean_webp(),以timestamp=False, bounding_box=False, crop=False, height=None且quality取自camera_config.snapshots.quality的参数渲染 WebP 图片,然后写入/media/frigate/clips/<camera>-<id>-clean.webp。事件缩略图(用于 UI 列表)则单独写入缩略图目录THUMB_DIR/<camera>/<id>.webp,其固定按 175px 高度裁剪渲染(见 tracked_object.py 的get_thumbnail()),与磁盘上的 clean 快照用途不同。
渲染模型:请求时叠加注释
Frigate 在磁盘上只保存一张不带注释的 clean 快照,所有注释(时间戳、边框、裁剪)都在请求发生时即时渲染。这保证了同一份原始素材可以被不同用途重复使用而互不影响。
| API / 用途 | 结果 |
|---|---|
| 磁盘存储文件 | <camera>-<id>-clean.webp,始终无注释 |
/api/events/<id>/snapshot.jpg | 以摄像头的snapshots默认配置为起点,在请求时叠加查询参数覆盖后渲染输出 |
/api/events/<id>/snapshot-clean.webp | 返回磁盘上同一张快照,不带任何注释 |
| Frigate+ 提交(即 Frigate+ 首个模型) | 使用同一张磁盘上的 clean 快照 |
渲染流程在get_img_bytes()(tracked_object.py)中实现:先从帧缓存取出thumbnail_data["frame_time"]对应的 YUV 帧并转换为 BGR,随后将timestamp、bounding_box、crop、height、quality、对象标签、检测框、得分、属性、时间戳样式等参数一并交给get_snapshot_bytes()完成注释绘制与编码。因此snapshot.jpg端点天然支持时间戳、边框、裁剪、高度、质量等渲染参数的按请求覆盖。
这几个事件快照端点(/events/{event_id}/snapshot.jpg与/events/{event_id}/snapshot-clean.webp)在 frigate/api/media.py 与 frigate/api/media.py 中定义;媒体访问遵循 Frigate 的认证与授权体系(可参考 API 集成文档 了解认证方式)。此外还有一个"按对象实时请求"的端点/{camera_name}/{label}/snapshot.jpg(media.py),通常与 MQTT 探测配合使用。
完整渲染链路速览
检测帧 → update() 中用 is_better_thumbnail() 评选最佳帧 → thumbnail_data 记录该帧元数据 │ ├─ 追踪结束 → should_save_snapshot() 判定 → write_snapshot_to_disk() │ └─ get_clean_webp() 以无注释参数编码 → /media/frigate/clips/<camera>-<id>-clean.webp │ └─ API 请求 /api/events/<id>/snapshot.jpg └─ get_img_bytes() 按请求参数叠加时间戳/边框/裁剪/高度/质量MQTT 快照与事件快照的差异
MQTT 快照是独立于本节snapshots配置体系的另一套机制,需要特别区分:
- MQTT 快照发布更频繁:每次在追踪过程中发现更好的缩略图帧,或当前最佳图片早于
best_image_timeout(默认 60 秒)时,就会向{camera}/{label}/snapshot主题推送一张新的 JPEG 快照(见 object_processing.py 的snapshot()回调,MQTT 开关同样受required_zones约束,参见同文件should_mqtt_snapshot()); - MQTT 快照使用摄像头 MQTT 设置下的独立注释与渲染参数(
timestamp、bounding_box、crop、height、quality),与全局snapshots设置无关; - 事件快照是追踪结束时在磁盘落盘一张 clean WebP,与 MQTT 按帧发布的 JPEG 是两套产物,互不影响。
换言之:snapshots配置只决定"磁盘上会不会有一张 clean 快照以及 API 请求时默认怎么渲染",而 MQTT 通知里的抓拍请到摄像头的 MQTT 配置项中调整。
快照与区域(Zones)的联动
required_zones与 MQTT 的required_zones在源码中是两套独立判定(object_processing.py 与 object_processing.py),逻辑一致:只要配置了必入区域,目标就必须进入过其中至少一个区域(set(obj.entered_zones) & set(required_zones)非空)才会保存/推送快照。区域定义本身及更精细的对象过滤见区域(Zones)文档。
常见误区小结
- 快照 ≠ 视频:快照按对象存单张图,录像按时间存片段;两者独立启用、独立保留;
- 磁盘文件始终是 clean 图:界面上看到的带框/带时间戳快照是 API 渲染产物,不是磁盘原样;
- 没有检测到移动对象就没有快照:从未移动的目标(
position_changes == 0)不会保存快照; - MQTT 快照走 camera 的 MQTT 配置:改全局
snapshots不会影响 MQTT 通知抓拍。
通过合理组合required_zones、retain.objects、按对象的区域过滤以及 API 请求时的渲染参数,可以在几乎不占用额外计算与存储的前提下,把 Frigate 快照用于门禁记录、区域入侵取证、人脸/车牌样本收集与 Frigate+ 模型优化等场景。
相关源码文件索引
- 配置模型与默认值:frigate/config/camera/snapshots.py
- 快照保存判定与写盘时序:frigate/track/object_processing.py、object_processing.py
- 最佳帧评选算法:frigate/util/image.py
- 帧记录、渲染与写盘实现:frigate/track/tracked_object.py、tracked_object.py
- 快照/clean 图 API 端点:frigate/api/media.py、media.py
- 清理任务参与快照生命周期:frigate/events/cleanup.py、frigate/util/camera_cleanup.py
【免费下载链接】frigateNVR with realtime local object detection for IP cameras项目地址: https://gitcode.com/GitHub_Trending/fr/frigate
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考