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:
255
docs_v1.0/API_V1.0.0/TRACE/TRACE_API_REFERENCE_V1.0.0.md
Normal file
255
docs_v1.0/API_V1.0.0/TRACE/TRACE_API_REFERENCE_V1.0.0.md
Normal 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 2554–2555) |
|
||||
| `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`.
|
||||
Reference in New Issue
Block a user