[文档] 同步 v3 运动事件驱动架构 - 整段素材分割运动片段再分析(不再整段送云端): README 1.1/2.2/2.2.1/2.3/模块表, PROGRESS 运行状态+变更记录; 记录 systemd 守护部署方式
This commit is contained in:
18
PROGRESS.md
18
PROGRESS.md
@@ -1,15 +1,27 @@
|
|||||||
# 项目进度追踪
|
# 项目进度追踪
|
||||||
|
|
||||||
> 最后更新: 2026-08-22 11:08
|
> 最后更新: 2026-08-22 12:45
|
||||||
|
|
||||||
## 服务运行状态
|
## 服务运行状态
|
||||||
|
|
||||||
| 服务 | 节点 | 地址 | 状态 | 验证结果 |
|
| 服务 | 节点 | 地址 | 状态 | 验证结果 |
|
||||||
|------|------|------|------|---------|
|
|------|------|------|------|---------|
|
||||||
| FAM-Core | NAS | 0.0.0.0:8000 | ✅ 运行中 | health=ok, gunicorn 单 worker;Oracle-Sync + 运动监测 Webhook(轮询已关闭,SS→NAS→Oracle 推送) |
|
| 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 | ✅ 运行中 | v2.0, SQLite 异步队列 + 消费者线程 + TokenBucket 速率限制 |
|
| FAM-Edge | Oracle | 0.0.0.0:5000 | ✅ 运行中 | systemd 守护(fam-edge.service);素材→运动片段分割→只分析片段;队列消费正常 |
|
||||||
| MariaDB | NAS | 127.0.0.1:3306 | ✅ 运行中 | 10.11.11, 6 张表, utf8mb4 |
|
| MariaDB | NAS | 127.0.0.1:3306 | ✅ 运行中 | 10.11.11, 6 张表, utf8mb4 |
|
||||||
| Ollama | Oracle | 127.0.0.1:11434 | ✅ 运行中 | qwen2.5:7b,仅智能问答兜底(不参与视觉/融合) |
|
| Ollama | Oracle | 127.0.0.1:11434 | ✅ 运行中 | qwen2.5:7b,仅智能问答兜底(不参与视觉/融合) |
|
||||||
|
|
||||||
|
## 2026-08-22 运动事件驱动架构(v3)
|
||||||
|
|
||||||
|
- **决策**:不再分析整段视频。rclone 整段素材保留在 Oracle,按 NAS 推送的 `ss_motion_events`(start_time/duration)**ffmpeg 分割成运动片段**,只分析片段。
|
||||||
|
- **改动**(commit `a1523b4` + `8d6cfad`,已部署 Oracle systemd 重启):
|
||||||
|
- `oracle_db.py`:videos 表兼容加 `motion_event_id`/`camera_id` 列;新增 `get_motion_events_in_range`(窗口内已结束事件,grace 容差)/`has_unfinished_motion_in_range`/`get_video_by_motion_event_id`
|
||||||
|
- `video_processor.py`:素材→分割(只分割已结束事件,`-c:v copy -c:a aac` 保留音频,motion_event_id 幂等)/片段→只分析 双分支;修复 ffmpeg args 缺可执行文件 bug
|
||||||
|
- `video_queue.py`:素材分割出的片段入队
|
||||||
|
- `config.yaml`:新增 `motion_segment` 块(clips_dir/keep_audio/min_duration/unfinished_grace_sec)
|
||||||
|
- **E2E 验证(真机)**:素材 `Generic_ONVIF-001-20260822-110859-...mp4` → 分割 35 段(真实 event_id 25504-25538、duration 1-132s)→ 片段只分析(summary 真实:人物/动作)→ events(绝对时间 ts)→ NAS 同步 → `/api/ui/videos` 显示 motion_ 片段(字段契约不变:filename/event_start_time/camera_name/event_count/summary_json/compute_provider)→ `/api/ui/videos/<id>` 详情 events + people 正常 → `/api/proxy/frame` 帧图 200 OK
|
||||||
|
- **关键认知**:SS 事件 duration=0 仅在动作**进行中**(结束时必为正数,实测 id=25538 从 0→2s),故只分割已结束事件(start+duration ≤ now+grace),进行中的等下一轮。
|
||||||
|
- **部署注意**:Oracle fam-edge 由 **systemd `fam-edge.service` 守护**(Restart=always),代码部署后必须 `sudo systemctl restart fam-edge`(手动 setsid 会与守护打架导致端口冲突)。
|
||||||
| Tailscale | Oracle ↔ NAS | 100.74 ↔ 100.70 | ⚠️ 待修复 | Tailscale 运行但端口不通,当前用公网IP |
|
| Tailscale | Oracle ↔ NAS | 100.74 ↔ 100.70 | ⚠️ 待修复 | Tailscale 运行但端口不通,当前用公网IP |
|
||||||
| FAM-UI | NAS | 0.0.0.0:8501 | ✅ 运行中 | Streamlit 1.61.1, HTTP 200, health=ok |
|
| FAM-UI | NAS | 0.0.0.0:8501 | ✅ 运行中 | Streamlit 1.61.1, HTTP 200, health=ok |
|
||||||
|
|
||||||
|
|||||||
82
README.md
82
README.md
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
> 多模型容灾降级 + 交互式命名 + AI 对话的家庭监控系统。
|
> 多模型容灾降级 + 交互式命名 + AI 对话的家庭监控系统。
|
||||||
> 本文档为项目需求文档与 README 的整合版,按当前代码实际状态(v1.0 E2E 已打通)编写。
|
> 本文档为项目需求文档与 README 的整合版,按当前代码实际状态(v1.0 E2E 已打通)编写。
|
||||||
> 最后更新:2026-08-20(云端多模型方案整合)
|
> 最后更新:2026-08-22(运动事件驱动架构:整段素材分割运动片段再分析)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -13,13 +13,13 @@
|
|||||||
|
|
||||||
### 1.1 首期范围(已基本完成)
|
### 1.1 首期范围(已基本完成)
|
||||||
|
|
||||||
> **新架构 v2(2026-08-21 重构)**:NAS 不再处理视频,仅作管理后台;视频分析全部上云(Oracle)。
|
> **新架构 v3(2026-08-22 重构:运动事件驱动)**:NAS 不再处理视频,仅作管理后台 + 运动事件推送;视频分析全部上云(Oracle),且**不再分析整段视频**——整段素材按 SS 运动事件**分割成运动片段**后只分析片段。
|
||||||
|
|
||||||
- **FAM-Core**(NAS 端单进程):仅 **Oracle-Sync**(每 30 分钟拉增量镜像)+ **Chat-Handler** + **Member-Manager** 三个子模块,CPU 占用极低
|
- **FAM-Core**(NAS 端单进程):**Oracle-Sync**(每 30 分钟拉增量镜像)+ **MotionNotifier**(轮询 SS 运动事件推送 Oracle)+ **Chat-Handler** + **Member-Manager**,CPU 占用极低
|
||||||
- **FAM-Edge**(Oracle 端单进程):rclone 实时同步 Google 硬盘视频 → 监听目录 → **整视频直传云端 VLM**(Gemini 用 Files API / NVIDIA 用整视频 `video_url`,不切片不抽帧)→ 结构化 JSON 落本地 SQLite → 对外提供 `/api/oracle/sync` 增量拉取接口(**本地模型不参与视频分析**)
|
- **FAM-Edge**(Oracle 端单进程):rclone 实时同步 Google 硬盘视频(**整段素材**)→ 按 `ss_motion_events` 运动事件(start_time/duration)**ffmpeg 分割运动片段** → **只把运动片段送云端 VLM**(Gemini 用 Files API / NVIDIA 整视频 `video_url`)→ 结构化 JSON 落本地 SQLite → 对外提供 `/api/oracle/sync` 增量拉取接口(**本地模型不参与视频分析**)
|
||||||
- **FAM-UI**(NAS 端):Streamlit 读本地同步镜像(sync_videos / sync_events / sync_people),事件时间轴 + 人物管理 + AI 对话 + 对话历史 + 统计
|
- **FAM-UI**(NAS 端):Vue3 SPA 读本地同步镜像(sync_videos / sync_events / sync_people),事件时间轴 + 人物管理 + AI 对话 + 对话历史 + 统计
|
||||||
- **数据库**:Oracle 侧 SQLite(videos/events/people/sync_cursor);NAS 侧 MariaDB 镜像(sync_videos / sync_events / sync_people / sync_cursor)+ chat_history
|
- **数据库**:Oracle 侧 SQLite(videos/events/people/ss_motion_events/sync_cursor);NAS 侧 MariaDB 镜像(sync_videos / sync_events / sync_people / sync_cursor)+ chat_history
|
||||||
- **数据流向**:Google 硬盘 ──rclone──► 甲骨文本地 ──整视频分析──► Oracle SQLite ──每 30 分钟 NAS 拉取──► NAS MariaDB 镜像 ──► FAM-UI
|
- **数据流向**:Google 硬盘 ──rclone──► 甲骨文整段素材 ──按运动事件分割片段──► 片段云端分析 ──► Oracle SQLite ──每 30 分钟 NAS 拉取──► NAS MariaDB 镜像 ──► FAM-UI;运动事件由 NAS 轮询 SS 推送 Oracle(NAS → Oracle 单向)
|
||||||
- **AI 对话**:查 sync_events 拼上下文 → 经 FAM-Edge 问答编排(Gemini → NVIDIA → 本地 Ollama 兜底)生成回答 → 返回并写 chat_history
|
- **AI 对话**:查 sync_events 拼上下文 → 经 FAM-Edge 问答编排(Gemini → NVIDIA → 本地 Ollama 兜底)生成回答 → 返回并写 chat_history
|
||||||
- **人物命名**:用户命名/合并某 label → 回推 Oracle `/api/oracle/people/correct`(manual 优先)→ 下一周期同步回 NAS;Oracle 独立 person_service 汇总全量人物 → LLM 合并为规范名 → 回灌视频提示
|
- **人物命名**:用户命名/合并某 label → 回推 Oracle `/api/oracle/people/correct`(manual 优先)→ 下一周期同步回 NAS;Oracle 独立 person_service 汇总全量人物 → LLM 合并为规范名 → 回灌视频提示
|
||||||
|
|
||||||
@@ -84,13 +84,13 @@ Orchestrator 视觉阶段按 `fallback` 模式顺序降级:Gemini → NVIDIA N
|
|||||||
▼
|
▼
|
||||||
┌──────────────────────── Oracle Cloud (129.146.203.203) ────────────────────────┐
|
┌──────────────────────── Oracle Cloud (129.146.203.203) ────────────────────────┐
|
||||||
│ FAM-Edge (Flask :5000) │
|
│ FAM-Edge (Flask :5000) │
|
||||||
│ ├─ Watch-Processor: 30s 轮询 /opt/fam-edge/gdrive_videos,新视频串行处理 │
|
│ ├─ Video-Queue: 30s 轮询 /opt/fam-edge/gdrive_videos 登记整段素材 │
|
||||||
│ ├─ Video-Processor: 整视频直传云端 VLM(不切片不抽帧) │
|
│ ├─ Video-Processor: 素材按 ss_motion_events 分割运动片段 → 只分析片段 │
|
||||||
│ │ Gemini(Files API) → 失败 NVIDIA(整视频 video_url) → 再失败 FAILED │
|
│ │ (ffmpeg -c:v copy -c:a aac) → Gemini → 失败 NVIDIA → 再失败 FAILED │
|
||||||
│ ├─ Person-Service: 汇总人物 → LLM 合并规范名 → 回灌视频提示 │
|
│ ├─ Person-Service: 汇总人物 → LLM 合并规范名 → 回灌视频提示 │
|
||||||
│ ├─ OracleDB (SQLite): videos / events / people / sync_cursor │
|
│ ├─ OracleDB (SQLite): videos / events / people / ss_motion_events │
|
||||||
│ └─ API: /api/oracle/sync (增量拉取) · /api/oracle/people/correct (命名校正) · │
|
│ └─ API: /api/oracle/sync (增量拉取) · /api/ss/motion (运动事件) · │
|
||||||
│ /api/edge/chat/ask (问答编排 Gemini→NVIDIA→Ollama) │
|
│ /api/oracle/people/correct (命名校正) · /api/edge/chat/ask (问答) │
|
||||||
└───────────────────────────────┬───────────────────────────────────────────────┘
|
└───────────────────────────────┬───────────────────────────────────────────────┘
|
||||||
│ HTTP GET /api/oracle/sync?since=&token= (每 30 分钟)
|
│ HTTP GET /api/oracle/sync?since=&token= (每 30 分钟)
|
||||||
▼
|
▼
|
||||||
@@ -106,49 +106,51 @@ Orchestrator 视觉阶段按 `fallback` 模式顺序降级:Gemini → NVIDIA N
|
|||||||
└─────────────────────────────────────────────────────────────────────────────────┘
|
└─────────────────────────────────────────────────────────────────────────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 2.2.1 运动监测链路(v3,Webhook 驱动 · 去轮询)
|
#### 2.2.1 运动监测链路(v3,NAS 轮询驱动)
|
||||||
|
|
||||||
摄像头动作事件由 **Surveillance Station 主动推送**,不经过任何轮询:
|
摄像头动作事件由 **NAS 端 MotionNotifier 轮询 Surveillance Station 事件列表**获取(简单稳定,事件不遗漏;Webhook 端点在代码中保留为可选低延迟补充):
|
||||||
|
|
||||||
Surveillance Station (NAS 本机)
|
Surveillance Station (NAS 本机)
|
||||||
│ 事件=偵測到動作 → 行動規則「Webhook」动作:event_time=%EVENT_TIME% 等
|
│ SYNO.SurveillanceStation.EventCenter.Event method=List
|
||||||
│ HTTP POST(同机 127.0.0.1:8000,无需外网)
|
│ camera_ids=2, event_types=10, start_time/end_time(下划线风格)
|
||||||
▼
|
▼
|
||||||
NAS FAM-Core :8000 /api/ss/webhook (motion_bp.py)
|
NAS FAM-Core MotionNotifier(motion_notifier.py,每 60s)
|
||||||
│ ├─ 解析 JSON / 表单(兼容单条与数组)
|
│ ├─ 增量游标(MariaDB sync_cursor.motion_last_event_id,DB 续用/重启补推)
|
||||||
│ ├─ 字段映射:%DEVICE_NAME% → camera_id(查 SS 名→id 映射)、%EVENT_TIME% → epoch
|
│ ├─ 推送失败批次不前进游标(下轮重试,不丢事件)
|
||||||
│ └─ 合成稳定 event_id = hash(device|time|thumb)(供甲骨文 UNIQUE 幂等去重)
|
│ └─ 定期空 events 心跳(证明推送链路存活)
|
||||||
│ HTTP POST /api/ss/motion?token=ORACLE_SYNC_TOKEN(事件触发即推)
|
│ HTTP POST /api/ss/motion?token=ORACLE_SYNC_TOKEN(真实 event_id/start_time/duration)
|
||||||
▼
|
▼
|
||||||
Oracle FAM-Edge :5000 /api/ss/motion (api_gateway.py)
|
Oracle FAM-Edge :5000 /api/ss/motion (api_gateway.py)
|
||||||
│ → OracleDB.ss_motion_events(event_id UNIQUE,自动去重)
|
│ → OracleDB.ss_motion_events(event_id UNIQUE,自动去重;start_time/duration 为 Unix epoch)
|
||||||
│ → video_processor.has_motion_in_range_local() 查本地事件做运动预过滤
|
▼
|
||||||
|
Oracle video_processor:整段素材按运动事件【分割运动片段】→ 只分析片段(见 2.3)
|
||||||
|
|
||||||
> 设计要点:甲骨文**不反向访问** NAS;SS 推送是 NAS 入站(同机 127.0.0.1)。
|
> 设计要点:甲骨文**不反向访问** NAS;只分割**已结束**事件(SS 事件 duration 在动作进行中为 0、结束才回填真实时长)。
|
||||||
> 失败-open:`ss_motion_events` 为空时预过滤返回 None(不误杀视频)。
|
> 失败-open:心跳超过 `max_heartbeat_age_sec`(900s)未更新时预过滤/分割 fail-open,不误判"无运动"。
|
||||||
|
|
||||||
**网络要点(新架构)**:
|
**网络要点(新架构)**:
|
||||||
- NAS → Oracle 出站共两条:① `GET /api/oracle/sync`(拉取增量)+ `POST /api/oracle/people/correct`(命名回推);② `POST /api/ss/motion`(运动侦测事件推送)。均走 Oracle 公网 IP:5000,token 鉴权
|
- NAS → Oracle 出站共两条:① `GET /api/oracle/sync`(拉取增量)+ `POST /api/oracle/people/correct`(命名回推);② `POST /api/ss/motion`(运动侦测事件推送)。均走 Oracle 公网 IP:5000,token 鉴权
|
||||||
- Oracle Ollama :11434 不对外暴露,问答经 FAM-Edge `/api/edge/chat/ask` 代理
|
- Oracle Ollama :11434 不对外暴露,问答经 FAM-Edge `/api/edge/chat/ask` 代理
|
||||||
- Tailscale 两节点在线但 NAS 无法反向访问 Oracle,故全部走 NAS 主动出站拉取模式
|
- Tailscale 两节点在线但 NAS 无法反向访问 Oracle,故全部走 NAS 主动出站拉取模式
|
||||||
|
|
||||||
### 2.3 主链路时序(新架构 v2)
|
### 2.3 主链路时序(新架构 v3:运动事件驱动)
|
||||||
|
|
||||||
1. Google 硬盘新视频 → rclone 定时同步到 Oracle `/opt/fam-edge/gdrive_videos`
|
1. Google 硬盘新视频(整段素材)→ rclone 定时同步到 Oracle `/opt/fam-edge/gdrive_videos`
|
||||||
2. Watch-Processor 轮询发现新文件 → 登记到 Oracle `videos`(pending)
|
2. Video-Queue 轮询发现新文件 → 登记到 Oracle `videos`(pending)
|
||||||
3. Video-Processor 串行处理:整视频上传 Gemini Files API(或 NVIDIA 整视频 `video_url`)→ 模型直出 `{global_summary, events[], people_mentioned[]}` → 写 Oracle `videos` + `events` + `people`
|
3. Video-Processor 处理素材:按文件名解析开始时间 → 查窗口内 `ss_motion_events` **已结束**运动事件 → ffmpeg 分割运动片段(`-c:v copy -c:a aac` 保留音频)→ 片段登记 `videos`(pending,`motion_event_id` 关联)并入队;素材标记"已分割 N 段"(仍有未结束事件则保持 pending 下轮再分割)
|
||||||
4. Person-Service 每 30 分钟汇总全量人物 → LLM 合并为规范名 → 更新 `people.canonical_name` → 生成 `known_members_context` 回灌后续视频提示
|
4. Video-Processor 处理运动片段:**只分析片段**(不分析整段)→ Gemini(或 NVIDIA 兜底)直出 `{global_summary, events[], people_mentioned[]}` → 写 Oracle `videos` + `events` + `people`
|
||||||
5. NAS Oracle-Sync 每 30 分钟 `GET /api/oracle/sync?since=<cursor>` → upsert 到本地 `sync_*` 镜像表 → 推进 `sync_cursor`
|
5. Person-Service 每 30 分钟汇总全量人物 → LLM 合并为规范名 → 更新 `people.canonical_name` → 生成 `known_members_context` 回灌后续片段提示
|
||||||
6. FAM-UI 读本地镜像展示;用户命名 → `POST /api/oracle/people/correct` 回推 Oracle,下一周期同步生效
|
6. NAS Oracle-Sync 每 30 分钟 `GET /api/oracle/sync?since=<cursor>` → upsert 到本地 `sync_*` 镜像表 → 推进 `sync_cursor`
|
||||||
|
7. FAM-UI 读本地镜像展示(时间轴/人物/统计字段契约不变);用户命名 → `POST /api/oracle/people/correct` 回推 Oracle,下一周期同步生效
|
||||||
|
|
||||||
**运动监测支流(v3,Webhook 驱动 · 去轮询)**:
|
**运动监测支流(NAS 轮询驱动)**:
|
||||||
- Surveillance Station 侦测到动作 → 行動規則「Webhook」动作 `POST :8000/api/ss/webhook`(参数 `event_time=%EVENT_TIME%`、`device_name=%DEVICE_NAME%`、`event_name`/`server_name`/`thumbnail_url`)
|
- MotionNotifier 每 60s 轮询 SS `EventCenter.Event.List`(camera_ids=2, event_types=10)→ 增量(游标)推送 `POST /api/ss/motion` 落库 `ss_motion_events`(真实 event_id/start_time/duration)
|
||||||
- FAM-Core `motion_bp` 解析并映射(`%DEVICE_NAME%`→camera_id、`%EVENT_TIME%`→epoch、合成稳定 event_id)→ `POST /api/ss/motion` 推送 Oracle
|
- 整段素材处理时按 `ss_motion_events` 分割运动片段(只分割已结束事件;duration=0 的进行中事件等结束后的下轮);片段分析结果的时间点(`events.ts`)为绝对时间,前端时间轴与帧图(`/api/proxy/frame`,绝对 ts − event_start_time 偏移取帧)天然兼容
|
||||||
- Oracle `api_gateway` 落库 `ss_motion_events`(UNIQUE event_id 幂等),`video_processor.has_motion_in_range_local()` 据此做运动预过滤(空表 fail-open 返回 None)
|
|
||||||
|
|
||||||
**容错设计**:
|
**容错设计**:
|
||||||
- Oracle 单视频串行(`max_concurrent=1`)避免多视频抢占云端配额
|
- Oracle 单视频串行(`max_concurrent=1`)避免多视频抢占云端配额
|
||||||
- 视频分析失败(两云端均不可用)标记 `failed`,下一周期 cursor 仍包含它会被重试
|
- 运动片段分析失败(两云端均不可用)标记 `failed`,下一周期 cursor 仍包含它会被重试
|
||||||
|
- 素材分割幂等:按 `motion_event_id` 去重,片段文件已存在则跳过分割
|
||||||
- NAS 同步失败仅记日志,下一周期(30 分钟)自动重试,不阻塞 UI
|
- NAS 同步失败仅记日志,下一周期(30 分钟)自动重试,不阻塞 UI
|
||||||
- fam-core 日志双写:stdout + `fam-core/logs/fam-core.log`
|
- fam-core 日志双写:stdout + `fam-core/logs/fam-core.log`
|
||||||
|
|
||||||
@@ -178,8 +180,8 @@ Orchestrator 视觉阶段按 `fallback` 模式顺序降级:Gemini → NVIDIA N
|
|||||||
| 模块 | 文件 | 职责 |
|
| 模块 | 文件 | 职责 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
| API-Gateway | `api_gateway/api_gateway.py` | `GET /api/oracle/sync`(增量拉取,since+token 校验);`POST /api/oracle/people/correct`(命名校正);`POST /api/edge/chat/ask`(问答编排);`POST /api/ss/motion`(运动事件接收,token 校验,落库 `ss_motion_events`);`GET /health` |
|
| API-Gateway | `api_gateway/api_gateway.py` | `GET /api/oracle/sync`(增量拉取,since+token 校验);`POST /api/oracle/people/correct`(命名校正);`POST /api/edge/chat/ask`(问答编排);`POST /api/ss/motion`(运动事件接收,token 校验,落库 `ss_motion_events`);`GET /health` |
|
||||||
| Video-Queue | `video_queue.py` | 生产-消费队列:生产者 30s 轮询 rclone 同步落地目录登记新视频入队(含重启恢复);消费者(`max_concurrent` 个线程)取队列调 Video-Processor;模型超时 = 原配置 ×`timeout_multiplier`;失败重试上限 `max_retries` |
|
| Video-Queue | `video_queue.py` | 生产-消费队列:生产者 30s 轮询 rclone 同步落地目录登记整段素材入队(含重启恢复);消费者(`max_concurrent` 个线程)取队列调 Video-Processor;模型超时 = 原配置 ×`timeout_multiplier`;失败重试上限 `max_retries` |
|
||||||
| Video-Processor | `video_processor.py` | 按 `vision_order` 调适配器 `analyze_video`(整视频);首个成功即落库 Oracle `videos`+`events`+`people`;全失败标 `failed`;运动预过滤改查本地 `ss_motion_events`(`has_motion_in_range_local`),不再反向访问 NAS |
|
| Video-Processor | `video_processor.py` | **素材→分割/片段→分析**双分支:素材按 `ss_motion_events` 已结束运动事件 ffmpeg 分割运动片段(`-c:v copy -c:a aac`,幂等去重),片段只送云端 VLM 分析;按 `vision_order` 调适配器;首个成功即落库 Oracle `videos`+`events`+`people`;全失败标 `failed` |
|
||||||
| Person-Service | `person_service.py` | 汇总全量人物 → LLM 合并为规范名 → `set_canonical`;生成 `known_members_context` 回灌视频提示;manual 命名优先不被覆盖 |
|
| Person-Service | `person_service.py` | 汇总全量人物 → LLM 合并为规范名 → `set_canonical`;生成 `known_members_context` 回灌视频提示;manual 命名优先不被覆盖 |
|
||||||
| OracleDB | `oracle_db.py` | SQLite:videos / events / people / sync_cursor / ss_motion_events;`get_sync_delta(since)` 增量导出;`record_motion_events` / `has_motion_in_range_local`(运动事件幂等落库与窗口查询) |
|
| OracleDB | `oracle_db.py` | SQLite:videos / events / people / sync_cursor / ss_motion_events;`get_sync_delta(since)` 增量导出;`record_motion_events` / `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`,`num_frames=128`)/ Ollama(纯文本,不参与视频) |
|
| Model-Adapters | `model_adapters/` | `BaseModelAdapter.analyze_video(video_path, known_members_context, event_start_time)`;Gemini(Files API 整视频)/ NVIDIA(整视频 `video_url`,`num_frames=128`)/ Ollama(纯文本,不参与视频) |
|
||||||
|
|||||||
Reference in New Issue
Block a user