---
document_type: "implementation_guide"
service: "MOMENTRY_CORE"
title: "Momentry Core API 示範手冊"
date: "2026-03-25"
version: "V1.0"
status: "active"
owner: "Warren"
created_by: "OpenCode"
tags:
  - "momentry"
  - "core"
  - "示範手冊"
ai_query_hints:
  - "查詢 Momentry Core API 示範手冊 的內容"
  - "Momentry Core API 示範手冊 的主要目的是什麼？"
  - "如何操作或實施 Momentry Core API 示範手冊？"
---

# Momentry Core API 示範手冊

| 項目 | 內容 |
|------|------|
| 建立者 | OpenCode |
| 建立時間 | 2026-03-25 |
| 文件版本 | V1.0 |

---

## 版本歷史

| 版本 | 日期 | 目的 | 操作人 | 工具/模型 |
|------|------|------|--------|-----------|
| V1.0 | 2026-03-25 | 創建示範手冊，包含 Demo API Key 與完整範例 | OpenCode | deepseek-reasoner |

---

**狀態**: 完成

---

## 快速開始

### Demo API Key

```
API Key:  muser_68600856036340bcafc01930eb4bd839_1774418104_97221b69
Key ID:   muser_68600856036340bcafc01930eb4bd839
過期日:   2027-03-25
```

### 測試連線

```bash
curl http://localhost:3002/health
```

```json
{"status":"ok","version":"0.1.0","uptime_ms":456464}
```

### 測試認證

```bash
curl -H "X-API-Key: muser_68600856036340bcafc01930eb4bd839_1774418104_97221b69" \
  http://localhost:3002/api/v1/videos | jq '.videos | length'
```

```json
13
```

---

## 環境 URL

| 環境 | URL | 用途 |
|------|-----|------|
| **本地開發** | `http://localhost:3002` | 本機開發測試 |
| **外部訪問** | `https://api.momentry.ddns.net` | n8n/WordPress/curl 生產環境 |

---

## 端點總覽

| 方法 | 端點 | 說明 | 認證 |
|------|------|------|------|
| GET | `/health` | 健康檢查 | 公開 |
| GET | `/health/detailed` | 詳細健康檢查 | 公開 |
| POST | `/api/v1/register` | 註冊影片 | 需要 |
| POST | `/api/v1/probe` | 探測影片資訊 | 需要 |
| POST | `/api/v1/search` | 語意搜尋 | 需要 |
| POST | `/api/v1/n8n/search` | n8n 格式搜尋 | 需要 |
| POST | `/api/v1/search/hybrid` | 混合搜尋 | 需要 |
| GET | `/api/v1/videos` | 列出所有影片 | 需要 |
| GET | `/api/v1/lookup` | 查詢影片 UUID | 需要 |
| GET | `/api/v1/progress/:uuid` | 處理進度 | 需要 |
| GET | `/api/v1/jobs` | 任務列表 | 需要 |
| GET | `/api/v1/jobs/:uuid` | 任務詳情 | 需要 |

---

## 1. curl 範例

### 基本格式

```bash
curl -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  URL
```

### 1.1 健康檢查（公開）

```bash
# 基本健康檢查
curl http://localhost:3002/health

# 詳細健康檢查（含服務狀態）
curl http://localhost:3002/health/detailed
```

### 1.2 列出影片

```bash
curl -H "X-API-Key: muser_68600856036340bcafc01930eb4bd839_1774418104_97221b69" \
  http://localhost:3002/api/v1/videos | jq '.'
```

```json
{
  "videos": [
    {
      "uuid": "952f5854b9febad1",
      "file_name": "ExaSAN PCIe series - Director Ou Yu-Zhi Shares His Experience.mp4",
      "duration": 159.637188,
      "width": 640,
      "height": 360
    },
    ...
  ]
}
```

### 1.3 搜尋影片

```bash
curl -X POST \
  -H "X-API-Key: muser_68600856036340bcafc01930eb4bd839_1774418104_97221b69" \
  -H "Content-Type: application/json" \
  -d '{"query": "ExaSAN", "limit": 5}' \
  http://localhost:3002/api/v1/search | jq '.'
```

```json
{
  "results": [
    {
      "uuid": "952f5854b9febad1",
      "chunk_id": "...",
      "text": "...",
      "score": 0.85,
      "start_time": 0.0,
      "end_time": 5.0
    }
  ],
  "total": 1,
  "query": "ExaSAN",
  "took_ms": 123
}
```

### 1.4 查詢進度

```bash
curl -H "X-API-Key: muser_68600856036340bcafc01930eb4bd839_1774418104_97221b69" \
  http://localhost:3002/api/v1/progress/952f5854b9febad1 | jq '.'
```

```json
{
  "uuid": "952f5854b9febad1",
  "overall_progress": 67,
  "current_processor": "yolo",
  "processors": [
    {"name": "asr", "status": "completed"},
    {"name": "cut", "status": "completed"},
    {"name": "yolo", "status": "running"}
  ]
}
```

---

## 2. n8n 範例

### 2.1 HTTP Request 節點設定

```
Method: POST
URL: https://api.momentry.ddns.net/api/v1/search
Authentication: None (使用 Header)

Headers:
┌─────────────────────┬──────────────────────────────────────────────────┐
│ Name                 │ Value                                            │
├─────────────────────┼──────────────────────────────────────────────────┤
│ X-API-Key            │ muser_68600856036340bcafc01930eb4bd839_...      │
│ Content-Type         │ application/json                                  │
└─────────────────────┴──────────────────────────────────────────────────┘

Body Content (JSON):
{
  "query": "{{ $json.search_term }}",
  "limit": 5
}
```

### 2.2 n8n 搜尋 Workflow

```json
{
  "nodes": [
    {
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [250, 300]
    },
    {
      "name": "Set Search Term",
      "type": "n8n-nodes-base.set",
      "parameters": {
        "values": {
          "json": {
            "search_term": "ExaSAN"
          }
        }
      },
      "position": [450, 300]
    },
    {
      "name": "Search Videos",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "method": "POST",
        "url": "https://api.momentry.ddns.net/api/v1/search",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-API-Key",
              "value": "muser_68600856036340bcafc01930eb4bd839_1774418104_97221b69"
            }
          ]
        },
        "sendBody": true,
        "bodyContentType": "json",
        "specifyBody": "json",
        "jsonBody": "={{ { \"query\": $json.search_term, \"limit\": 5 } }}"
      },
      "position": [650, 300]
    },
    {
      "name": "Process Results",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "// Extract video results\nconst results = $input.first().json.results;\nreturn results.map(r => ({\n  uuid: r.uuid,\n  text: r.text,\n  score: r.score,\n  time: `${r.start_time}s - ${r.end_time}s`\n}));"
      },
      "position": [850, 300]
    }
  ],
  "connections": {
    "Manual Trigger": {
      "main": [[{"node": "Set Search Term"}]]
    },
    "Set Search Term": {
      "main": [[{"node": "Search Videos"}]]
    },
    "Search Videos": {
      "main": [[{"node": "Process Results"}]]
    }
  }
}
```

### 2.3 n8n 列出影片 Workflow

```json
{
  "nodes": [
    {
      "name": "Get Videos",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "method": "GET",
        "url": "https://api.momentry.ddns.net/api/v1/videos",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-API-Key",
              "value": "muser_68600856036340bcafc01930eb4bd839_1774418104_97221b69"
            }
          ]
        }
      },
      "position": [450, 300]
    },
    {
      "name": "Extract Video List",
      "type": "n8n-nodes-base.code",
      "parameters": {
        "jsCode": "const videos = $input.first().json.videos;\nreturn videos.map(v => ({\n  json: {\n    uuid: v.uuid,\n    name: v.file_name,\n    duration: Math.round(v.duration) + 's',\n    resolution: `${v.width}x${v.height}`\n  }\n}));"
      },
      "position": [650, 300]
    },
    {
      "name": "Slack Notification",
      "type": "n8n-nodes-base.slack",
      "parameters": {
        "channel": "#momentry",
        "text": "=Found {{ $json.length }} videos:\n{{ $json.map(v => `• ${v.name} (${v.duration})`).join(`\n`) }}"
      },
      "position": [850, 300]
    }
  ]
}
```

### 2.4 n8n 定時同步 Workflow

```json
{
  "nodes": [
    {
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": {
        "rule": {
          "interval": [{"field": "hours", "hours": 1}]
        }
      },
      "position": [250, 300]
    },
    {
      "name": "Get Pending Videos",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "method": "GET",
        "url": "https://api.momentry.ddns.net/api/v1/videos"
      },
      "position": [450, 300]
    },
    {
      "name": "Filter Processing",
      "type": "n8n-nodes-base.filter",
      "parameters": {
        "conditions": {
          "options": {"caseSensitive": true},
          "conditions": [
            {"id": "status", "leftValue": "{{ $json.status }}", "rightValue": "processing"}
          ]
        }
      },
      "position": [650, 300]
    }
  ]
}
```

---

## 3. WordPress 範例

### 3.1 PHP 函數庫

```php
<?php
/**
 * Momentry API Client
 */

class Momentry_API {
    private const API_URL = 'https://api.momentry.ddns.net';
    private const API_KEY = 'muser_68600856036340bcafc01930eb4bd839_1774418104_97221b69';

    /**
     * 發送 API 請求
     */
    private function request(string $endpoint, array $data = [], string $method = 'GET'): array {
        $url = self::API_URL . $endpoint;
        
        $args = [
            'headers' => [
                'X-API-Key' => self::API_KEY,
                'Content-Type' => 'application/json',
            ],
            'timeout' => 30,
        ];

        if ($method === 'POST') {
            $args['method'] = 'POST';
            $args['body'] = json_encode($data);
        }

        $response = wp_remote_request($url, $args);
        
        if (is_wp_error($response)) {
            throw new Exception($response->get_error_message());
        }

        return json_decode(wp_remote_retrieve_body($response), true);
    }

    /**
     * 列出所有影片
     */
    public function list_videos(): array {
        return $this->request('/api/v1/videos');
    }

    /**
     * 搜尋影片內容
     */
    public function search(string $query, int $limit = 10): array {
        return $this->request('/api/v1/search', [
            'query' => $query,
            'limit' => $limit,
        ], 'POST');
    }

    /**
     * 取得影片進度
     */
    public function get_progress(string $uuid): array {
        return $this->request("/api/v1/progress/{$uuid}");
    }

    /**
     * 檢查健康狀態
     */
    public function health_check(): array {
        return $this->request('/health');
    }
}
```

### 3.2 短代碼 (Shortcode)

```php
<?php
/**
 * WordPress 短代碼範例
 */

// 註冊短代碼
add_shortcode('momentry_videos', function($atts) {
    $atts = shortcode_atts([
        'limit' => 10,
    ], $atts);

    $api = new Momentry_API();
    
    try {
        $result = $api->list_videos();
        $videos = array_slice($result['videos'], 0, $atts['limit']);
        
        ob_start();
        ?>
        <div class="momentry-videos">
            <h3>影片列表</h3>
            <ul>
                <?php foreach ($videos as $video): ?>
                    <li>
                        <strong><?= esc_html($video['file_name']) ?></strong>
                        <br>
                        <small>
                            UUID: <?= esc_html($video['uuid']) ?>
                            | 時長: <?= gmdate("H:i:s", $video['duration']) ?>
                        </small>
                    </li>
                <?php endforeach; ?>
            </ul>
        </div>
        <?php
        return ob_get_clean();
        
    } catch (Exception $e) {
        return '<p class="error">載入失敗: ' . esc_html($e->getMessage()) . '</p>';
    }
});

// 搜尋短代碼
add_shortcode('momentry_search', function($atts, $content = '') {
    $query = sanitize_text_field($content);
    
    if (empty($query)) {
        return '<p>請提供搜尋關鍵字</p>';
    }

    $api = new Momentry_API();
    
    try {
        $result = $api->search($query);
        
        ob_start();
        ?>
        <div class="momentry-search-results">
            <h3>「<?= esc_html($query) ?>」搜尋結果</h3>
            <?php if (empty($result['results'])): ?>
                <p>沒有找到相關結果</p>
            <?php else: ?>
                <ul>
                    <?php foreach ($result['results'] as $item): ?>
                        <li>
                            <a href="/video/<?= esc_attr($item['uuid']) ?>?t=<?= (int)$item['start_time'] ?>">
                                <?= esc_html($item['text']) ?>
                            </a>
                            <br>
                            <small>相似度: <?= round($item['score'] * 100) ?>%</small>
                        </li>
                    <?php endforeach; ?>
                </ul>
            <?php endif; ?>
        </div>
        <?php
        return ob_get_clean();
        
    } catch (Exception $e) {
        return '<p class="error">搜尋失敗: ' . esc_html($e->getMessage()) . '</p>';
    }
});
```

### 3.3 使用方式

在 WordPress 頁面或文章中：

```
[momentry_videos limit="5"]

[momentry_search]ExaSAN[/momentry_search]
```

### 3.4 REST API 整合

```php
<?php
/**
 * 註冊 WordPress REST API 端點
 */

add_action('rest_api_init', function() {
    register_rest_route('momentry/v1', '/search', [
        'methods' => 'GET',
        'callback' => function(WP_REST_Request $request) {
            $query = sanitize_text_field($request->get_param('q'));
            
            if (empty($query)) {
                return new WP_Error('missing_query', '需要搜尋關鍵字', ['status' => 400]);
            }

            $api = new Momentry_API();
            $result = $api->search($query);
            
            return new WP_REST_Response($result, 200);
        },
        'permission_callback' => '__return_true',
    ]);
});

// 使用方式: GET /wp-json/momentry/v1/search?q=ExaSAN
```

---

## 4. 疑難排解

### 4.1 常見錯誤

| 錯誤 | 原因 | 解決方案 |
|------|------|----------|
| `401 Unauthorized` | API Key 無效或過期 | 檢查 API Key 是否正確 |
| `500 Internal Server Error` | 伺服器錯誤 | 檢查 `/health/detailed` 服務狀態 |
| `Connection Timeout` | 網路問題 | 確認 `api.momentry.ddns.net` 可達 |

### 4.2 測試腳本

```bash
#!/bin/bash
# test_api.sh - Momentry API 測試腳本

API_KEY="muser_68600856036340bcafc01930eb4bd839_1774418104_97221b69"
BASE_URL="http://localhost:3002"

echo "=== 1. 健康檢查 ==="
curl -s "$BASE_URL/health" | jq .
echo ""

echo "=== 2. 列出影片 ==="
curl -s -H "X-API-Key: $API_KEY" "$BASE_URL/api/v1/videos" | jq '.videos | length'
echo ""

echo "=== 3. 搜尋測試 ==="
curl -s -X POST -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "test", "limit": 3}' \
  "$BASE_URL/api/v1/search" | jq '.results | length'
echo ""

echo "=== 完成 ==="
```

### 4.3 驗證腳本

```bash
#!/bin/bash
# verify_auth.sh - 驗證 API Key

API_KEY="muser_68600856036340bcafc01930eb4bd839_1774418104_97221b69"
BASE_URL="http://localhost:3002"

# 測試 1: 無 API Key
echo "測試 1: 無 API Key"
RESULT=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/api/v1/videos")
[ "$RESULT" = "401" ] && echo "✅ 正確拒絕 (401)" || echo "❌ 預期 401，實際 $RESULT"

# 測試 2: 有 API Key
echo "測試 2: 有 API Key"
RESULT=$(curl -s -H "X-API-Key: $API_KEY" "$BASE_URL/api/v1/videos")
echo "$RESULT" | jq -e '.videos' > /dev/null && echo "✅ 成功取得資料" || echo "❌ 取得資料失敗"

# 測試 3: 無效 API Key
echo "測試 3: 無效 API Key"
RESULT=$(curl -s -o /dev/null -w "%{http_code}" -H "X-API-Key: invalid_key" "$BASE_URL/api/v1/videos")
[ "$RESULT" = "401" ] && echo "✅ 正確拒絕 (401)" || echo "❌ 預期 401，實際 $RESULT"
```

---

## 5. API Key 管理

### 5.1 建立新 API Key

```bash
# 本地建立
./target/release/momentry api-key create "My App" --key-type user --ttl 90
```

### 5.2 列出 API Keys

```bash
./target/release/momentry api-key list
```

### 5.3 驗證 API Key

```bash
./target/release/momentry api-key validate --key "YOUR_API_KEY"
```

### 5.4 撤銷 API Key

```bash
./target/release/momentry api-key revoke --key "YOUR_API_KEY"
```

---

## 附錄

### A. 影片 UUID 說明

UUID 是基於檔案路徑的 SHA256 哈希前 16 位：

```
/Users/accusys/momentry/var/sftpgo/data/demo/video.mp4
    ↓
SHA256 Hash
    ↓
9760d0820f0cf9a7
```

### B. 處理器狀態

| 狀態 | 說明 |
|------|------|
| `pending` | 等待處理 |
| `running` | 處理中 |
| `completed` | 已完成 |
| `failed` | 失敗 |

### C. 支援的處理器

- **ASR**: 語音識別
- **CUT**: 場景剪切
- **YOLO**: 物件偵測

### D. 聯絡支援

- Email: support@momentry.ddns.net
- 文件: https://docs.momentry.ddns.net
- GitHub: https://github.com/anomalyco/momentry
