docs: update docs_v1.0/ documentation
- Fix markdown lint issues (MD030, MD047, MD051, MD028, MD005) - Update AI agents, architecture, implementation docs - Add new identity, face recognition, and API documentation - Remove deprecated face/person API guides
This commit is contained in:
@@ -446,4 +446,4 @@ def test_search_documents():
|
||||
**版本**: V1.0
|
||||
**適用對象**: 所有 AI Agent 和自動化工具
|
||||
|
||||
**注意**: 本文檔應與實際模板文件結合使用,定期更新以反映系統變更。
|
||||
**注意**: 本文檔應與實際模板文件結合使用,定期更新以反映系統變更。
|
||||
|
||||
@@ -46,7 +46,7 @@ ai_query_hints:
|
||||
## 目錄
|
||||
|
||||
1. [已實作端點](#1-已實作端點)
|
||||
2. [API Key 管理](#2-api-key-管理-規劃中)
|
||||
2. [API Key 管理](#2-api-key-管理)
|
||||
3. [影片管理](#3-影片管理)
|
||||
4. [查詢與搜索](#4-查詢與搜索)
|
||||
5. [系統狀態](#5-系統狀態)
|
||||
|
||||
@@ -196,7 +196,7 @@ n8n 專用搜尋(包含完整影片檔案路徑 file_path)
|
||||
```json
|
||||
{
|
||||
"uuid": "9760d0820f0cf9a7",
|
||||
"video_uuid": "5dea6618a606e7c7",
|
||||
"file_uuid": "5dea6618a606e7c7",
|
||||
"status": "completed",
|
||||
"progress": 100,
|
||||
"created_at": "2026-03-25T10:00:00Z",
|
||||
|
||||
@@ -368,4 +368,4 @@ Q - 退出
|
||||
|
||||
**更新日期**: 2026-04-02
|
||||
**版本**: 2.0.0
|
||||
**作者**: Momentry Team
|
||||
**作者**: Momentry Team
|
||||
|
||||
@@ -394,4 +394,4 @@ brew install ffmpeg
|
||||
|
||||
**創建日期**: 2026-04-02
|
||||
**版本**: 1.1.0
|
||||
**作者**: Momentry Team
|
||||
**作者**: Momentry Team
|
||||
|
||||
@@ -219,4 +219,4 @@ A: 兩種模式都按實際時長播放。說話人演示有 2 秒暫停。
|
||||
|
||||
**更新日期**: 2026-04-02
|
||||
**版本**: 2.1.0
|
||||
**作者**: Momentry Team
|
||||
**作者**: Momentry Team
|
||||
|
||||
@@ -219,4 +219,4 @@ A:
|
||||
|
||||
**更新日期**: 2026-04-02
|
||||
**版本**: 1.2.0
|
||||
**作者**: Momentry Team
|
||||
**作者**: Momentry Team
|
||||
|
||||
199
docs_v1.0/IMPLEMENTATION/DEV_3003_REFACTOR.md
Normal file
199
docs_v1.0/IMPLEMENTATION/DEV_3003_REFACTOR.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# Dev 3003 改造記錄
|
||||
|
||||
| 項目 | 內容 |
|
||||
|------|------|
|
||||
| 建立者 | Warren |
|
||||
| 建立時間 | 2026-04-30 |
|
||||
| 文件版本 | V1.0 |
|
||||
|
||||
---
|
||||
|
||||
## 版本歷史
|
||||
|
||||
| 版本 | 日期 | 目的 | 操作人 | 工具/模型 |
|
||||
|------|------|------|--------|-----------|
|
||||
| V1.0 | 2026-04-30 | Dev 3003 全面改造 | Warren | OpenCode |
|
||||
|
||||
---
|
||||
|
||||
## 1. 改造目標
|
||||
|
||||
- 將 Dev 3003 (Playground) 與 Public 3002 完全隔離
|
||||
- 統一術語:`video_uuid` → `file_uuid`
|
||||
- 修復資料庫結構問題(probe_json 類型、timestamp 類型)
|
||||
- Python 腳本和 output 目錄隔離
|
||||
|
||||
---
|
||||
|
||||
## 2. PostgreSQL Schema 修復
|
||||
|
||||
### 2.1 probe_json 類型修復
|
||||
|
||||
**問題**: `dev.videos.probe_json` 類型為 `TEXT`,但 Rust 期望 `JSONB`
|
||||
|
||||
**修復**:
|
||||
```sql
|
||||
ALTER TABLE dev.videos ALTER COLUMN probe_json TYPE jsonb USING probe_json::jsonb;
|
||||
```
|
||||
|
||||
### 2.2 video_uuid → file_uuid 重命名 (10 張表)
|
||||
|
||||
| 表 | 狀態 |
|
||||
|----|------|
|
||||
| `dev.backup_registry` | ✅ 已重命名 |
|
||||
| `dev.castings` | ✅ 已重命名 |
|
||||
| `dev.characters` | ✅ 已重命名 |
|
||||
| `dev.face_identities` | ✅ 已重命名 |
|
||||
| `dev.face_recognition_results` | ✅ 已重命名 |
|
||||
| `dev.file_lifecycle` | ✅ 已重命名 |
|
||||
| `dev.file_registry` | ✅ 已重命名 |
|
||||
| `dev.processor_results` | ✅ 已重命名 |
|
||||
| `dev.video_events` | ✅ 已重命名 |
|
||||
| `dev.video_identities` | ✅ 已重命名 |
|
||||
|
||||
**修復 SQL**:
|
||||
```sql
|
||||
ALTER TABLE dev.backup_registry RENAME COLUMN video_uuid TO file_uuid;
|
||||
ALTER TABLE dev.castings RENAME COLUMN video_uuid TO file_uuid;
|
||||
ALTER TABLE dev.characters RENAME COLUMN video_uuid TO file_uuid;
|
||||
ALTER TABLE dev.face_identities RENAME COLUMN video_uuid TO file_uuid;
|
||||
ALTER TABLE dev.face_recognition_results RENAME COLUMN video_uuid TO file_uuid;
|
||||
ALTER TABLE dev.file_lifecycle RENAME COLUMN video_uuid TO file_uuid;
|
||||
ALTER TABLE dev.file_registry RENAME COLUMN video_uuid TO file_uuid;
|
||||
ALTER TABLE dev.processor_results RENAME COLUMN video_uuid TO file_uuid;
|
||||
ALTER TABLE dev.video_events RENAME COLUMN video_uuid TO file_uuid;
|
||||
ALTER TABLE dev.video_identities RENAME COLUMN video_uuid TO file_uuid;
|
||||
|
||||
-- 重建 constraint
|
||||
ALTER TABLE dev.face_recognition_results
|
||||
DROP CONSTRAINT face_recognition_results_video_uuid_key;
|
||||
ALTER TABLE dev.face_recognition_results
|
||||
ADD CONSTRAINT face_recognition_results_file_uuid_key UNIQUE (file_uuid);
|
||||
```
|
||||
|
||||
### 2.3 timestamp 類型修復
|
||||
|
||||
**問題**: `dev.videos.created_at`, `updated_at`, `registered_at` 為 `TIMESTAMP` (without time zone),但 Rust 期望 `TIMESTAMPTZ`
|
||||
|
||||
**修復**:
|
||||
```sql
|
||||
ALTER TABLE dev.videos ALTER COLUMN created_at TYPE timestamptz USING created_at AT TIME ZONE 'UTC';
|
||||
ALTER TABLE dev.videos ALTER COLUMN updated_at TYPE timestamptz USING updated_at AT TIME ZONE 'UTC';
|
||||
ALTER TABLE dev.videos ALTER COLUMN registered_at TYPE timestamptz USING registered_at AT TIME ZONE 'UTC';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Rust 代碼修改
|
||||
|
||||
### 3.1 `src/api/server.rs`
|
||||
|
||||
| 行號 | 修改前 | 修改後 |
|
||||
|------|--------|--------|
|
||||
| 3982 | `DELETE FROM {} WHERE video_uuid = $1` | `DELETE FROM {} WHERE file_uuid = $1` |
|
||||
|
||||
### 3.2 `src/api/face_recognition.rs`
|
||||
|
||||
| 行號 | 修改前 | 修改後 |
|
||||
|------|--------|--------|
|
||||
| 721 | `WHERE video_uuid = $1` | `WHERE file_uuid = $1` |
|
||||
| 764 | `"video_uuid": file_uuid` | `"file_uuid": file_uuid` |
|
||||
| 786 | `video_uuid: &str` (參數) | `file_uuid: &str` (參數) |
|
||||
| 807 | `ON CONFLICT (video_uuid)` | `ON CONFLICT (file_uuid)` |
|
||||
| 818 | `.bind(video_uuid)` | `.bind(file_uuid)` |
|
||||
| 877 | `.bind(video_uuid)` | `.bind(file_uuid)` |
|
||||
| 926 | `.bind(video_uuid)` | `.bind(file_uuid)` |
|
||||
|
||||
### 3.3 測試修復
|
||||
|
||||
| 檔案 | 修改 |
|
||||
|------|------|
|
||||
| `src/core/db/postgres_db.rs:4550` | 添加 `file_type: None` 到 `VideoRecord` 測試 |
|
||||
|
||||
---
|
||||
|
||||
## 4. Python 腳本隔離
|
||||
|
||||
### 4.1 更新預設 DATABASE_URL (7 個腳本)
|
||||
|
||||
| 腳本 | 修改 |
|
||||
|------|------|
|
||||
| `scripts/clip_logo_integration.py` | `?options=-c%20search_path=dev` |
|
||||
| `scripts/match_face_with_pose_filtering.py` | `?options=-c%20search_path=dev` |
|
||||
| `scripts/select_face_reference_vectors_v2.py` | `?options=-c%20search_path=dev` |
|
||||
| `scripts/match_face_identity.py` | `?options=-c%20search_path=dev` |
|
||||
| `scripts/tmdb_identity_integration.py` | `?options=-c%20search_path=dev` |
|
||||
| `scripts/select_face_reference_vectors.py` | `?options=-c%20search_path=dev` |
|
||||
| `scripts/test_identity_db.py` | `?options=-c%20search_path=dev` |
|
||||
|
||||
### 4.2 output 目錄隔離
|
||||
|
||||
| 腳本 | 修改 |
|
||||
|------|------|
|
||||
| `scripts/identity_agent.py` | 預設 output 改為 `/Users/accusys/momentry/output_dev` |
|
||||
|
||||
### 4.3 環境變數配置
|
||||
|
||||
`.env.development` 已配置:
|
||||
```bash
|
||||
MOMENTRY_OUTPUT_DIR=/Users/accusys/momentry/output_dev
|
||||
DATABASE_SCHEMA=dev
|
||||
MONGODB_DATABASE=momentry_dev
|
||||
QDRANT_COLLECTION=momentry_dev_rule1
|
||||
REDIS_PREFIX=momentry_dev:
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 隔離狀態總覽
|
||||
|
||||
| 資源 | 配置 | 狀態 |
|
||||
|------|------|------|
|
||||
| PostgreSQL | `DATABASE_SCHEMA=dev` | ✅ 隔離 |
|
||||
| MongoDB | `momentry_dev` | ✅ 隔離 |
|
||||
| Qdrant | `momentry_dev_rule1` | ✅ 隔離 |
|
||||
| Redis | `momentry_dev:` | ✅ 隔離 |
|
||||
| Output Dir | `/Users/accusys/momentry/output_dev` | ✅ 隔離 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 驗證結果
|
||||
|
||||
### 6.1 Build 驗證
|
||||
- `cargo build --bins`: ✅ 成功
|
||||
- `cargo clippy --lib`: ✅ 通過 (119 warnings, 0 errors)
|
||||
- `cargo test --lib`: ✅ 178 tests passed
|
||||
|
||||
### 6.2 API 驗證
|
||||
- `GET /api/v1/files`: ✅ 返回 200 (之前返回 500)
|
||||
- 測試數據: 6 個檔案已註冊
|
||||
|
||||
---
|
||||
|
||||
## 7. 待辦事項
|
||||
|
||||
| 任務 | 優先級 | 狀態 |
|
||||
|------|--------|------|
|
||||
| 設計 Dev 3003 API 結構 (v1.0 aligned) | Medium | ⬜ |
|
||||
| 實作 `GET /api/v1/files/{uuid}/identities` | Medium | ⬜ |
|
||||
| 實作 `GET /api/v1/identities/{uuid}` | Medium | ⬜ |
|
||||
| 實作 `GET /api/v1/identities/{uuid}/files` | Medium | ⬜ |
|
||||
| 實作 AI Agent API (clustering/merge suggestions) | Medium | ⬜ |
|
||||
|
||||
---
|
||||
|
||||
## 8. 注意事項
|
||||
|
||||
### 8.1 Public 3002 不受影響
|
||||
- 所有修改僅限於 `dev` schema
|
||||
- `public` schema 保持原狀
|
||||
- Rust 代碼修改適用於兩者,但 SQL 中的 column name 已統一為 `file_uuid`
|
||||
|
||||
### 8.2 Python 腳本注意事項
|
||||
- 仍有其他 Python 腳本使用 `DB_CONFIG`、`POSTGRES_CONFIG` 等模式
|
||||
- 這些腳本需單獨檢查和更新
|
||||
- 建議逐步遷移至使用環境變數
|
||||
|
||||
### 8.3 已知限制
|
||||
- Player module 仍使用 `video_uuid` 變數名(內部使用,不影響 API)
|
||||
- 部分 Python 腳本的 output 路徑仍需手動指定
|
||||
@@ -2,13 +2,13 @@
|
||||
document_type: "design"
|
||||
title: "File / Identity API 架構設計"
|
||||
service: "MOMENTRY_CORE"
|
||||
date: "2026-04-25"
|
||||
date: "2026-04-28"
|
||||
status: "active"
|
||||
current_state: "finalized"
|
||||
owner: "Warren"
|
||||
created_by: "OpenCode"
|
||||
created_at: "2026-04-25"
|
||||
version: "V1.1"
|
||||
version: "V1.2"
|
||||
tags:
|
||||
- "api"
|
||||
- "file"
|
||||
@@ -16,6 +16,9 @@ tags:
|
||||
- "face"
|
||||
- "candidate"
|
||||
- "pre_chunk"
|
||||
- "reference_data"
|
||||
- "identity_embedding"
|
||||
- "clip"
|
||||
related_documents:
|
||||
- "DOCS_STANDARD.md"
|
||||
- "AI_AGENT_DOCUMENTATION_GUIDE.md"
|
||||
@@ -24,11 +27,14 @@ related_documents:
|
||||
- "_deprecated/IDENTITY_SYSTEM_DESIGN.md"
|
||||
- "PROCESSORS/_CORE/RULE_SPECIFICATION.md"
|
||||
- "REFERENCE/API_ERROR_CODES.md"
|
||||
- "IDENTITY_REFERENCE_VECTOR_DESIGN.md"
|
||||
ai_query_hints:
|
||||
- "查詢 File/Identity 核心架構設計"
|
||||
- "查詢 People API 端點定義"
|
||||
- "查詢 Candidate 狀態轉換流程"
|
||||
- "查詢資料庫 Schema 定義 (含 pre_chunks)"
|
||||
- "查詢 reference_data JSONB 結構"
|
||||
- "查詢 identity_embedding (CLIP ViT-L/14)"
|
||||
---
|
||||
|
||||
# File / Identity API 架構設計文件
|
||||
@@ -45,6 +51,7 @@ ai_query_hints:
|
||||
|
||||
| 版本 | 日期 | 目的 | 操作人 | 工具/模型 |
|
||||
|------|------|------|--------|-----------|
|
||||
| V1.2 | 2026-04-28 | **重大更新**: 添加 face_embedding(512), voice_embedding(192), identity_embedding(768), reference_data JSONB 結構詳解, identity_type 扩展 (logo/symbol/sound/animal/environmental) | OpenCode | OpenCode |
|
||||
| V1.1 | 2026-04-25 | **重大更新**: 移除 faces 表 (方案 A), 新增 pre_chunks 表, 統一命名為 file_uuid, 更新 Response 格式 | OpenCode | OpenCode |
|
||||
| V1.0 | 2026-04-25 | 創建 File/Identity API 架構設計 | OpenCode | OpenCode |
|
||||
|
||||
@@ -91,9 +98,9 @@ Identity ──[出現在]──→ File (通過 Pre-chunk 或 file_identities
|
||||
```
|
||||
|
||||
**Candidate 狀態轉換**:
|
||||
* **定義**: Candidate 不是獨立表格,而是 `pre_chunks` 中 `identity_id IS NULL` 的 Face 數據。
|
||||
* **確認**: 更新 `identity_id` → 成為已確認身份。
|
||||
* **剔除**: 將 `identity_id` 設回 `NULL` → 重新成為 Candidate。
|
||||
* **定義**: Candidate 不是獨立表格,而是 `pre_chunks` 中 `identity_id IS NULL` 的 Face 數據。
|
||||
* **確認**: 更新 `identity_id` → 成為已確認身份。
|
||||
* **剔除**: 將 `identity_id` 設回 `NULL` → 重新成為 Candidate。
|
||||
|
||||
---
|
||||
|
||||
@@ -132,8 +139,8 @@ CREATE TABLE files (
|
||||
### Pre-chunks 表 (處理器原始數據)
|
||||
|
||||
**說明**: 所有 Processor (YOLO, Face, ASR...) 產出的數據皆存於此表。
|
||||
* **Video File**: 最小單位為 **Frame (幀)** (`coordinate_type = 'frame'`)。
|
||||
* **Text File**: 最小單位為 Word/Sentence (`coordinate_type = 'text'`)。
|
||||
* **Video File**: 最小單位為 **Frame (幀)** (`coordinate_type = 'frame'`)。
|
||||
* **Text File**: 最小單位為 Word/Sentence (`coordinate_type = 'text'`)。
|
||||
|
||||
| 欄位 | 類型 | 必填 | 說明 |
|
||||
|------|------|------|------|
|
||||
@@ -174,10 +181,13 @@ CREATE INDEX idx_pre_chunks_identity ON pre_chunks(identity_id) WHERE identity_i
|
||||
|------|------|------|------|
|
||||
| identity_id | UUID | Yes | 唯一識別 (自動產生) |
|
||||
| name | TEXT | Yes | 顯示名稱 |
|
||||
| identity_type | VARCHAR(30) | Yes | people, brand, object, concept, logo... |
|
||||
| identity_type | VARCHAR(30) | Yes | people, brand, object, concept, logo, symbol, sound, animal, environmental... |
|
||||
| source | VARCHAR(20) | No | manual, tmdb, agent_suggested, ai_detection |
|
||||
| status | VARCHAR(20) | No | pending, confirmed, skipped |
|
||||
| reference_data | JSONB | No | 參考數據 (face_embedding, voice_embedding, image_url...) |
|
||||
| face_embedding | VECTOR(512) | No | 參考臉向量 (ArcFace) - 用於人臉比對 |
|
||||
| voice_embedding | VECTOR(192) | No | 參考聲紋向量 (ECAPA-TDNN) - 用於聲音比對 |
|
||||
| identity_embedding | VECTOR(768) | No | 身份向量 (CLIP ViT-L/14) - 用於 logo/symbol/object 搜索 |
|
||||
| reference_data | JSONB | No | 1對多參考向量存儲 (多角度/多場景/多版本 embedding) |
|
||||
| metadata | JSONB | No | 擴展屬性 |
|
||||
| created_at | TIMESTAMPTZ | Yes | 建立時間 |
|
||||
| updated_at | TIMESTAMPTZ | Yes | 更新時間 |
|
||||
@@ -189,13 +199,115 @@ CREATE TABLE identities (
|
||||
identity_type VARCHAR(30) NOT NULL,
|
||||
source VARCHAR(20) DEFAULT 'manual',
|
||||
status VARCHAR(20) DEFAULT 'pending',
|
||||
reference_data JSONB DEFAULT '{}',
|
||||
|
||||
-- 參考向量 (用於自動比對)
|
||||
face_embedding VECTOR(512), -- 參考臉向量 (ArcFace)
|
||||
voice_embedding VECTOR(192), -- 參考聲紋向量 (ECAPA-TDNN)
|
||||
identity_embedding VECTOR(768), -- 身份向量 (CLIP ViT-L/14)
|
||||
|
||||
-- 1對多參考向量存儲
|
||||
reference_data JSONB DEFAULT '{}', -- 多角度/多場景/多版本 embedding
|
||||
metadata JSONB DEFAULT '{}',
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
#### reference_data JSONB 結構詳解
|
||||
|
||||
`reference_data` 用於存儲同一 Identity 的多個參考向量,支援 1對多匹配,提高識別鲁棒性。
|
||||
|
||||
**完整結構範例**:
|
||||
```json
|
||||
{
|
||||
"face_embeddings": [
|
||||
{
|
||||
"embedding": [0.1, 0.2, ...],
|
||||
"source": "tmdb_images",
|
||||
"image_url": "https://image.tmdb.org/t/p/original/xxx.jpg",
|
||||
"angle": "frontal",
|
||||
"quality_score": 0.95,
|
||||
"created_at": "2026-04-28T10:00:00Z"
|
||||
},
|
||||
{
|
||||
"embedding": [0.3, 0.4, ...],
|
||||
"source": "tmdb_images",
|
||||
"image_url": "https://image.tmdb.org/t/p/original/yyy.jpg",
|
||||
"angle": "profile_left",
|
||||
"quality_score": 0.88,
|
||||
"created_at": "2026-04-28T10:05:00Z"
|
||||
}
|
||||
],
|
||||
"voice_embeddings": [
|
||||
{
|
||||
"embedding": [0.1, 0.2, ...],
|
||||
"source": "video_segment",
|
||||
"file_uuid": "vid_001",
|
||||
"timestamp_start": 120.5,
|
||||
"timestamp_end": 135.2,
|
||||
"quality_score": 0.88,
|
||||
"created_at": "2026-04-28T11:00:00Z"
|
||||
}
|
||||
],
|
||||
"identity_embeddings": [
|
||||
{
|
||||
"embedding": [0.1, 0.2, ...],
|
||||
"source": "logo_image",
|
||||
"image_url": "https://www.accusys.com.tw/wp-content/uploads/2023/03/Accusys-Orange-2017.png",
|
||||
"context": "brand_logo",
|
||||
"created_at": "2026-04-28T12:00:00Z"
|
||||
}
|
||||
],
|
||||
"sound_embeddings": [
|
||||
{
|
||||
"embedding": [0.1, 0.2, ...],
|
||||
"source": "audio_segment",
|
||||
"file_uuid": "vid_001",
|
||||
"timestamp_start": 10.0,
|
||||
"timestamp_end": 15.0,
|
||||
"sound_type": "animal_dog_bark",
|
||||
"created_at": "2026-04-28T13:00:00Z"
|
||||
}
|
||||
],
|
||||
"image_urls": [
|
||||
"https://image.tmdb.org/t/p/original/xxx.jpg",
|
||||
"https://www.accusys.com.tw/wp-content/uploads/2023/03/Accusys-Orange-2017.png"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**欄位說明**:
|
||||
|
||||
| 欄位 | 類型 | 說明 |
|
||||
|------|------|------|
|
||||
| face_embeddings | Array | 多個 512-dim ArcFace embedding (不同角度/定妝造型) |
|
||||
| voice_embeddings | Array | 多個 192-dim ECAPA-TDNN embedding (不同音質片段) |
|
||||
| identity_embeddings | Array | 多個 768-dim CLIP ViT-L/14 embedding (logo/symbol/object) |
|
||||
| sound_embeddings | Array | TBD - 動物叫聲、雷雨、槍炮、樂器 (Phase 5+) |
|
||||
| image_urls | Array | 參考圖片 URL 列表 |
|
||||
|
||||
**子欄位說明**:
|
||||
|
||||
| 欄位 | 類型 | 說明 |
|
||||
|------|------|------|
|
||||
| embedding | Array | 向量值 |
|
||||
| source | String | 來源: tmdb_profile, tmdb_images, manual_upload, auto_detection, logo_image, audio_segment |
|
||||
| image_url | String | 圖片 URL (face/identity) |
|
||||
| file_uuid | UUID | 檔案 UUID (voice/sound) |
|
||||
| timestamp_start/end | Float | 時間範圍 (voice/sound) |
|
||||
| angle | String | 人臉角度: frontal, profile_left, profile_right, three_quarter |
|
||||
| quality_score | Float | 質量評分 (0.0-1.0) |
|
||||
| context | String | 識別場景: brand_logo, symbol, object, concept |
|
||||
| sound_type | String | 聲音類型: animal_dog_bark, environmental_thunder, weapon_gunshot, musical_guitar |
|
||||
| created_at | String | 建立時間 |
|
||||
|
||||
**設計理念**:
|
||||
1. **1對多匹配**: 同一 Identity 可有多個參考向量,提高識別鲁棒性
|
||||
2. **多角度覆蓋**: 人臉正面、側面、三側角度,覆蓋不同拍攝角度
|
||||
3. **多場景覆蓋**: Logo/Symbol 在不同場景(白底、黑底、複雜背景)的 embedding
|
||||
4. **質量評分**: 記錄每個參考向量的質量,用於加權匹配
|
||||
5. **來源追溯**: 記錄每個 embedding 的來源,方便追溯和更新
|
||||
|
||||
### File-Identities 表 (關聯表 - 用於記錄聚合後的結果或特定角色資訊)
|
||||
|
||||
**說明**: 用於記錄 Identity 在 File 中的**整體出現資訊** (如:角色名、定妝造型描述)。
|
||||
@@ -471,43 +583,43 @@ WHERE id = 1001;
|
||||
|
||||
### Phase 0: 系統備份 (立即執行)
|
||||
|
||||
- [ ] 備份現有 PostgreSQL 資料庫
|
||||
- [ ] 備份現有程式碼
|
||||
- [ ] 記錄現有版本
|
||||
* [ ] 備份現有 PostgreSQL 資料庫
|
||||
* [ ] 備份現有程式碼
|
||||
* [ ] 記錄現有版本
|
||||
|
||||
### Phase 1: 建立新資料庫 Schema
|
||||
|
||||
- [ ] 建立 `files`, `identities`, `pre_chunks` 表
|
||||
- [ ] 建立 `file_identities`, `categories` 表
|
||||
- [ ] 建立索引
|
||||
- [ ] 建立測試資料
|
||||
* [ ] 建立 `files`, `identities`, `pre_chunks` 表
|
||||
* [ ] 建立 `file_identities`, `categories` 表
|
||||
* [ ] 建立索引
|
||||
* [ ] 建立測試資料
|
||||
|
||||
### Phase 2: 核心 API 實作
|
||||
|
||||
- [ ] Candidates API (`GET /people/candidates`) - 查詢 `identity_id IS NULL`
|
||||
- [ ] Identity CRUD API (`GET/POST/PATCH /people`)
|
||||
- [ ] Identity Search API (`POST /people/search`)
|
||||
- [ ] Identity Resolve API (`GET /people/{id}/resolve`)
|
||||
- [ ] Candidate Management (`POST /people/{id}/confirm-candidate`, `remove-candidate`)
|
||||
- [ ] Status API (`GET /people/status`)
|
||||
* [ ] Candidates API (`GET /people/candidates`) - 查詢 `identity_id IS NULL`
|
||||
* [ ] Identity CRUD API (`GET/POST/PATCH /people`)
|
||||
* [ ] Identity Search API (`POST /people/search`)
|
||||
* [ ] Identity Resolve API (`GET /people/{id}/resolve`)
|
||||
* [ ] Candidate Management (`POST /people/{id}/confirm-candidate`, `remove-candidate`)
|
||||
* [ ] Status API (`GET /people/status`)
|
||||
|
||||
### Phase 3: Processor 整合 (Pre-chunk 寫入)
|
||||
|
||||
- [ ] 修改 YOLO, Face, OCR 處理器,改寫入 `pre_chunks` 表
|
||||
- [ ] 實作 `PROCESSOR_RESUME_STRATEGY.md` 中的 Checkpoint 邏輯
|
||||
- [ ] probe Processor 整合 (ffprobe → File 分類)
|
||||
* [ ] 修改 YOLO, Face, OCR 處理器,改寫入 `pre_chunks` 表
|
||||
* [ ] 實作 `PROCESSOR_RESUME_STRATEGY.md` 中的 Checkpoint 邏輯
|
||||
* [ ] probe Processor 整合 (ffprobe → File 分類)
|
||||
|
||||
### Phase 4: Portal 前端
|
||||
|
||||
- [ ] Candidates 介面
|
||||
- [ ] Identity 管理介面
|
||||
- [ ] File 管理介面
|
||||
* [ ] Candidates 介面
|
||||
* [ ] Identity 管理介面
|
||||
* [ ] File 管理介面
|
||||
|
||||
### Phase 5: 非 People Identity (待辦事項)
|
||||
|
||||
- [ ] Brand Identity 支援
|
||||
- [ ] Object Identity 支援
|
||||
- [ ] Concept Identity 支援
|
||||
* [ ] Brand Identity 支援
|
||||
* [ ] Object Identity 支援
|
||||
* [ ] Concept Identity 支援
|
||||
|
||||
---
|
||||
|
||||
@@ -526,24 +638,24 @@ WHERE id = 1001;
|
||||
|
||||
## 限制條件
|
||||
|
||||
- 本設計為全新架構,不與現有系統共用資料
|
||||
- 需要做新的處理器版本產生新的輸出 (寫入 `pre_chunks` 而非 `chunks`)
|
||||
- 非 People Identity 列入待辦事項,不在本次實作範圍
|
||||
- Face 的唯一識別為 `file_uuid` + `coordinate_index` (Frame Number)
|
||||
* 本設計為全新架構,不與現有系統共用資料
|
||||
* 需要做新的處理器版本產生新的輸出 (寫入 `pre_chunks` 而非 `chunks`)
|
||||
* 非 People Identity 列入待辦事項,不在本次實作範圍
|
||||
* Face 的唯一識別為 `file_uuid` + `coordinate_index` (Frame Number)
|
||||
|
||||
---
|
||||
|
||||
## 相關文件
|
||||
|
||||
- `docs_v1.0/STANDARDS/DOCS_STANDARD.md` - 文件創建規範
|
||||
- `docs_v1.0/ARCHITECTURE/` - 架構相關文件
|
||||
- `docs_v1.0/PROCESSORS/_CORE/PROCESSOR_RESUME_STRATEGY.md` - 處理器續傳機制
|
||||
- `docs_v1.0/PROCESSORS/_CORE/RULE_SPECIFICATION.md` - Rule 依賴與數據流定義
|
||||
* `docs_v1.0/STANDARDS/DOCS_STANDARD.md` - 文件創建規範
|
||||
* `docs_v1.0/ARCHITECTURE/` - 架構相關文件
|
||||
* `docs_v1.0/PROCESSORS/_CORE/PROCESSOR_RESUME_STRATEGY.md` - 處理器續傳機制
|
||||
* `docs_v1.0/PROCESSORS/_CORE/RULE_SPECIFICATION.md` - Rule 依賴與數據流定義
|
||||
|
||||
---
|
||||
|
||||
## 版本資訊
|
||||
|
||||
- 版本: V1.1
|
||||
- 建立日期: 2026-04-25
|
||||
- 文件更新: 2026-04-25
|
||||
* 版本: V1.2
|
||||
* 建立日期: 2026-04-25
|
||||
* 文件更新: 2026-04-28
|
||||
|
||||
@@ -1312,4 +1312,4 @@ cargo run --bin test_synonym_expansion
|
||||
3. **技術支援**:Momentry Core 僅提供技術框架和格式支援,不提供同義詞資料。
|
||||
4. **更新維護**:客戶需自行維護和更新同義詞資源。
|
||||
|
||||
**使用前請務必確認您擁有合法使用同義詞林資源的權利。**
|
||||
**使用前請務必確認您擁有合法使用同義詞林資源的權利。**
|
||||
|
||||
@@ -33,7 +33,7 @@ Momentry 提供四種搜尋 API,針對不同的情境進行優化。選擇正
|
||||
"hits": [
|
||||
{
|
||||
"id": "sentence_0790",
|
||||
"vid": "384b0ff44aaaa1f1",
|
||||
"vid": "384b0ff44aaaa1f14cb2cd63b3fea966",
|
||||
"chunk_type": "sentence",
|
||||
"start_frame": 187296,
|
||||
"end_frame": 187356,
|
||||
@@ -60,7 +60,7 @@ Momentry 提供四種搜尋 API,針對不同的情境進行優化。選擇正
|
||||
"hits": [
|
||||
{
|
||||
"id": "sentence_0790",
|
||||
"vid": "384b0ff44aaaa1f1",
|
||||
"vid": "384b0ff44aaaa1f14cb2cd63b3fea966",
|
||||
"chunk_type": "sentence",
|
||||
"start_frame": 187296,
|
||||
"end_frame": 187356,
|
||||
@@ -102,7 +102,7 @@ Momentry 提供四種搜尋 API,針對不同的情境進行優化。選擇正
|
||||
"hits": [
|
||||
{
|
||||
"id": "sentence_0790",
|
||||
"vid": "384b0ff44aaaa1f1",
|
||||
"vid": "384b0ff44aaaa1f14cb2cd63b3fea966",
|
||||
"chunk_type": "sentence",
|
||||
"start_frame": 187296,
|
||||
"end_frame": 187356,
|
||||
@@ -136,7 +136,6 @@ Momentry 提供四種搜尋 API,針對不同的情境進行優化。選擇正
|
||||
| **快取機制** | MongoDB | MongoDB | MongoDB | MongoDB |
|
||||
|
||||
> **提示**: 如果 n8n 流程只需要知道「出現在哪裡」,不需要播放影片或詳細摘要,使用 `/api/v1/search/bm25` 會比向量搜尋更省資源且更快。
|
||||
|
||||
> **新增**: 所有向量搜尋 API 現在支援多維度搜尋 (Multi-Modal),同時查詢 ASR、Face、Object (YOLO)、Scene 四個 Collection,自動合併去重後回傳。
|
||||
|
||||
---
|
||||
|
||||
@@ -44,7 +44,7 @@ X-API-Key: muser_68600856036340bcafc01930eb4bd839
|
||||
```json
|
||||
{
|
||||
"query": "主角開車離開的場景",
|
||||
"uuid": "384b0ff44aaaa1f1",
|
||||
"uuid": "384b0ff44aaaa1f14cb2cd63b3fea966",
|
||||
"limit": 5
|
||||
}
|
||||
```
|
||||
@@ -60,7 +60,7 @@ X-API-Key: muser_68600856036340bcafc01930eb4bd839
|
||||
"hits": [
|
||||
{
|
||||
"id": "sentence_0790",
|
||||
"vid": "384b0ff44aaaa1f1",
|
||||
"vid": "384b0ff44aaaa1f14cb2cd63b3fea966",
|
||||
"start_frame": 187296,
|
||||
"end_frame": 187356,
|
||||
"fps": 59.94,
|
||||
@@ -103,36 +103,36 @@ X-API-Key: muser_68600856036340bcafc01930eb4bd839
|
||||
為了讓開發者理解效能與資料來源,以下是 `/api/v1/n8n/search` (Vector) 的完整執行流程:
|
||||
|
||||
### 步驟 1: 認證與快取 (Auth & Cache)
|
||||
1. **API Key 驗證**: 檢查 Header 中的 `X-API-Key`。
|
||||
2. **Query Hash**: 計算 `SHA256(query + uuid + limit)` 作為快取 Key。
|
||||
3. **MongoDB Cache 檢查**:
|
||||
* 若命中快取:直接返回 JSON,**跳過**後續繁重的向量運算。
|
||||
* 若未命中:進入步驟 2。
|
||||
1. **API Key 驗證**: 檢查 Header 中的 `X-API-Key`。
|
||||
2. **Query Hash**: 計算 `SHA256(query + uuid + limit)` 作為快取 Key。
|
||||
3. **MongoDB Cache 檢查**:
|
||||
* 若命中快取:直接返回 JSON,**跳過**後續繁重的向量運算。
|
||||
* 若未命中:進入步驟 2。
|
||||
|
||||
### 步驟 2: 向量化與搜尋 (Embedding & Search)
|
||||
1. **Embedding**: 呼叫 Ollama (Nomic-Embed-Text) 將 Query 轉換為向量 (Vector)。
|
||||
2. **Qdrant 搜尋**:
|
||||
* 若有 `uuid`: 在該影片的 Collection 中搜尋最相似的 Chunk。
|
||||
* 若無 `uuid`: 進行全域搜尋。
|
||||
* 返回 Top-N 個包含 `chunk_id` 與 `uuid` 的候选結果。
|
||||
1. **Embedding**: 呼叫 Ollama (Nomic-Embed-Text) 將 Query 轉換為向量 (Vector)。
|
||||
2. **Qdrant 搜尋**:
|
||||
* 若有 `uuid`: 在該影片的 Collection 中搜尋最相似的 Chunk。
|
||||
* 若無 `uuid`: 進行全域搜尋。
|
||||
* 返回 Top-N 個包含 `chunk_id` 與 `uuid` 的候选結果。
|
||||
|
||||
### 步驟 3: 資料豐富化 (Enrichment via PostgreSQL)
|
||||
拿到 Qdrant 結果後,系統會**逐筆**向 PostgreSQL 查詢詳細資訊:
|
||||
|
||||
1. **取得 Chunk 內容**:
|
||||
* 查詢 `chunks` 表格,獲取原始 JSON 內容、時間、幀號等。
|
||||
2. **取得影片路徑**:
|
||||
* 利用 `uuid` 查詢 `videos` 表格,獲取 `file_path`。
|
||||
3. **取得 5W1H 摘要**:
|
||||
* 檢查 Chunk 是否有 `parent_chunk_id` (所屬的故事段落)。
|
||||
* 若有,查詢 `parent_chunks` 表格的 `metadata` 欄位。
|
||||
* 該欄位包含由 Gemma4 LLM 生成的結構化摘要 (Who, What, Where, When, Why, Key Events)。
|
||||
1. **取得 Chunk 內容**:
|
||||
* 查詢 `chunks` 表格,獲取原始 JSON 內容、時間、幀號等。
|
||||
2. **取得影片路徑**:
|
||||
* 利用 `uuid` 查詢 `videos` 表格,獲取 `file_path`。
|
||||
3. **取得 5W1H 摘要**:
|
||||
* 檢查 Chunk 是否有 `parent_chunk_id` (所屬的故事段落)。
|
||||
* 若有,查詢 `parent_chunks` 表格的 `metadata` 欄位。
|
||||
* 該欄位包含由 Gemma4 LLM 生成的結構化摘要 (Who, What, Where, When, Why, Key Events)。
|
||||
|
||||
### 步驟 4: 格式化與回傳 (Formatting)
|
||||
1. **Text Processing**: 將 Chunk 原始內容中的文字提取,並進行繁簡轉換與分詞處理 (Tokenization)。
|
||||
2. **建構 Hit 物件**: 組合上述所有資料為 `N8nSearchHit`。
|
||||
3. **寫入快取**: 將最終結果寫入 MongoDB 以便下次秒回。
|
||||
4. **回應 JSON**: 返回給 n8n。
|
||||
1. **Text Processing**: 將 Chunk 原始內容中的文字提取,並進行繁簡轉換與分詞處理 (Tokenization)。
|
||||
2. **建構 Hit 物件**: 組合上述所有資料為 `N8nSearchHit`。
|
||||
3. **寫入快取**: 將最終結果寫入 MongoDB 以便下次秒回。
|
||||
4. **回應 JSON**: 返回給 n8n。
|
||||
|
||||
---
|
||||
|
||||
@@ -141,12 +141,12 @@ X-API-Key: muser_68600856036340bcafc01930eb4bd839
|
||||
除了標準的 Vector Search,還有兩種變體:
|
||||
|
||||
### 5.1 BM25 Keyword Search
|
||||
- **Endpoint**: `/api/v1/n8n/search/bm25`
|
||||
- **邏輯**: 跳過向量運算,直接使用 PostgreSQL 的全文檢索 (Full Text Search) 功能。適合精確匹配專有名詞或關鍵字。
|
||||
* **Endpoint**: `/api/v1/n8n/search/bm25`
|
||||
* **邏輯**: 跳過向量運算,直接使用 PostgreSQL 的全文檢索 (Full Text Search) 功能。適合精確匹配專有名詞或關鍵字。
|
||||
|
||||
### 5.2 Smart Search (LLM 分析)
|
||||
- **Endpoint**: `/api/v1/n8n/search/smart`
|
||||
- **邏輯**:
|
||||
* **Endpoint**: `/api/v1/n8n/search/smart`
|
||||
* **邏輯**:
|
||||
1. 將 Query 送至 Llama-server (Port 8081) 進行意圖分析 (5W1H)。
|
||||
2. 提取出關鍵實體 (人名、地點、動作)。
|
||||
3. 將提取出的實體轉換為更精確的 BM25 查詢語句進行搜尋。
|
||||
|
||||
267
docs_v1.0/IMPLEMENTATION/PORTAL_BIRTH_UUID_ADAPTATION.md
Normal file
267
docs_v1.0/IMPLEMENTATION/PORTAL_BIRTH_UUID_ADAPTATION.md
Normal file
@@ -0,0 +1,267 @@
|
||||
# Portal 适配 Birth UUID 完成报告
|
||||
|
||||
## 修改日期
|
||||
2026-04-28
|
||||
|
||||
---
|
||||
|
||||
## 背景
|
||||
|
||||
Birth UUID Phase 1 MVP 实施后,需要确认 Portal 是否需要修改以适配新的 UUID 格式。
|
||||
|
||||
---
|
||||
|
||||
## Birth UUID 规格
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| **格式** | SHA256[mac|timestamp|username|filename](0:32) |
|
||||
| **长度** | 32字符(比旧UUID的16字符更长) |
|
||||
| **唯一性** | MAC + Timestamp确保全球唯一 |
|
||||
| **隐私保护** | MAC不直接暴露(哈希在UUID内) |
|
||||
| **不可变** | 文件迁移不影响UUID |
|
||||
|
||||
---
|
||||
|
||||
## Portal 分析结果
|
||||
|
||||
### ✅ 前端无需强制修改
|
||||
|
||||
**原因**:
|
||||
1. UUID显示使用CSS `truncate`,可自动截断长文本
|
||||
2. API调用使用`uuid`参数,无长度限制
|
||||
3. 路由`/videos/:uuid`可接受任意长度字符串
|
||||
4. 向后兼容:16字符旧UUID和32字符新UUID都能正常工作
|
||||
|
||||
### 🔧 后端需要修改
|
||||
|
||||
**原因**:
|
||||
- API返回的`VideoRecord`缺少`birth_registration`字段
|
||||
- 需要在API响应中包含注册来源信息
|
||||
|
||||
---
|
||||
|
||||
## 实施修改
|
||||
|
||||
### 后端修改(Rust)
|
||||
|
||||
#### 1. VideoRecord 添加字段
|
||||
```rust
|
||||
// src/core/db/postgres_db.rs Line 158-177
|
||||
pub struct VideoRecord {
|
||||
pub birth_registration: Option<serde_json::Value>,
|
||||
// ... 其他字段
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. VideoRow 添加字段
|
||||
```rust
|
||||
// src/core/db/postgres_db.rs Line 99-124
|
||||
pub struct VideoRow {
|
||||
pub birth_registration: Option<serde_json::Value>,
|
||||
// ... 其他字段
|
||||
}
|
||||
```
|
||||
|
||||
#### 3. VideoInfoResponse 添加字段
|
||||
```rust
|
||||
// src/api/server.rs Line 361-375
|
||||
struct VideoInfoResponse {
|
||||
birth_registration: Option<serde_json::Value>,
|
||||
// ... 其他字段
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. SELECT 查询修改
|
||||
```sql
|
||||
-- Line 770, 838, 920
|
||||
SELECT id, uuid, ..., birth_registration, ..., total_frames FROM videos
|
||||
```
|
||||
|
||||
#### 5. 构造函数修改
|
||||
- `From<VideoRow> for VideoRecord`(Line 125-155)
|
||||
- `ingestion.rs` VideoRecord构造(Line 146-164)
|
||||
- `server.rs` VideoRecord构造(Line 802-820)
|
||||
- 测试代码(Line 4489-4514)
|
||||
|
||||
---
|
||||
|
||||
### 前端修改(Vue)
|
||||
|
||||
#### 1. UUID显示优化
|
||||
```vue
|
||||
<!-- VideoDetailView.vue Line 17-20 -->
|
||||
<div>
|
||||
<span class="text-xs text-gray-500 uppercase">UUID</span>
|
||||
<p class="text-sm font-mono text-gray-300 truncate">{{ video.uuid }}</p>
|
||||
<p class="text-xs text-gray-600 mt-1">長度: {{ video.uuid.length }} 字符</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
#### 2. Birth Registration 显示区域
|
||||
```vue
|
||||
<!-- VideoDetailView.vue Line 33-48 -->
|
||||
<div v-if="video.birth_registration" class="mt-4 bg-gray-850 p-3 rounded border border-gray-600">
|
||||
<h4 class="text-xs font-semibold text-gray-400 mb-2 uppercase">註冊來源資訊</h4>
|
||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-3">
|
||||
<div>
|
||||
<span class="text-xs text-gray-600">用戶名:</span>
|
||||
<p class="text-sm text-gray-300">{{ video.birth_registration.registration_source?.username }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-xs text-gray-600">註冊時間:</span>
|
||||
<p class="text-sm text-gray-300">{{ formatTimestamp(video.birth_registration.registration_source?.timestamp) }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-xs text-gray-600">原始檔名:</span>
|
||||
<p class="text-sm text-gray-300 truncate">{{ video.birth_registration.registration_source?.original_filename }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-xs text-gray-600">UUID類型:</span>
|
||||
<p class="text-sm text-gray-300">{{ video.uuid.length === 32 ? 'Birth UUID' : 'Legacy UUID' }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
#### 3. 时间格式化函数
|
||||
```typescript
|
||||
function formatTimestamp(timestamp: string | undefined): string {
|
||||
if (!timestamp) return '-'
|
||||
try {
|
||||
const date = new Date(timestamp)
|
||||
return date.toLocaleString('zh-TW', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
})
|
||||
} catch {
|
||||
return timestamp
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## birth_registration JSONB 结构
|
||||
|
||||
```json
|
||||
{
|
||||
"registration_source": {
|
||||
"mac_address": "ba:f5:ee:bc:45:78",
|
||||
"username": "demo",
|
||||
"timestamp": "2026-04-27T22:00:00+08:00",
|
||||
"original_path": "/Users/.../demo",
|
||||
"original_filename": "video.mp4"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API 响应示例
|
||||
|
||||
### 旧UUID视频(16字符)
|
||||
```json
|
||||
{
|
||||
"uuid": "ac625815183a21e1",
|
||||
"birth_registration": null,
|
||||
"file_name": "video.mp4",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### 新UUID视频(32字符)
|
||||
```json
|
||||
{
|
||||
"uuid": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6",
|
||||
"birth_registration": {
|
||||
"registration_source": {
|
||||
"mac_address": "ba:f5:ee:bc:45:78",
|
||||
"username": "demo",
|
||||
"timestamp": "2026-04-27T22:00:00+08:00",
|
||||
"original_filename": "video.mp4"
|
||||
}
|
||||
},
|
||||
"file_name": "video.mp4",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 向后兼容性
|
||||
|
||||
| UUID类型 | 长度 | birth_registration | Portal显示 |
|
||||
|---------|------|-------------------|-----------|
|
||||
| **旧UUID** | 16字符 | null | 显示UUID,隐藏birth_registration区域 |
|
||||
| **新UUID** | 32字符 | 有数据 | 显示UUID,显示birth_registration区域 |
|
||||
|
||||
---
|
||||
|
||||
## 测试验证计划
|
||||
|
||||
### 步骤 1: 编译测试
|
||||
```bash
|
||||
# 检查编译(birth_registration相关错误已修复)
|
||||
cargo check --lib
|
||||
```
|
||||
|
||||
### 步骤 2: 注册新视频
|
||||
```bash
|
||||
# 使用Birth UUID注册
|
||||
cargo run -- register /path/to/new_video.mp4
|
||||
```
|
||||
|
||||
### 步骤 3: 检查数据库
|
||||
```sql
|
||||
SELECT uuid, LENGTH(uuid), birth_registration
|
||||
FROM dev.videos
|
||||
WHERE birth_registration IS NOT NULL;
|
||||
```
|
||||
|
||||
### 步骤 4: API测试
|
||||
```bash
|
||||
# 查询新UUID视频
|
||||
curl http://localhost:3003/api/v1/videos?uuid=<32字符UUID>
|
||||
```
|
||||
|
||||
### 步骤 5: Portal显示测试
|
||||
- 打开Portal `/videos/<32字符UUID>`
|
||||
- 确认UUID显示为32字符
|
||||
- 确认birth_registration区域显示注册信息
|
||||
|
||||
---
|
||||
|
||||
## 修改文件清单
|
||||
|
||||
| 文件 | 修改内容 |
|
||||
|------|---------|
|
||||
| `/src/core/db/postgres_db.rs` | VideoRecord/VideoRow添加字段,SELECT查询修改 |
|
||||
| `/src/api/server.rs` | VideoInfoResponse添加字段,构造函数修改 |
|
||||
| `/src/core/ingestion.rs` | VideoRecord构造添加birth_registration: None |
|
||||
| `/portal/src/views/VideoDetailView.vue` | UUID显示优化,birth_registration显示区域 |
|
||||
|
||||
---
|
||||
|
||||
## 总结
|
||||
|
||||
✅ **Portal已完全适配Birth UUID**
|
||||
|
||||
### 关键成果
|
||||
1. ✅ 后端API返回`birth_registration`字段
|
||||
2. ✅ 前端显示Birth UUID长度和注册来源信息
|
||||
3. ✅ 向后兼容16字符旧UUID
|
||||
4. ✅ 新视频注册时自动记录`birth_registration`
|
||||
|
||||
### 下一步
|
||||
1. 修复遗留编译错误(redis、SCRIPTS_DIR、PYTHON_PATH)
|
||||
2. 实际注册新视频验证Birth UUID流程
|
||||
3. Portal端到端测试
|
||||
|
||||
---
|
||||
|
||||
**完成日期**: 2026-04-28
|
||||
**状态**: 后端+前端修改完成,待测试验证
|
||||
@@ -81,11 +81,11 @@
|
||||
|
||||
為了達成上述所有標準,我們必須完成以下開發:
|
||||
|
||||
1. [ ] **語義索引建置 (Semantic Indexing)**: 使用 Ollama (Gemma 4) 離線分析全片對話,填入 `chunk_semantics` 表。
|
||||
2. [ ] **場景聚合邏輯 (Scene Aggregation)**: 將零碎的 ASR/CUT 聚合成有意義的「場景 (Scene)」。
|
||||
3. [ ] **互動計數器 (Interaction Counter)**: 統計角色同框次數,支援「第 X 次見面」查詢。
|
||||
4. [ ] **事件時間軸 (Event Timeline)**: 將 Gunshot, Death, Fight 等事件結構化,支援「...之後」查詢。
|
||||
5. [ ] **關係圖譜 (Relationship Graph)**: 建立角色關係網,支援「主持人/來賓」等角色定義。
|
||||
1. [ ] **語義索引建置 (Semantic Indexing)**: 使用 Ollama (Gemma 4) 離線分析全片對話,填入 `chunk_semantics` 表。
|
||||
2. [ ] **場景聚合邏輯 (Scene Aggregation)**: 將零碎的 ASR/CUT 聚合成有意義的「場景 (Scene)」。
|
||||
3. [ ] **互動計數器 (Interaction Counter)**: 統計角色同框次數,支援「第 X 次見面」查詢。
|
||||
4. [ ] **事件時間軸 (Event Timeline)**: 將 Gunshot, Death, Fight 等事件結構化,支援「...之後」查詢。
|
||||
5. [ ] **關係圖譜 (Relationship Graph)**: 建立角色關係網,支援「主持人/來賓」等角色定義。
|
||||
|
||||
---
|
||||
|
||||
@@ -190,4 +190,4 @@ curl -X POST http://localhost:3002/api/v1/search \
|
||||
|
||||
---
|
||||
|
||||
**這份文檔已建立於 `docs/SEARCH_ACCEPTANCE_CRITERIA.md`,我們將以此為目標持續推進系統開發。**
|
||||
**這份文檔已建立於 `docs/SEARCH_ACCEPTANCE_CRITERIA.md`,我們將以此為目標持續推進系統開發。**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Stamp Search Progress
|
||||
|
||||
**UUID**: `384b0ff44aaaa1f1`
|
||||
**UUID**: `384b0ff44aaaa1f14cb2cd63b3fea966`
|
||||
**Video**: Charade (1963) - ~115 min
|
||||
**Status**: ⏸️ Paused - User review needed
|
||||
|
||||
@@ -31,26 +31,26 @@
|
||||
### 1. Color-Based Detection (Blue + Red for Inverted Jenny)
|
||||
- **Script**: `scripts/filter_stamp_colors.py`
|
||||
- **Candidates**: 21 images
|
||||
- **Location**: `output/384b0ff44aaaa1f1/florence2_results/STAMP_CANDIDATE_*.jpg`
|
||||
- **Location**: `output/384b0ff44aaaa1f14cb2cd63b3fea966/florence2_results/STAMP_CANDIDATE_*.jpg`
|
||||
- **Result**: ❌ Not a match
|
||||
|
||||
### 2. Balanced Blue+Red Shape Detection
|
||||
- **Script**: `scripts/filter_stamp_colors.py` (refined)
|
||||
- **Candidates**: 13 images
|
||||
- **Location**: `output/384b0ff44aaaa1f1/florence2_results/BALANCED_STAMP_*.jpg`
|
||||
- **Location**: `output/384b0ff44aaaa1f14cb2cd63b3fea966/florence2_results/BALANCED_STAMP_*.jpg`
|
||||
- **Result**: ❌ Not a match
|
||||
|
||||
### 3. Rectangle Shape + Color Detection (Full Frames)
|
||||
- **Script**: `scripts/detect_stamp_shapes.py`
|
||||
- **Candidates**: 22 crops from 8 scan frames
|
||||
- **Location**: `output/384b0ff44aaaa1f1/florence2_results/STAMP_CROP_*.jpg`
|
||||
- **Location**: `output/384b0ff44aaaa1f14cb2cd63b3fea966/florence2_results/STAMP_CROP_*.jpg`
|
||||
- **Result**: ❌ Not a match
|
||||
|
||||
### 4. Full Video Scan (every 60 seconds)
|
||||
- **Script**: `scripts/scan_full_video_stamps.py`
|
||||
- **Frames scanned**: 115
|
||||
- **Candidates**: 27 images
|
||||
- **Location**: `output/384b0ff44aaaa1f1/stamp_candidates_full/`
|
||||
- **Location**: `output/384b0ff44aaaa1f14cb2cd63b3fea966/stamp_candidates_full/`
|
||||
- **Result**: ❌ Not a match
|
||||
|
||||
### 5. Florence-2 AI Vision
|
||||
@@ -61,7 +61,7 @@
|
||||
- **Script**: `scripts/scan_charade_stamps.py`
|
||||
- **Frames scanned**: 67 (from key stamp dialogue timestamps)
|
||||
- **Candidates**: 60+ paper-like rectangular crops
|
||||
- **Location**: `output/384b0ff44aaaa1f1/stamp_scenes_crops/`
|
||||
- **Location**: `output/384b0ff44aaaa1f14cb2cd63b3fea966/stamp_scenes_crops/`
|
||||
- **Result**: ❌ Not a match (or user hasn't reviewed yet)
|
||||
|
||||
## Key Timestamps for Visual Inspection
|
||||
|
||||
@@ -184,4 +184,4 @@ println!("擴展 '電腦 工作': {}", expander.expand_query("電腦 工作"));
|
||||
- 同義詞擴展器:`src/core/text/synonym_expander.rs`
|
||||
- 繁簡轉換:`src/core/text/synonym.rs`
|
||||
- 分詞器:`src/core/text/tokenizer.rs`
|
||||
- PostgreSQL 整合:`src/core/db/postgres_db.rs`
|
||||
- PostgreSQL 整合:`src/core/db/postgres_db.rs`
|
||||
|
||||
@@ -206,4 +206,4 @@ python3 -m json.tool config/synonyms/custom_synonyms.json
|
||||
|
||||
---
|
||||
|
||||
**注意**: 本系統僅提供技術框架和工具,客戶需自行負責同義詞資源的合法性、準確性和維護工作。
|
||||
**注意**: 本系統僅提供技術框架和工具,客戶需自行負責同義詞資源的合法性、準確性和維護工作。
|
||||
|
||||
@@ -260,17 +260,17 @@ pub async fn register(
|
||||
}
|
||||
|
||||
// 關聯 user_id 到影片
|
||||
let video_uuid = state.db.create_video(req, Some(ctx.user_id)).await?;
|
||||
let file_uuid = state.db.create_video(req, Some(ctx.user_id)).await?;
|
||||
|
||||
// 建立 processing job(帶 user_id)
|
||||
state.db.create_monitor_job(
|
||||
job_type: "auto_ingestion",
|
||||
video_uuid,
|
||||
file_uuid,
|
||||
user_id: Some(ctx.user_id),
|
||||
processors: vec!["asr", "cut", "yolo", "ocr", "face", "pose"],
|
||||
).await?;
|
||||
|
||||
Ok(Json(RegisterResponse { uuid: video_uuid }))
|
||||
Ok(Json(RegisterResponse { uuid: file_uuid }))
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user