Files
silver_pose/docs/api.md
T

91 lines
2.7 KiB
Markdown
Raw Normal View History

2026-07-20 22:05:55 +08:00
# 本地模块与事件合约
> Silver Pose 没有后端 API;本文定义 V1/V2 必须保持一致的本地配置、数据和事件合约。
## 配置合约
`v1/config.example.json` 的最小形状:
```json
{
"source": {
"id": "lobby-camera-01",
"rtsp_url_env": "SILVER_POSE_RTSP_URL",
"roi_normalized": [0.0, 0.0, 1.0, 1.0]
},
"model": {
"path": "models/best.pt",
"sha256": "填写受控模型哈希",
"confidence_threshold": 0.25
},
"event": {
"keypoint_confidence_threshold": 0.4,
"suspect_window_seconds": 0.5,
"confirm_window_seconds": 1.0,
"recovery_window_seconds": 2.0,
"cooldown_seconds": 10.0
},
"artifacts": {
"event_dir": "../artifacts/events"
}
}
```
- `rtsp_url_env` 必填;应用从同名环境变量读取真实 URL。
- 数值是待现场录像校准的默认值;每个值必须真正进入事件逻辑。
- 缺少环境变量、模型不存在或哈希不符时,应用显示配置错误,不启动监控。
## 核心数据
```text
Keypoint = { x: float, y: float, confidence: float }
PersonPose = {
track_id: string,
detected_at_monotonic: float,
box_xyxy: [float, float, float, float],
box_confidence: float,
keypoints: Keypoint[17]
}
PoseQuality = {
accepted: bool,
reason: string,
visible_joint_count: int
}
FallEvent = {
event_id: string,
source_id: string,
track_id: string,
started_at_utc: string,
confirmed_at_utc: string,
latency_seconds: float,
state: "CONFIRMED",
evidence: {
horizontal_pose: bool,
rapid_vertical_change: bool,
persistence_seconds: float
},
screenshot_path: string,
config_version: string
}
```
`FallEvent` 只在状态首次进入 `CONFIRMED` 时创建一次。连续帧更新 UI 状态,但不重复创建事件。
## 事件合约
| 事件 | 触发者 | 负载 | 结果 |
| --- | --- | --- | --- |
| `source.connected` | 视频源 | `source_id`、时间 | UI 显示在线。 |
| `source.error` | 视频源 | `source_id`、错误码、可重试标记 | UI 显示异常;不报警。 |
| `person.updated` | 跟踪与 Pose | `PersonPose`、`PoseQuality`、状态 | UI 绘制骨架与 ID。 |
| `fall.suspected` | 状态机 | `track_id`、开始时间 | UI 显示黄色疑似状态。 |
| `fall.confirmed` | 状态机 | `FallEvent` | 红色叠加、声音、弹窗、截图、JSONL。 |
| `fall.recovered` | 状态机 | `track_id`、时间 | UI 恢复绿色正常状态。 |
## 副作用边界
- 仅 `alerts` 模块可写事件截图、播放声音、弹窗和追加 JSONL。
- 仅 `video_source` 模块读 RTSP 或本地视频。
- 仅 `pose` 模块加载模型;UI 不得直接调用模型。
- V2 可以改变实现语言,但不得改变配置含义、`FallEvent` 字段和事件幂等语义。