别把宠物摄像头只当告警器:用 pet-report 在本地把 Frigate 事件变成可复核的每日记录
家里已有 Frigate 摄像头时,常见的体验是:移动侦测和对象识别已经能产生大量事件,但信息仍碎成一段段通知。看到「检测到猫」以后,主人还得打开片段、判断是不是同一只、回忆今天是否喝水、有没有比平时更少活动。若把这些原始事件直接交给云端多模态服务,又会把室内影像和日常习惯交给第三方。
pet-report 提供了一个很有代表性的本地 AI 工作流:它不取代 Frigate,也不直接控制摄像头;它读取 Frigate 已经产生的事件、快照、视频片段与音频标签,调用局域网中的视觉语言模型,把结果写入 SQLite,并在 Web 界面中提供按天汇总、时间线和可追溯的证据。项目采用 AGPL-3.0 许可证,当前仓库以 Haskell 为后端实现,并提供 NixOS、Docker 与手动部署路径。
这不是「让模型替你诊断宠物健康」的产品。它真正值得借鉴的地方是:把模型输出降级为可检查的观察记录,而不是不可质疑的结论。
从摄像头事件到每日记录:中间多了一层可复核的数据模型
pet-report 的数据流可以概括为:
摄像头 → Frigate → pet-report → SQLite → Web 界面
↕
本地视觉语言模型
Frigate 负责它擅长的事情:汇聚摄像头、检测对象并保留事件素材。pet-report 则按批次处理新的标记事件:将帧图像和相关片段发给视觉模型,获得结构化的「看见了什么、在做什么」观察,再写入每只宠物的记录、统计和当天摘要。项目 README 说明默认是每天两次批处理;这意味着它的取舍是接受较高延迟,以换取本地运行和较低的持续算力压力,而不是追求实时视频理解。
这种分层有两个工程好处。第一,Frigate 的保留策略和对象检测仍是唯一的摄像头入口,AI 应用不需要重新接入 RTSP 流,也不会变成另一个 NVR。第二,模型的每个描述都可以回到对应片段验证:时间线中的事件附带其来源素材,用户可以更正模型读数,系统会保留原始读数,并据更正后的记录重建统计与当天摘要。
对于本地 AI 系统,这种「模型结果 + 原始证据」的组合比单独生成一段自然语言日报更可靠。模型可以帮助筛选和归纳,但不应成为唯一事实来源。
部署前先确认三项依赖,而不是先选模型
项目明确依赖三部分:运行中的 Frigate、一个本地的 OpenAI 兼容视觉模型端点,以及 pet-report 自身。视觉端点可以由 llama.cpp、llama-swap 等提供;README 同时提示,项目使用了 llama.cpp 的 JSON Schema response_format、reasoning_content 与 chat_template_kwargs 等扩展,因此「形式上兼容 OpenAI API」的服务不一定完整支持已测试的路径。
先把这三项边界确认清楚:
- Frigate 是事件与素材来源。 pet-report 不直接连接摄像头;需要先让 Frigate 正常产生宠物相关事件。
- 模型是辅助观察者。 较大的视觉模型通常更能处理暗光、遮挡和复杂画面;较小模型则更快、更省资源,但误判更多。
- 存储要分开看。 SQLite 中的日报和统计是长期记录;未被保留的图片与片段则会受 pet-report 的保留窗口和 Frigate 自己的保留策略共同限制。
特别是多宠物家庭,不能把「识别到一只猫」误解为可靠的个体识别。项目当前按物种处理:只有某个物种恰好对应一只活跃宠物时,事件才会自动映射到名字;两只猫的场景仍需要人从时间线中确认个体。它没有使用人脸式的重识别模型,纠正某次记录也不会训练模型或自动影响下一次识别。
用 Docker 接入现有主机服务
如果 Frigate 和模型服务器已经运行在 Docker 宿主机上,可以按项目 README 的方式构建镜像并映射数据卷。下面把模型名、时区改成环境变量,避免把机器相关信息写死在命令里:
docker build -t pet-report .
docker run -d --name pet-report \
-p 8115:8115 \
-v pet-report-data:/data \
--add-host host.docker.internal:host-gateway \
-e FRIGATE_URL=http://host.docker.internal:8114 \
-e LLAMA_SWAP_URL=http://host.docker.internal:8080 \
-e VISION_MODEL="${VISION_MODEL}" \
-e PET_REPORT_TZ="${PET_REPORT_TZ}" \
pet-report:latest
容器启动后,界面位于 http://localhost:8115,首次访问会进入引导设置。/data 卷保存 SQLite、待处理帧、证据帧及保留的媒体;它应进入备份计划,否则重建容器时会丢失本地记录。
这里最容易踩的网络坑是地址选择。host.docker.internal 与 --add-host ...:host-gateway 是「Frigate 和模型在宿主机」的方案;若三者都是容器,应把它们放入同一个 Docker 网络,改用服务名和容器内部端口,例如 FRIGATE_URL=http://frigate:5000,同时移除 --add-host。不要混用两种拓扑,否则很可能出现容器内访问不到宿主机服务的问题。
配置不是一堆环境变量:区分基础设施与家庭语义
容器能启动不代表系统已经具备有意义的输出。pet-report 将两类信息刻意分开:FRIGATE_URL、LLAMA_SWAP_URL、VISION_MODEL、监听地址与时区等属于基础设施配置;宠物名单、区分线索、关注的日常行为和报告偏好则由首次进入界面时的引导设置写入应用状态。这样的拆分避免了把会随家庭变化的资料散落在 Compose 文件中,也让迁移时能单独备份数据卷。
模型配置还应以「能复现失败」为目标。先选择一个固定模型名和固定模型服务地址,保留原始事件与模型观察的关联;遇到暗光、逆光或宠物重叠时,才能比较是相机位置、事件素材还是模型能力造成问题。项目把不确定事件放到人工复核路径,正是因为视觉模型的置信感不等于事实可靠性。不要为了让日报看起来完整而把未观察到的行为补写成推断结论。
运行一段时间后,重点监控的也不是模型回答是否优美,而是三个操作性信号:Frigate 是否持续提供事件、批处理是否按预期完成、/data 所在卷是否有足够空间。保留的片段会占据更多空间,未保留素材则会随着保留窗口和 Frigate 的策略消失。把 SQLite 与保留媒体一起纳入备份,并在恢复演练中验证数据卷可被新容器读取,才算真正拥有可持续的本地记录。
报告不是医疗结论:把失败模式设计进使用流程
宠物影像尤其容易让人对自然语言摘要产生过度信任。README 对边界的描述很明确:暗处可能漏检,模型可能混淆物种或臆测活动;饮水、进食和猫砂使用难以仅凭镜头完整观察;统计是「摄像头看见的次数与比例」,不是凭空推导出的持续时间。因此「没有观察到饮水」只能表示未在可见画面中记录到,不能表示宠物没有喝水。
比较稳妥的使用方式是把它放进一个人工复核闭环:每天先读摘要,再查看被标记为不确定的片段;发现错误时在时间线修正;真正异常仍以人的观察与兽医建议为准。这样,AI 的价值不是替代判断,而是把成百上千条事件压缩成少量值得查看的证据。
安全边界也不能忽略。pet-report 的后端默认只监听回环地址,由 nginx 暴露界面;项目没有登录和逐请求认证。README 建议只在受信任 LAN 或 VPN 中使用,或在前面加带认证的反向代理,明确不应直接做公网端口转发。对保存家庭影像的服务而言,这比多一个方便的公网访问入口重要得多。
适合谁,以及不适合谁
这个项目适合已经部署 Frigate、愿意维护本地模型服务,并希望把「告警流」升级为「可回看记录」的家庭实验者。它也提供了一个可迁移到其他本地视觉场景的设计范式:事件系统负责采集,模型负责批量结构化,SQLite 保存可查询记录,界面把每个结论链接回原始证据。
反过来,若没有现成的 Frigate、只想要即开即用的云服务,或者需要可靠的多宠物身份识别与医学级告警,pet-report 并不合适。它要求本地基础设施、模型推理资源和人工复核;这些成本恰好也是它换取隐私控制权与可验证性的代价。