From c9354ed1a1fd6df2ff1dc05a40614cded6ad78d8 Mon Sep 17 00:00:00 2001 From: ericwyuan Date: Fri, 28 Aug 2026 12:10:14 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=90=8C=E6=AD=A5=208/28=20=E8=BF=81?= =?UTF-8?q?=E7=A7=BB=E6=95=85=E9=9A=9C=E6=8E=92=E6=9F=A5=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=EF=BC=88FFmpeg=20=E7=BC=BA=E5=A4=B1=20+=20=E7=A3=81=E7=9B=98?= =?UTF-8?q?=E5=86=99=E6=BB=A1=E6=AD=BB=E5=BE=AA=E7=8E=AF=20+=20DiskGuard?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit README.md 新增 Disk-Guard 模块表条目、修正一处遗漏的机器规格描述 (2C12G -> 4C23G)、当前进度补充这次完整排查记录;PROGRESS.md 服务运行 状态表更新 + 新增详细的故障排查时间线记录。 Co-Authored-By: Claude Sonnet 5 --- PROGRESS.md | 17 ++++++++++++++--- README.md | 6 ++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/PROGRESS.md b/PROGRESS.md index b2f6d56..dac90ed 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -1,17 +1,28 @@ # 项目进度追踪 -> 最后更新: 2026-08-24 +> 最后更新: 2026-08-28 ## 服务运行状态 | 服务 | 节点 | 地址 | 状态 | 验证结果 | |------|------|------|------|---------| -| FAM-Core | NAS | 0.0.0.0:8000 | ✅ 运行中 | health=ok, gunicorn 单 worker;Oracle-Sync + MotionNotifier 轮询 SS 事件推送(游标 DB 续用/失败重试);已部署事件时间轴删除功能 | -| FAM-Edge | Oracle | 0.0.0.0:5000 | ✅ 运行中 | systemd 守护(fam-edge.service);素材→运动片段分割→只分析片段;问答改为转发 AI-Gateway;队列消费正常;已部署 `/api/oracle/video/delete` | +| FAM-Core | NAS | 0.0.0.0:8000 | ✅ 运行中 | health=ok, gunicorn 单 worker;Oracle-Sync + MotionNotifier 轮询 SS 事件推送(游标 DB 续用/失败重试);已部署事件时间轴删除功能;`/api/status`/`/api/ss/status` 500 bug 已修复 | +| FAM-Edge | Oracle(新机 129.146.26.249) | 0.0.0.0:5000 | ✅ 运行中 | systemd 守护(fam-edge.service);素材→运动片段分割→只分析片段;问答改为转发 AI-Gateway;队列消费正常;已部署 `/api/oracle/video/delete`;FFmpeg 已补装;新增 DiskGuard 磁盘守护 | | **AI-Gateway** | Oracle | 0.0.0.0:5100 | ✅ 运行中 | systemd 守护(ai-gateway.service),2026-08-23 新增;独立仓库/独立部署;`/health` 正常,端到端问答实测成功(provider=nvidia) | | MariaDB | NAS | 127.0.0.1:3306 | ✅ 运行中 | 10.11.11, 6 张表, utf8mb4 | | Ollama | Oracle | 127.0.0.1:11434 | ✅ 运行中 | qwen2.5:7b,仅智能问答兜底(不参与视觉/融合);**被 AI-Gateway 调用,不再被 FAM-Edge 直接调用** | +## 2026-08-28 Oracle 迁移故障排查:FFmpeg 缺失 + 磁盘写满死循环 + DiskGuard + +- **触发**:用户反馈事件时间轴历史图片丢失、"谷歌同步是不是有问题"。逐层排查,发现的是三个叠在一起的独立问题,不是一个: + 1. **8/25 迁移新机器时漏装 FFmpeg**:`ffprobe: command not found`。导致 `videos.duration_sec` 全部读成 0、运动片段分割 `_segment_motion_clips` 全部失败(`ffmpeg` 也没装),190 个素材全部"分割 0 段",`events` 表完全是空的,`motion_clips/` 目录空的——事件时间轴从 8/25 起就没有任何新内容,图片自然也生成不出来。**已修复**:`apt-get install ffmpeg`,恢复正常。 + 2. **8/25 之前的历史图片无法找回**:迁移时只搬了 `data/oracle.db`(数据库/文字记录),没有搬 `motion_clips/`(磁盘上的运动片段视频文件,缩略图的生成源);旧机器(129.146.203.203)已经释放销毁。历史事件的文字描述还在(早就同步进了 NAS 镜像),但配图永久丢失,无法找回。 + 3. **Oracle↔Google Drive 同步"只下载不删除"**:排查一度走了弯路(先怀疑 NAS CloudSync 停摆,后发现新文件其实一直在下载,是判断证据不足导致的误判)。最终精确对比 Google Drive 远端(141 文件,最早 8/25)vs Oracle 本地(264 文件,最早 8/15)实锤:148 个文件是"远端已删、本地未删"的孤儿文件。根因是磁盘被写满到 100%(`no space left on device`),触发 rclone 内置安全机制——同步过程中遇到 IO 错误就整体拒绝执行删除,形成"越满删不掉,删不掉越满"的死循环。**已修复**:手动删除 148 个孤儿文件,释放 41G,磁盘 100%→59%;重新跑 `rclone_sync.sh` 验证 `exit=0` 无错误,下载+删除恢复正常。 +- **新增 DiskGuard 磁盘守护**(commit `ef56ae5`,永久性预防措施):`fam-edge/oracle_db.py` 新增 `get_oldest_purgeable_material()`(只挑最旧的、已完成分割阶段的整段素材,绝不碰运动片段和处理中的素材);`disk_guard.py` 新增后台线程,5 分钟检查一次,剩余空间 <10GB 触发清理,删到 15GB 水位为止;`/api/oracle/activity` 新增 `disk` 字段(实时剩余空间 + 最近清理动作)。9 个新测试,fam-edge 全量 139/139 通过。 +- **用户决策**:8/25-28 期间因 FFmpeg 缺失而"分割 0 段"的 190 个素材/736 个运动事件,明确选择不重新处理,翻页接受这段时间的空白。 +- **顺带修复**(commit `09708bd`):`/api/status`、`/api/ss/status` 500——上次"移除 SS Webhook"重构(`cf3d145`)删了 `MotionNotifier` 的 `camera_name_to_id` 等属性但 `status()` 忘记同步更新,导致这两个端点自那次重构起就一直是坏的。 +- **文档同步**(commit `3ec79de`):README 里 5 处 + `vite.config.js` 1 处仍描述"`/api/ss/webhook` 保留为可选"的过时内容,实际已被彻底删除,逐处订正。 + ## 2026-08-24 事件时间轴支持删除视频会话 - **决策**:用户要求事件时间轴能删除某个视频会话;调研确认项目里没有任何 delete 类端点先例,且增量同步(`get_sync_delta`)只做 upsert 感知不到 Oracle 端的物理删除,NAS 镜像必须显式清理,不能靠 `trigger_now()` 拉增量。用户明确要求连同磁盘上的视频文件一起删除,明确选择不做"防止误删事件被重新分割"的额外保护机制(风险极低:素材一旦标记 done 就不会被生产者重新捡起) diff --git a/README.md b/README.md index d041ee5..30b8e6d 100644 --- a/README.md +++ b/README.md @@ -193,6 +193,7 @@ Orchestrator 视觉阶段按 `fallback` 模式顺序降级:Gemini → NVIDIA N | Video-Queue | `video_queue.py` | 生产-消费队列:生产者 30s 轮询 rclone 同步落地目录登记整段素材入队(含重启恢复);消费者(`max_concurrent` 个线程)取队列调 Video-Processor;素材分割出的运动片段自动入队;模型超时 = 原配置 ×`timeout_multiplier`;失败重试上限 `max_retries` | | Video-Processor | `video_processor.py` | **素材→分割/片段→分析**双分支:素材按 `ss_motion_events` 已结束运动事件 ffmpeg 分割运动片段(`-c:v copy -c:a aac` 保留音频,`motion_event_id` 幂等),片段只送云端 VLM 分析;按 `vision_order` 调适配器;首个成功即落库 Oracle `videos`+`events`+`people`;全失败标 `failed` | | Person-Service | `person_service.py` | 汇总全量人物 → LLM 合并为规范名 → `set_canonical`;生成 `known_members_context` 回灌片段提示;manual 命名优先不被覆盖 | +| Disk-Guard | `disk_guard.py` | **2026-08-28 新增**:5 分钟检查一次磁盘剩余空间,低于 `min_free_gb`(默认 10GB)就清理最旧的、已完成分割阶段的整段素材,删到 `target_free_gb`(默认 15GB)水位为止;只碰原始素材(`gdrive_videos`),绝不碰运动片段(`motion_clips`,事件时间轴/人物头像依赖它)或还在处理中的素材 | | OracleDB | `oracle_db.py` | SQLite:videos(含 `motion_event_id`/`camera_id` 列)/ events / people / sync_cursor / ss_motion_events;`get_sync_delta(since)` 增量导出;`record_motion_events` / `get_motion_events_in_range`(已结束运动事件窗口查询,分割用)/ `has_motion_in_range_local` / 心跳 | | Model-Adapters | `model_adapters/` | `BaseModelAdapter.analyze_video(video_path, known_members_context, event_start_time)`;Gemini(Files API)/ NVIDIA(整视频 `video_url`)——**只有视觉分析用,2026-08-23 起不再含 Ollama/文字模型**,问答模型完全移交 AI-Gateway | | QA-Proxy | `qa.py` | **2026-08-23 重写为 HTTP 转发客户端**(原来自己遍历适配器 `chat()` 做 NVIDIA→Gemini→Ollama 三级降级的逻辑已整个搬到 AI-Gateway):调 AI-Gateway `/v1/chat/completions`,把 OpenAI 兼容响应翻译回原有 `run_qa`/`run_qa_stream` 契约,`api_gateway.py` 和 FAM-Core 调用方零改动 | @@ -758,7 +759,7 @@ cd fam-ui && npm run build # 产物 fam-ui/dist/ |------|-----| | 公网 IP | 129.146.26.249 | | SSH 用户 | ubuntu(密钥 `~/.ssh/oracle_new`) | -| 系统 | aarch64 (Ampere A1 2C12G), Ubuntu 20.04 LTS | +| 系统 | aarch64 (Ampere A1 4C23G), Ubuntu 20.04 LTS | | Tailscale | 已安装未启用(备用;新机公网直连为主) | | 登录命令 | `ssh -i ~/.ssh/oracle_new ubuntu@129.146.26.249` | @@ -829,8 +830,9 @@ export NVIDIA_API_KEY="nvapi-9cFAdO5xdbwPuxS8KGRTnlVimn1gJzbbbzWNhPwHa_Yl3pTe-Pf ## 12. 当前进度与 v1.1 计划 -### 已完成(截至 2026-08-24) +### 已完成(截至 2026-08-28) +- **Oracle 迁移故障排查 + DiskGuard 磁盘守护**(2026-08-28):8/25 迁移新机器时漏装了 FFmpeg,导致运动片段分割和帧图抽取全部失效(`ffprobe: command not found`);同时 `gdrive_videos` 持续下载新素材没有配套清理,磁盘被写满到 100%,触发 rclone 的安全机制(IO 错误时拒绝执行删除),形成"越满越删不掉"的死循环,表现为"只下载不删除"。已装回 FFmpeg、手动清理了 148 个远端已不存在的孤儿文件(释放 41G)恢复同步;新增 `DiskGuard` 后台服务作为永久兜底,剩余空间 <10GB 自动清理最旧的已完成素材。8/25 之前(旧机器时代)的历史事件帧图因源文件未随迁移保留、旧机器已销毁,无法找回;8/25-28 期间的 190 个素材/736 个运动事件按用户决定不重新处理 - **事件时间轴支持删除视频会话**(2026-08-24):三端联动,沿用"NAS 转发写请求到 Oracle"的既有模式(新增 `POST /api/oracle/video/delete` + `DELETE /api/ui/videos/`);删 events+videos 行 + 磁盘文件,不清理 `ss_motion_events` 源事件;`db_layer.delete_sync_video()` 是项目里第一个"NAS 直接写自己镜像表"的函数(增量同步机制感知不到删除,不能靠 `trigger_now()` 拉增量清理) - **问答链路抽离为独立 ai-gateway 服务**(2026-08-23):FAM-Edge 原本自己维护的问答模型降级链(NVIDIA→Gemini→Ollama,含 key 轮换/熔断)整个搬到独立仓库/独立部署单元 `ai-gateway`(OpenAI 兼容协议 `/v1/chat/completions`,Bearer token 鉴权,对外 `:5100`);FAM-Edge `qa.py` 重写为转发客户端,`/api/edge/chat/ask(/stream)` 对 FAM-Core 的契约不变;`OllamaAdapter` 从 FAM-Edge 删除 - **运动事件驱动**(v3,2026-08-22):不再分析整段视频。NAS MotionNotifier 轮询 SS 事件列表(60s,游标续用/失败重试/心跳)推送 `ss_motion_events`;Oracle 整段素材按运动事件 ffmpeg 分割运动片段(`-c:v copy -c:a aac`,只分割已结束事件,`motion_event_id` 幂等),**只分析运动片段**;前端契约不变