## 新架构:Oracle 集中计算 + NAS 代理展示 ### Oracle 端 (fam-edge) - 新增 frame_service: ffmpeg 视频抽帧 + VLM 人物定位裁剪头像(磁盘缓存) - 新增 /api/oracle/frame: 按 video_id+ts 抽帧返回 jpeg(带 token) - 新增 /api/oracle/avatar: 按 label 生成人物头像(VLM 定位人物 + 兜底整帧居中) - 新增 person_identifier: 人物身份识别模块 - Gemini 适配器支持 flash/flash-lite 双模型切换,429 自动降级 - frame_service VLM 全模型 429 时进入 10 分钟熔断,避免每次请求白打配额 - 兜底头像不落缓存,配额恢复后自动重试 VLM 精确定位 ### 人物合并硬规则校验(框架级修复) - person_service: LLM 合并结果落库前加硬冲突检测 - 性别冲突 → 绝不合并 - 年龄档跨未成年/成年 → 绝不合并(防止把爷爷/宝宝并进同一人) - oracle_db: upsert_person 入口剥离括号后缀(人物A(别名:人物B) → 人物A),消灭垃圾人物行 - 修复 set_canonical 丢弃 source 参数的 bug(旧代码硬编码 'manual' 导致错误合并被永久固化) - get_events_for_label: 只提取该身份组的特征文本,头像定位更精准 ### NAS 端 (fam-core) - 新增 img_proxy: /api/proxy/frame 和 /api/proxy/avatar 代理 Oracle 图片 - app.py 注册 img_bp 蓝图 - oracle_sync / db_layer / member_manager 同步人物表 ### UI 端 (fam-ui) - 事件时间轴: 每条事件卡片加时间点缩略帧 - 人物管理: 每人卡片加头像(150x150 圆角) - parse_persons: 剥离括号备注,与 Oracle 归一化一致 - 新增 EventItem 组件、Timeline 页改造 - Chat / ServiceStatus 页相应调整 ### 数据库 - scripts/ddl.sql: 同步表结构更新 - Oracle people 表: features_json / display_uid / source 字段完善
69 lines
3.5 KiB
YAML
69 lines
3.5 KiB
YAML
# FAM-Core 配置文件 (NAS 端) - 新架构 v2(2026-08-21)
|
||
#
|
||
# NAS 仅作管理后台,不再处理视频。唯一后台线程 Oracle-Sync 每 30 分钟
|
||
# 从甲骨文 FAM-Edge 拉取增量镜像到本地 MariaDB(sync_videos/events/people)。
|
||
# 所有视频分析在 Oracle 完成。
|
||
#
|
||
# Tailscale 当前无法从 NAS 反向访问 Oracle,故 base_url 用 Oracle 公网 IP。
|
||
# token 与 Oracle 端 sync_api.token 一致,均取自环境变量 ORACLE_SYNC_TOKEN。
|
||
|
||
server:
|
||
host: "0.0.0.0"
|
||
port: 8000
|
||
|
||
database:
|
||
host: "127.0.0.1"
|
||
port: 3306
|
||
user: "root"
|
||
password: "iLoveJava5!"
|
||
database: "sentinel_home_ai"
|
||
unix_socket: "/run/mysqld/mysqld10.sock"
|
||
|
||
# 甲骨文同步(每 30 分钟拉增量镜像)
|
||
oracle_sync:
|
||
# FAM-Edge 对外同步接口地址(端口同其 server.port=5000)
|
||
base_url: "http://129.146.203.203:5000"
|
||
# 与 Oracle 端 sync_api.token 一致(环境变量注入,避免明文入库)
|
||
token: "${ORACLE_SYNC_TOKEN}"
|
||
interval_sec: 1800 # 拉取间隔(秒),默认 30 分钟
|
||
timeout: 120 # 单次拉取超时(秒)
|
||
|
||
chat_handler:
|
||
# 智能问答统一走 FAM-Edge 编排端点(Gemini → NVIDIA → 本地 Ollama 兜底)
|
||
qa_url: "http://129.146.203.203:5000/api/edge/chat/ask"
|
||
qa_stream_url: "http://129.146.203.203:5000/api/edge/chat/ask/stream" # 流式版
|
||
timeout: 120
|
||
|
||
# 运动监测通知服务(2026-08-22 定稿:轮询主路径)
|
||
# NAS 本机轮询 SS EventCenter.Event.List(真实 event_id/start_time/duration),
|
||
# 增量推送到甲骨文 FAM-Edge(单向 NAS -> Oracle,甲骨文不再反向访问 NAS)。
|
||
# Webhook(/api/ss/webhook)保留为可选低延迟补充,SS 行动规则未配置则不触发。
|
||
# SS 凭据走环境变量(${DSM_ACCOUNT}/${DSM_PASSWORD}),由启动脚本 source 的 .env 提供。
|
||
motion_notifier:
|
||
enabled: true
|
||
poll_enabled: true # 轮询主路径(默认开启)
|
||
dsm_host: "192.168.50.64" # Surveillance Station 所在地址(NAS 本机)
|
||
dsm_port: 5000
|
||
dsm_account: "${DSM_ACCOUNT}"
|
||
dsm_password: "${DSM_PASSWORD}"
|
||
camera_ids: [2] # 轮询关注的摄像头(Generic_ONVIF-001)
|
||
# 摄像头名 -> camera_id 静态映射(Webhook 路径用;启动时还会从 SS 拉一份补全)
|
||
camera_name_to_id:
|
||
"Generic_ONVIF-001": 2
|
||
oracle_base_url: "http://129.146.203.203:5000" # 与 oracle_sync.base_url 一致
|
||
oracle_token: "${ORACLE_SYNC_TOKEN}" # 与 oracle_sync.token 一致
|
||
timeout_sec: 10 # 单次 SS 请求超时
|
||
# 心跳:跟轮询 SS 无关,只是定期空 POST 一下甲骨文的 /api/ss/motion,证明
|
||
# NAS->Oracle 这条推送链路本身还活着(enabled=true 就跑,不受 poll_enabled 影响)。
|
||
# 甲骨文侧 dsm_motion_prefilter.max_heartbeat_age_sec(默认 900s)据此判断"无运动"
|
||
# 结论是否可信——这个心跳间隔要明显小于那个阈值,否则会被误判成链路已死。
|
||
heartbeat_interval_sec: 300
|
||
# 轮询参数
|
||
poll_interval_sec: 60 # 轮询间隔
|
||
poll_window_hours: 2 # 每轮回看窗口(小时),覆盖轮询间隔内的新事件
|
||
batch_size: 100 # 单批推送上限
|
||
# Webhook 可选补全(仅 webhook 路径用):收到 webhook 后,以 camera_id+触发时刻
|
||
# 为中心开此时间窗(秒)回头查 SS 事件列表,匹配最接近的运动事件回填真实
|
||
# start_time/duration/event_id(Webhook 本身不提供这些字段)。
|
||
enrich_window_sec: 120
|