529 lines
12 KiB
Markdown
529 lines
12 KiB
Markdown
# Momentry Core API 安裝指南
|
||
|
||
| 項目 | 內容 |
|
||
|------|------|
|
||
| 建立者 | Warren |
|
||
| 建立時間 | 2026-03-18 |
|
||
| 文件版本 | V1.3 |
|
||
|
||
---
|
||
|
||
## 版本歷史
|
||
|
||
| 版本 | 日期 | 目的 | 操作人 | 工具/模型 |
|
||
|------|------|------|--------|-----------|
|
||
| V1.0 | 2026-03-18 | 創建文件 | Warren | OpenCode / MiniMax M2.5 |
|
||
| V1.1 | 2026-03-23 | 更新端點與實際一致 | OpenCode | - |
|
||
| V1.2 | 2026-03-25 | 新增快取/刪除 API | OpenCode | - |
|
||
| V1.3 | 2026-03-26 | 修正認證聲明與API回應格式 | OpenCode | - |
|
||
|
||
---
|
||
|
||
## Base URL
|
||
|
||
| 環境 | URL | 說明 |
|
||
|------|-----|------|
|
||
| **本地開發** | `http://localhost:3002` | 直接訪問 API,繞過反向代理 |
|
||
| **外部訪問** | `https://api.momentry.ddns.net` | 通過 Caddy 反向代理訪問,需網路可達 |
|
||
|
||
> **Note:** Port 3000 is used by Gitea. Momentry API server runs on **port 3002**.
|
||
|
||
### URL 使用時機
|
||
|
||
| 情境 | 建議 URL |
|
||
|------|----------|
|
||
| 本地開發/測試 | `http://localhost:3002` |
|
||
| n8n workflow | `https://api.momentry.ddns.net` |
|
||
| 外部系統整合 | `https://api.momentry.ddns.net` |
|
||
| 反向代理有問題時 | `http://localhost:3002` (繞過代理) |
|
||
|
||
## Authentication
|
||
|
||
**API Key 認證:**
|
||
|
||
所有 `/api/v1/*` 端點需要 `X-API-Key` header 進行認證。
|
||
|
||
**公開端點:**
|
||
- `GET /health` - 健康檢查
|
||
- `GET /health/detailed` - 詳細健康檢查
|
||
|
||
**認證格式:**
|
||
```bash
|
||
curl -H "X-API-Key: YOUR_API_KEY" http://localhost:3002/api/v1/videos
|
||
```
|
||
|
||
**API Key 管理:**
|
||
- 使用 `/api/v1/api-keys` 端點管理 API Keys
|
||
- 詳細說明請參考 [API Key Management Guide](../docs/API_KEY_MANAGEMENT.md)
|
||
|
||
---
|
||
|
||
## Endpoints
|
||
|
||
### 1. Register Video
|
||
Register a video file to the system.
|
||
|
||
**Endpoint:** `POST /api/v1/register`
|
||
|
||
**Request Body:**
|
||
```json
|
||
{
|
||
"path": "/path/to/video.mp4"
|
||
}
|
||
```
|
||
|
||
| Field | Type | Required | Description |
|
||
|-------|------|----------|-------------|
|
||
| `path` | string | Yes | Absolute path to video file |
|
||
|
||
**Response (200):**
|
||
```json
|
||
{
|
||
"uuid": "5dea6618a606e7c7",
|
||
"video_id": 1,
|
||
"job_id": 10,
|
||
"file_name": "video.mp4",
|
||
"duration": 120.5,
|
||
"width": 1920,
|
||
"height": 1080,
|
||
"already_exists": false
|
||
}
|
||
```
|
||
|
||
**Example:**
|
||
```bash
|
||
curl -X POST http://localhost:3002/api/v1/register \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-API-Key: YOUR_API_KEY" \
|
||
-d '{"path": "/Users/accusys/test_video/BigBuckBunny_320x180.mp4"}'
|
||
```
|
||
|
||
---
|
||
|
||
### 2. Process Video (CLI)
|
||
Process video to generate ASR, CUT, YOLO, OCR, Face, Pose data.
|
||
|
||
**Note:** This is a CLI command, not an HTTP endpoint.
|
||
|
||
```bash
|
||
# Process video by UUID
|
||
cargo run --bin momentry -- process 5dea6618a606e7c7
|
||
|
||
# Or process by file path
|
||
cargo run --bin momentry -- process /path/to/video.mp4
|
||
```
|
||
|
||
---
|
||
|
||
### 3. Get Progress
|
||
Get real-time processing progress via Redis.
|
||
|
||
**Endpoint:** `GET /api/v1/progress/:uuid`
|
||
|
||
| Parameter | Type | Description |
|
||
|-----------|------|-------------|
|
||
| `uuid` | path | Video UUID (16 characters) |
|
||
|
||
**Response (200):**
|
||
```json
|
||
{
|
||
"uuid": "5dea6618a606e7c7",
|
||
"processors": [
|
||
{
|
||
"name": "asr",
|
||
"status": "complete",
|
||
"current": 0,
|
||
"total": 0,
|
||
"message": "7 segments"
|
||
},
|
||
{
|
||
"name": "cut",
|
||
"status": "complete",
|
||
"current": 134,
|
||
"total": 134,
|
||
"message": "134 scenes"
|
||
},
|
||
{
|
||
"name": "yolo",
|
||
"status": "progress",
|
||
"current": 5000,
|
||
"total": 14315,
|
||
"message": "frame 5000"
|
||
},
|
||
{
|
||
"name": "ocr",
|
||
"status": "pending",
|
||
"current": 0,
|
||
"total": 0,
|
||
"message": ""
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
**Processor Status Values:**
|
||
- `pending` - Not started
|
||
- `info` - Starting/info message
|
||
- `progress` - In progress
|
||
- `complete` - Finished
|
||
- `error` - Failed
|
||
|
||
**Example:**
|
||
```bash
|
||
# Get progress for specific video
|
||
curl -H "X-API-Key: YOUR_API_KEY" http://localhost:3002/api/v1/progress/5dea6618a606e7c7
|
||
```
|
||
|
||
---
|
||
|
||
### 4. Natural Language Search
|
||
Search video chunks using natural language queries (RAG).
|
||
|
||
**Endpoint:** `POST /api/v1/search`
|
||
|
||
**Request Body:**
|
||
```json
|
||
{
|
||
"query": "What is the person saying about machine learning?",
|
||
"limit": 10,
|
||
"uuid": "5dea6618a606e7c7"
|
||
}
|
||
```
|
||
|
||
| Field | Type | Required | Description |
|
||
|-------|------|----------|-------------|
|
||
| `query` | string | Yes | Natural language search query |
|
||
| `limit` | integer | No | Max results (default: 10) |
|
||
| `uuid` | string | No | Filter by specific video UUID |
|
||
|
||
**Response (200):**
|
||
```json
|
||
{
|
||
"results": [
|
||
{
|
||
"uuid": "5dea6618a606e7c7",
|
||
"chunk_id": "0",
|
||
"chunk_type": "sentence",
|
||
"start_time": 5.5,
|
||
"end_time": 8.2,
|
||
"text": "Machine learning is a subset of artificial intelligence...",
|
||
"score": 0.85
|
||
}
|
||
],
|
||
"query": "What is the person saying about machine learning?"
|
||
}
|
||
```
|
||
|
||
**Example:**
|
||
```bash
|
||
curl -X POST http://localhost:3002/api/v1/search \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-API-Key: YOUR_API_KEY" \
|
||
-d '{"query": "machine learning", "limit": 5}'
|
||
```
|
||
|
||
---
|
||
|
||
### 4a. N8N Search (n8n Workflow Integration)
|
||
N8n-compatible search endpoint with standardized response format for direct workflow integration.
|
||
|
||
**Endpoint:** `POST /api/v1/n8n/search`
|
||
|
||
**Request Body:**
|
||
```json
|
||
{
|
||
"query": "sunset",
|
||
"limit": 10,
|
||
"uuid": "5dea6618a606e7c7"
|
||
}
|
||
```
|
||
|
||
| Field | Type | Required | Description |
|
||
|-------|------|----------|-------------|
|
||
| `query` | string | Yes | Natural language search query |
|
||
| `limit` | integer | No | Max results (default: 10) |
|
||
| `uuid` | string | No | Filter by specific video UUID |
|
||
|
||
**Response (200):**
|
||
```json
|
||
{
|
||
"query": "sunset",
|
||
"count": 2,
|
||
"hits": [
|
||
{
|
||
"id": "c_001",
|
||
"vid": "5dea6618a606e7c7",
|
||
"start": 5.5,
|
||
"end": 8.2,
|
||
"title": "Sunset Scene",
|
||
"text": "The sun slowly sets over the ocean...",
|
||
"score": 0.92,
|
||
"file_path": "/Users/accusys/momentry/var/sftpgo/data/demo/video.mp4"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
| Field | Type | Description |
|
||
|-------|------|-------------|
|
||
| `query` | string | Original search query |
|
||
| `count` | integer | Number of results |
|
||
| `hits[].id` | string | Chunk ID |
|
||
| `hits[].vid` | string | Video UUID |
|
||
| `hits[].start` | number | Start time in seconds |
|
||
| `hits[].end` | number | End time in seconds |
|
||
| `hits[].title` | string | Chunk title (from metadata or auto-generated) |
|
||
| `hits[].text` | string | Text content |
|
||
| `hits[].score` | number | Relevance score (0-1) |
|
||
| `hits[].file_path` | string | Full file path to video file |
|
||
|
||
**Example:**
|
||
```bash
|
||
curl -X POST http://localhost:3002/api/v1/n8n/search \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-API-Key: YOUR_API_KEY" \
|
||
-d '{"query": "sunset", "limit": 5}'
|
||
```
|
||
|
||
**Environment Variables:**
|
||
| Variable | Default | Description |
|
||
|----------|---------|-------------|
|
||
| `MOMENTRY_MEDIA_BASE_URL` | `https://wp.momentry.ddns.net` | Base URL for constructing media URLs |
|
||
|
||
---
|
||
|
||
### 5. Lookup Video
|
||
Lookup video UUID by path or get video details by UUID.
|
||
|
||
**Endpoint:** `GET /api/v1/lookup`
|
||
|
||
| Parameter | Type | Required | Description |
|
||
|-----------|------|----------|-------------|
|
||
| `path` | query | No* | Video file path |
|
||
| `uuid` | query | No* | Video UUID |
|
||
|
||
*One of `path` or `uuid` is required.
|
||
|
||
**Response (200):**
|
||
```json
|
||
{
|
||
"uuid": "5dea6618a606e7c7",
|
||
"file_path": "/path/to/video.mp4",
|
||
"file_name": "video.mp4",
|
||
"duration": 120.5
|
||
}
|
||
```
|
||
|
||
**Example:**
|
||
```bash
|
||
# Lookup by path
|
||
curl -H "X-API-Key: YOUR_API_KEY" "http://localhost:3002/api/v1/lookup?path=/path/to/video.mp4"
|
||
|
||
# Lookup by UUID
|
||
curl -H "X-API-Key: YOUR_API_KEY" "http://localhost:3002/api/v1/lookup?uuid=5dea6618a606e7c7"
|
||
```
|
||
|
||
---
|
||
|
||
### 6. List Videos
|
||
List all registered videos.
|
||
|
||
**Endpoint:** `GET /api/v1/videos`
|
||
|
||
**Response (200):**
|
||
```json
|
||
{
|
||
"videos": [
|
||
{
|
||
"uuid": "5dea6618a606e7c7",
|
||
"file_path": "/path/to/video.mp4",
|
||
"file_name": "video.mp4",
|
||
"duration": 120.5,
|
||
"width": 1920,
|
||
"height": 1080
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
**Example:**
|
||
```bash
|
||
curl -H "X-API-Key: YOUR_API_KEY" http://localhost:3002/api/v1/videos
|
||
```
|
||
|
||
---
|
||
|
||
## Data Flow
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────┐
|
||
│ 完整工作流程 │
|
||
└─────────────────────────────────────────────────────────────────────┘
|
||
|
||
1. Register Video
|
||
POST /api/v1/register
|
||
└── UUID: 5dea6618a606e7c7
|
||
|
||
2. Process Video (CLI)
|
||
cargo run -- process 5dea6618a606e7c7
|
||
├── ASR (WhisperX) → 7 segments
|
||
├── CUT (PySceneDetect) → 134 scenes
|
||
├── YOLO (YOLOv8) → 10483 frames with objects
|
||
├── OCR (EasyOCR) → 40 frames with text
|
||
├── Face (OpenCV) → 44 frames with faces
|
||
└── Pose (YOLOv8-Pose) → 14315 frames
|
||
|
||
3. Monitor Progress (Real-time)
|
||
GET /api/v1/progress/:uuid
|
||
└── Redis Pub/Sub + Hash
|
||
|
||
4. Chunk (CLI)
|
||
cargo run -- chunk 5dea6618a606e7c7
|
||
└── Create chunks in database
|
||
|
||
5. Vectorize (CLI)
|
||
cargo run -- vectorize 5dea6618a606e7c7
|
||
└── Generate embeddings in Qdrant
|
||
|
||
6. Search (API)
|
||
POST /api/v1/search
|
||
└── Natural language query
|
||
```
|
||
|
||
---
|
||
|
||
## Processor Reference
|
||
|
||
| Processor | Model | Description |
|
||
|-----------|-------|-------------|
|
||
| **ASR** | WhisperX (faster-whisper) | Speech recognition + diarization |
|
||
| **CUT** | PySceneDetect | Scene detection/segmentation |
|
||
| **ASRX** | WhisperX | Speaker diarization |
|
||
| **YOLO** | YOLOv8n | Object detection |
|
||
| **OCR** | EasyOCR | Text recognition |
|
||
| **Face** | OpenCV Haar Cascade | Face detection |
|
||
| **Pose** | YOLOv8n-Pose | Pose estimation |
|
||
|
||
---
|
||
|
||
## Cache Toggle
|
||
|
||
Toggle caching at runtime.
|
||
|
||
**Endpoint:** `POST /api/v1/config/cache`
|
||
|
||
**Request Body:**
|
||
```json
|
||
{
|
||
"enabled": true
|
||
}
|
||
```
|
||
|
||
| Field | Type | Required | Description |
|
||
|-------|------|----------|-------------|
|
||
| `enabled` | boolean | Yes | Enable (true) or disable (false) cache |
|
||
|
||
**Response (200):**
|
||
```json
|
||
{
|
||
"cache_enabled": true,
|
||
"message": "Cache toggled successfully"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Unregister Video
|
||
|
||
Delete a video and all associated data (chunks, processor results, thumbnails).
|
||
|
||
**Endpoint:** `POST /api/v1/unregister`
|
||
|
||
**Request Body:**
|
||
```json
|
||
{
|
||
"uuid": "5dea6618a606e7c7"
|
||
}
|
||
```
|
||
|
||
| Field | Type | Required | Description |
|
||
|-------|------|----------|-------------|
|
||
| `uuid` | string | Yes | Video UUID (16 character hex) |
|
||
|
||
**Response (200):**
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "Video unregistered successfully",
|
||
"uuid": "5dea6618a606e7c7"
|
||
}
|
||
```
|
||
|
||
**Warning:** This operation is irreversible and will delete all associated chunks, processor results, and thumbnails.
|
||
|
||
---
|
||
|
||
## Error Responses
|
||
|
||
**400 Bad Request**
|
||
```json
|
||
{
|
||
"error": "Invalid request body"
|
||
}
|
||
```
|
||
|
||
**404 Not Found**
|
||
```json
|
||
{
|
||
"error": "Resource not found"
|
||
}
|
||
```
|
||
|
||
**500 Internal Server Error**
|
||
```json
|
||
{
|
||
"error": "Internal server error"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Environment Variables
|
||
|
||
| Variable | Default | Description |
|
||
|----------|---------|-------------|
|
||
| `DATABASE_URL` | `postgres://accusys@localhost:5432/momentry` | PostgreSQL connection |
|
||
| `REDIS_URL` | `redis://localhost:6379` | Redis connection |
|
||
| `REDIS_PASSWORD` | `accusys` | Redis password |
|
||
| `QDRANT_URL` | `http://localhost:6333` | Qdrant vector DB URL |
|
||
| `QDRANT_API_KEY` | - | Qdrant API key |
|
||
| `QDRANT_COLLECTION` | `chunks` | Qdrant collection name |
|
||
| `MOMENTRY_MEDIA_BASE_URL` | `https://wp.momentry.ddns.net` | Base URL for n8n search media URLs |
|
||
|
||
---
|
||
|
||
## Starting the Server
|
||
|
||
```bash
|
||
# Default (port 3002, since 3000 is Gitea)
|
||
cargo run --bin momentry -- server
|
||
|
||
# Custom host and port
|
||
cargo run --bin momentry -- server --host 127.0.0.1 --port 3002
|
||
```
|
||
|
||
---
|
||
|
||
## Quick Reference
|
||
|
||
| Task | Command |
|
||
|------|---------|
|
||
| Register video | `POST /api/v1/register` |
|
||
| Process video | `cargo run -- process <uuid>` |
|
||
| Check progress | `GET /api/v1/progress/<uuid>` |
|
||
| Search | `POST /api/v1/search` |
|
||
| List videos | `GET /api/v1/videos` |
|
||
| Lookup | `GET /api/v1/lookup?uuid=<uuid>` |
|
||
| Toggle cache | `POST /api/v1/config/cache` |
|
||
| Delete video | `POST /api/v1/unregister` |
|