Initial commit: docs_v1.0 structure

- API_V1.0.0: 正式 API 文件(spec、release、deploy、test)
- M4_workspace: M4 工作記錄(review、issue、提案)
- M5_workspace: M5 工作記錄(實作、評估、sync)
- AGENTS.md: 專案規則

M5/M4 協作方式:git push/pull 同步 workspace 文件
This commit is contained in:
M5
2026-05-07 23:42:19 +08:00
commit 28e927f7bb
519 changed files with 136077 additions and 0 deletions

View File

@@ -0,0 +1,255 @@
# Trace API v1.0.0 Reference — M5 Official
**Author**: M5
**Date**: 2026-05-07
**Status**: ✅ Production — implemented and verified on Charade (Job 255)
---
## Design Philosophy
> 可以追蹤的 trace 就像雷達看到的物體 — 都可以分析。
A **trace** is any entity detected and tracked across consecutive frames:
```
Detection → Grouping (tracking) → Trace → Analysis → Identity Binding
```
### Coordinate System: 2D+time (current), 3D+time (future)
| Dimension | Current (Face) | Future (Object/Pose) |
|-----------|---------------|---------------------|
| x, y | Bbox center (image plane) | Bbox center (world space) |
| w, h | Bbox size (image plane) | Bbox size (world space) |
| t | Frame number / timestamp | Frame number / timestamp |
Future: 3D bounding cube `[x, y, z, w, h, d, t]` with camera-relative analysis, camera trace (observer), and light source trace (illuminator). See design discussion in `M4_workspace/TRACE_API_REFERENCE_V1.0.0.md`.
---
## Base URL
```
http://localhost:{port}/api/v1
```
Playground: port 3003 | Production: port 3002
## Authentication
All endpoints require `X-API-Key` header.
---
## Trace Model
A **trace** is a sequence of detections of the same entity across consecutive frames:
```
Identity (person) ──has_many──> Trace (tracked segment) ──has_many──> Detection (single frame)
```
| Trace Type | Detection Source | Identity Binding | Status |
|-----------|-----------------|-----------------|--------|
| `face` | Face detector (Vision + FaceNet) | `face_detections.identity_id``identities` | ✅ Implemented |
| `object` | YOLO pre_chunks by class label | By object class name | 🔜 Future (needs tracking) |
| `pose` | Pose skeleton keypoints | TBD | 🔜 Future |
### YOLO Object Trace (Future)
YOLO produces frame-level detections with class labels but **no tracking ID**. To enable:
1. Add IoU tracking (SORT) across frames
2. Assign `trace_id` per group, store in `pre_chunks` or new `yolo_traces` table
3. Add routes: `POST /object_trace/sortby`, `GET /object_trace/:id/detections`
---
## Endpoints
### 1. List Face Traces
**`POST /api/v1/file/:file_uuid/face_trace/sortby`**
Aggregated face traces with sorting and filtering.
#### Request Body
```json
{
"sort_by": "face_count | duration | first_appearance",
"limit": 100,
"min_faces": 1,
"min_confidence": 0.0,
"max_confidence": 1.0
}
```
#### Response
```json
{
"success": true,
"file_uuid": "3abeee81d94597629ed8cb943f182e94",
"total_traces": 6892,
"total_faces": 108204,
"traces": [
{
"trace_id": 1271,
"face_count": 33,
"first_frame": 68280,
"last_frame": 69240,
"first_sec": 2731.2,
"last_sec": 2769.6,
"duration_sec": 38.4,
"avg_confidence": 0.782,
"sample_face_id": "18441"
}
]
}
```
| Field | Description |
|-------|-------------|
| `trace_id` | Unique ID within the video file |
| `face_count` | Number of detections in this trace |
| `first_frame / last_frame` | Frame range |
| `first_sec / last_sec` | Time range |
| `duration_sec` | Duration in seconds |
| `avg_confidence` | Mean detection confidence |
| `sample_face_id` | ID of the highest-confidence detection |
| `identity_id` *(future)* | Bound identity ID |
| `identity_name` *(future)* | Identity display name |
---
### 2. Trace Face Detections
**`GET /api/v1/file/:file_uuid/trace/:trace_id/faces`**
#### Query Parameters
| Param | Type | Default | Description |
|-------|------|---------|-------------|
| `limit` | int | 200 | Max faces (capped 1000) |
| `offset` | int | 0 | Pagination |
| `interpolate` | bool | false | Enable linear interpolation |
#### Response
```json
{
"success": true,
"file_uuid": "3abeee81d94597629ed8cb943f182e94",
"trace_id": 2,
"total": 2,
"faces": [
{
"id": 12400,
"start_frame": 4650,
"start_time": 186.0,
"x": 1047,
"y": 361,
"width": 187,
"height": 187,
"confidence": 0.834,
"interpolated": false
}
]
}
```
Interpolated frames: `id=0, confidence=0.0, interpolated=true`.
#### Interpolation Algorithm
Linear interpolation between consecutive detections:
```
t = (mid_frame - prev.frame) / (next.frame - prev.frame)
x = prev.x + (next.x - prev.x) * t
y = prev.y + (next.y - prev.y) * t
width = prev.w + (next.w - prev.w) * t
height = prev.h + (next.h - prev.h) * t
```
---
### 3. Trace Video Clip
**`GET /api/v1/file/:file_uuid/trace/:trace_id/video`**
MP4 video with bounding box overlay for a trace.
| Param | Type | Default | Description |
|-------|------|---------|-------------|
| `padding` | float | 2.0 | Padding seconds before/after |
---
### 4. Bounding Box Overlay Video
**`GET /api/v1/file/:file_uuid/video/bbox`**
MP4 video segment with face bboxes.
| Param | Type | Default | Description |
|-------|------|---------|-------------|
| `start` | int | — | Start frame (required) |
| `end` | int | — | End frame (required) |
| `duration` | float | 10 | Clip duration seconds |
---
### 5. Frame Thumbnail
**`GET /api/v1/file/:file_uuid/thumbnail`**
Single frame JPEG, with optional crop.
| Param | Type | Default | Description |
|-------|------|---------|-------------|
| `frame` | int | — | Frame number (required) |
| `x, y, w, h` | int | — | Crop region |
---
## CLI Verification (Charade, Job 255)
```
File: Charade (1963), 25fps, 108204 faces, 6892 traces
Dev server: http://localhost:3003
Auth: X-API-Key: muser_test_apikey
```
| # | Endpoint | Request | M5 Result |
|---|----------|---------|-----------|
| 1 | `POST /face_trace/sortby` | `{"limit":2}` | 6892 traces, 108204 faces |
| 2 | `POST /face_trace/sortby` | `{"sort_by":"face_count","limit":3}"` | #1271=33, #2171=26, #1268=24 faces |
| 3 | `POST /face_trace/sortby` | `{"sort_by":"duration","limit":3}` | Longest 38.4s, 30.0s, 27.6s |
| 4 | `POST /face_trace/sortby` | `{"min_faces":10,"min_confidence":0.7}` | Filtered traces |
| 5 | `GET /trace/2/faces` | `?limit=5` | 1 face: frame 4620 |
| 6 | `GET /trace/2/faces` | `?limit=100&interpolate=true` | 31 frames (2 real + 29 interpolated) |
| 7 | `GET /trace/1271/faces` | `?limit=2` | 33 total, paginated |
| 8 | `GET /trace/1271/faces` | `?limit=10&interpolate=true` | 271 frames |
| 9 | `GET /trace/2/video` | — | 2.0MB MP4 |
| 10 | `GET /video/bbox` | `?start=4650&end=4680` | 1.9MB MP4 overlay |
| 11 | `GET /thumbnail` | `?frame=4650` | 82KB JPEG |
---
## Source Files
| File | Purpose |
|------|---------|
| `src/api/trace_agent_api.rs` | Face trace listing + detail + interpolation |
| `src/api/media_api.rs` | Video clip, bbox overlay, thumbnail |
| `src/api/server.rs` | Route merge (lines 25542555) |
| `portal/src/components/FaceTraceTimeline.vue` | Frontend trace display |
## Route Pattern
Current: `/api/v1/file/:file_uuid/face_trace/...`
Future: `/api/v1/file/:file_uuid/{type}_trace/...` where `type` = `object`, `pose`, etc.
New trace types should add new modules (e.g., `object_trace_api.rs`) rather than overloading `trace_agent_api.rs`.