## 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
448 lines
10 KiB
Markdown
448 lines
10 KiB
Markdown
# 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>` |
|