Core Changes: - Fix SearchView to use start_frame/end_frame directly (no time*fps conversion) - Add hard_delete support to delete_trace API - VideoPlayer: Main timeline + Mark system foundation - Proxy: Add local routes for auth, media, identity-matches, cluster-results - Add .gitignore to exclude build artifacts and dependencies Design Documents: - Multi-track Mark system design (.opencode/plans/) - Video editing positioning standards research Files Modified: - src/views/SearchView.vue: Frame positioning, ensureMinDuration (240 frames) - src/views/PeopleView.vue: batchDeleteGroups with hard_delete - src/api/index.ts: delete_trace with hard_delete body - src/components/VideoPlayer.vue: Timeline + Mark UI - src-tauri/src/proxy.rs: New local routes - AGENTS.md: Update documentation
8.3 KiB
8.3 KiB
Face Group 命名持久化問題 - 技術分析報告
日期: 2026-07-19
提出團隊: Momentry Studio
狀態: 待 Core Team 討論
一、問題現象
1.1 用戶操作流程
- 選擇影片檔案
- 建立 face group 並命名(如 "test group")
- 將 trace 移入該 group
- 成功顯示新 group,可播放影片
- 跳轉到其他頁面
- 返回 Face 頁面
- "test group" 消失
1.2 影響範圍
| 功能 | 影響 |
|---|---|
| 新建 face group | ❌ 無法持久化 |
| 重新命名 face group | ❌ 無法持久化 |
| 移動 trace 到 group | ❌ 無法持久化 |
| 系統自動生成的 group | ✅ 正常 |
二、技術分析
2.1 數據流追蹤
Frontend Core API TKG
│ │ │
│ updateTraceProfileGroup( │ │
│ fileUuid, traceIds, │ │
│ { name: "test group" } │ │
│ ) │ │
├─────────────────────────────────►│ │
│ │ PUT /trace-profile/group │
│ │ { name: "test group" } │
│ ├─────────────────────────►│
│ │ │
│ │ 存入 face_trace.label
│ │ │
│ loadClusterResults() │ │
├─────────────────────────────────►│ │
│ │ GET /file/{uuid}/ │
│ │ face-groups │
│ ├─────────────────────────►│
│ │ │
│ │ 從 TKG 讀取 label
│ │◄─────────────────────────┤
│ │ │
│ ◄───────────────────────────────┤ { face_groups: [...] } │
│ │ │
2.2 Bug 定位
文件位置: /Users/accusys/momentry_studio/src/api/index.ts
行號: 379
問題代碼:
case 'update_trace_profile_group': {
return {
url: '/api/v1/trace-profile/group',
method: 'PUT',
body: {
file_uuid: a.fileUuid,
trace_ids: a.traceIds,
name: a.group_name || a.label, // ← BUG: 忽略 a.name
key_frame: a.keyFrame,
key_face: a.keyFace
}
}
}
Frontend 調用分析:
| 行號 | 文件 | 調用方式 | 參數 |
|---|---|---|---|
| 430 | PeopleView.vue | updateTraceProfileGroup(..., { name }) |
name ✅ |
| 864 | PeopleView.vue | updateTraceProfileGroup(..., { label: name }) |
label ⚠️ |
| 928 | PeopleView.vue | updateTraceProfileGroup(..., { name: ... }) |
name ✅ |
| 971 | PeopleView.vue | updateTraceProfileGroup(..., { name }) |
name ✅ |
結果:
- API Builder 期望
group_name或label - Frontend 大部分傳入
name - 導致 Core API 收到
name: undefined
三、命名不一致問題
3.1 各層級欄位對照
| 層級 | 欄位名稱 | 說明 |
|---|---|---|
TKG face_trace node |
label |
根本存儲位置 |
Core API /trace-profile (GET) |
name |
返回給前端 |
Core API /trace-profile/group (PUT) |
name |
接受前端參數 |
| Frontend 大部分調用 | name |
✅ 正確 |
| Frontend line 864 | label |
⚠️ 不一致 |
| API Builder 期望 | group_name || label |
❌ 不匹配 |
3.2 Core API 文檔定義
PUT /api/v1/trace-profile/group
| 參數 | 類型 | 必填 | 說明 |
|---|---|---|---|
file_uuid |
string | Yes | File UUID |
trace_ids |
integer[] | Yes | Trace IDs |
name |
string | Yes | 新群組名稱 |
Core API 明確接受 name 參數。
四、架構設計問題
4.1 TKG Label 類型混淆
現狀: TKG label 欄位可能代表不同意圖:
| 來源 | 值範例 | 說明 |
|---|---|---|
| 用戶命名 | "Peter", "Cary Grant" | 用戶主動指定 |
| 系統生成 | "Trace_1", "Face Trace 9" | 自動生成 |
| 其他 | 可能還有其他類型 | 待確認 |
問題: 無法區分 label 的來源/類型
4.2 建議方案
選項 A:增加 label_type 欄位
// TKG face_trace node
{
"node_type": "face_trace",
"label": "Peter",
"label_type": "face_name", // 新增欄位
"properties": {
"trace_id": 9,
"face_count": 142,
...
}
}
label_type 可能值:
| 值 | 說明 |
|---|---|
face_name |
用戶定義的名稱 |
system |
系統自動生成 |
tmdb |
來自 TMDB 識別 |
選項 B:使用 labels 陣列(支援多標籤)
{
"node_type": "face_trace",
"labels": [
{ "value": "Peter", "type": "face_name", "source": "user" },
{ "value": "Trace_9", "type": "system", "source": "auto" }
],
...
}
選項 C:維持現狀
- TKG 保持
label單一欄位 - Core API 翻譯:
label↔name - Frontend 統一使用
name
五、修復方案
5.1 方案 A:前端統一使用 name(最小改動)
修改點:
| 文件 | 行號 | 原代碼 | 新代碼 |
|---|---|---|---|
src/api/index.ts |
379 | name: a.group_name || a.label |
name: a.name |
src/views/PeopleView.vue |
864 | { label: name } |
{ name } |
優點:
- 改動少
- 符合 Core API 文檔
- 立即解決問題
缺點:
- 未處理 TKG label 類型問題
- 未來可能有類似問題
預計工作量: 0.5 小時
5.2 方案 B:TKG 增加 label_type(完整方案)
需要修改:
-
TKG Schema
- 增加
label_type欄位
- 增加
-
Core API
/trace-profile/group增加label_type參數(默認face_name)- 更新 TKG node 時設定
label_type
-
Frontend
- 傳遞
{ name: "...", label_type: "face_name" }
- 傳遞
優點:
- 完整解決命名類型問題
- 支援未來擴展
缺點:
- 需要改動 TKG 和 Core API
- 工作量較大
預計工作量: 2-4 小時(跨團隊)
六、討論議題
6.1 短期決策
- 是否先執行方案 A,讓功能正常運作?
- 方案 A 的風險評估?
6.2 長期設計
- TKG 是否需要
label_type欄位? - 如果需要,
label_type應該有哪些值? - Core API 是否需要同時支援
name和label_type參數?
6.3 命名規範
建議建立正式對照表:
| 層級 | 欄位 | 類型 | 說明 |
|---|---|---|---|
| TKG | label |
string | 根本存儲 |
| TKG | label_type |
string | 類型標識(新增?) |
| Core API | name |
string | API 參數/返回 |
| Frontend | name |
string | 統一使用 |
七、附錄
A. 相關代碼位置
| 文件 | 說明 |
|---|---|
/Users/accusys/momentry_studio/src/api/index.ts:379 |
API Builder |
/Users/accusys/momentry_studio/src/store.ts:252 |
updateTraceProfileGroup |
/Users/accusys/momentry_studio/src/views/PeopleView.vue:430,864,928,971 |
調用點 |
/Users/accusys/momentry_core/docs_v1.0/doc_wasm/modules/18_profile.md |
Core API 文檔 |
B. Core API 端點
| 端點 | 方法 | 說明 |
|---|---|---|
/api/v1/trace-profile |
GET | 獲取單一 trace profile |
/api/v1/trace-profile |
PUT | 更新單一 trace profile |
/api/v1/trace-profile/group |
PUT | 批量更新 trace profile |
/api/v1/file/{uuid}/face-groups |
GET | 獲取 face groups |
以上問題請 Core Team 確認後,再決定修復方向。