# Face Group 命名持久化問題 - 技術分析報告 **日期**: 2026-07-19 **提出團隊**: Momentry Studio **狀態**: 待 Core Team 討論 --- ## 一、問題現象 ### 1.1 用戶操作流程 1. 選擇影片檔案 2. 建立 face group 並命名(如 "test group") 3. 將 trace 移入該 group 4. 成功顯示新 group,可播放影片 5. 跳轉到其他頁面 6. 返回 Face 頁面 7. **"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 **問題代碼**: ```javascript 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` 欄位 ```javascript // 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` 陣列(支援多標籤) ```javascript { "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`(完整方案) **需要修改**: 1. **TKG Schema** - 增加 `label_type` 欄位 2. **Core API** - `/trace-profile/group` 增加 `label_type` 參數(默認 `face_name`) - 更新 TKG node 時設定 `label_type` 3. **Frontend** - 傳遞 `{ name: "...", label_type: "face_name" }` **優點**: - 完整解決命名類型問題 - 支援未來擴展 **缺點**: - 需要改動 TKG 和 Core API - 工作量較大 **預計工作量**: 2-4 小時(跨團隊) --- ## 六、討論議題 ### 6.1 短期決策 1. **是否先執行方案 A**,讓功能正常運作? 2. **方案 A 的風險評估**? ### 6.2 長期設計 1. **TKG 是否需要 `label_type` 欄位**? 2. **如果需要,`label_type` 應該有哪些值**? 3. **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 確認後,再決定修復方向。**