feat: Initial v0.9 release with API Key authentication

## v0.9.20260325_144654

### Features
- API Key Authentication System
- Job Worker System
- V2 Backup Versioning

### Bug Fixes
- get_processor_results_by_job column mapping

Co-authored-by: OpenCode
This commit is contained in:
accusys
2026-03-25 14:52:51 +08:00
parent 47e86b696f
commit 383201cacd
193 changed files with 40268 additions and 422 deletions

447
docs/API_REFERENCE.md Normal file
View File

@@ -0,0 +1,447 @@
# Momentry Core API 安裝指南
| 項目 | 內容 |
|------|------|
| 建立者 | Warren |
| 建立時間 | 2026-03-18 |
| 文件版本 | V1.0 |
---
## 版本歷史
| 版本 | 日期 | 目的 | 操作人 | 工具/模型 |
|------|------|------|--------|-----------|
| V1.0 | 2026-03-18 | 創建文件 | Warren | OpenCode / MiniMax M2.5 |
| V1.1 | 2026-03-23 | 更新端點與實際一致 | 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
Currently no authentication is required.
---
## 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,
"file_name": "video.mp4",
"duration": 120.5,
"width": 1920,
"height": 1080
}
```
**Example:**
```bash
curl -X POST http://localhost:3002/api/v1/register \
-H "Content-Type: application/json" \
-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 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" \
-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,
"media_url": "https://wp.momentry.ddns.net/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[].media_url` | string | Full media URL (optional) |
**Example:**
```bash
curl -X POST http://localhost:3002/api/v1/n8n/search \
-H "Content-Type: application/json" \
-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 "http://localhost:3002/api/v1/lookup?path=/path/to/video.mp4"
# Lookup by UUID
curl "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 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 |
---
## 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>` |