---
document_type: "architecture_design"
service: "N8N"
title: "Momentry API 使用流程"
date: "2026-03-25"
version: "V1.0"
status: "active"
owner: "Warren"
created_by: "OpenCode"
tags:
  - "momentry"
  - "使用流程"
ai_query_hints:
  - "查詢 Momentry API 使用流程 的內容"
  - "Momentry API 使用流程 的主要目的是什麼？"
  - "如何操作或實施 Momentry API 使用流程？"
---

# Momentry API 使用流程

> **目標**: 從影片上傳到搜尋的完整流程  
> **適用**: WordPress / n8n 整合  
> **版本**: V1.0 | **日期**: 2026-03-25

---

## 流程總覽

```
┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  1. 上傳    │ →  │  2. 註冊    │ →  │  3. 確認    │ →  │  4. 處理    │ →  │  5. 搜尋    │
│  SFTPGo     │    │  自動完成    │    │  UUID       │    │  查詢進度   │    │  測試       │
└─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘
```

---

## Step 1: 上傳影片

### 方式 A: SFTP 上傳（推薦）

```bash
# 連線資訊
主機: sftpgo.momentry.ddns.net
連接埠: 2022
用戶名: demo
密碼: demopassword123
```

使用 FileZilla 或 SFTP 客戶端上傳到 `/` 目錄

### 方式 B: SFTP 命令列

```bash
sshpass -p "demopassword123" sftp -P 2022 demo@sftpgo.momentry.ddns.net
```

上傳後確認檔案在 SFTPGo 中的位置

---

## Step 2: 自動註冊

上傳後，系統會自動：
1. 偵測新檔案
2. 計算 UUID（SHA256）
3. 建立資料庫記錄

**無需手動操作**

---

## Step 3: 確認註冊成功

### 查詢所有影片

```bash
curl -s -H "X-API-Key: YOUR_API_KEY" \
  "https://api.momentry.ddns.net/api/v1/videos" | jq '.videos | length'
```

### 查詢特定檔案

```bash
curl -s -H "X-API-Key: YOUR_API_KEY" \
  "https://api.momentry.ddns.net/api/v1/videos" | jq '.videos[] | select(.file_name | contains("你的檔案名"))'
```

### 預期回應

```json
{
  "uuid": "952f5854b9febad1",
  "file_path": "/Users/accusys/momentry/var/sftpgo/data/demo/你的檔案.mp4",
  "file_name": "你的檔案.mp4",
  "duration": 123.45,
  "width": 1920,
  "height": 1080
}
```

**確認要點**:
- ✅ UUID 已產生（16位 hex）
- ✅ `file_path` 正確
- ✅ `duration` > 0

---

## Step 4: 查詢處理進度

### 取得任務 UUID

```bash
# 從影片資訊取得 job_id
curl -s -H "X-API-Key: YOUR_API_KEY" \
  "https://api.momentry.ddns.net/api/v1/videos" | \
  jq '.videos[] | select(.file_name == "你的檔案.mp4") | {uuid, job_id}'
```

### 查詢任務狀態

```bash
curl -s -H "X-API-Key: YOUR_API_KEY" \
  "https://api.momentry.ddns.net/api/v1/jobs/{uuid}"
```

### 任務狀態說明

| status | 說明 | 動作 |
|--------|------|------|
| `pending` | 等待處理 | 等待中 |
| `processing` | 處理中 | 繼續輪詢 |
| `completed` | 已完成 | 可進入 Step 5 |
| `failed` | 處理失敗 | 檢查錯誤 |

### n8n 輪詢範例

```javascript
// n8n Workflow: 檢查處理狀態
const jobUuid = $input.item.json.job_uuid;

const response = await fetch(
  `https://api.momentry.ddns.net/api/v1/jobs/${jobUuid}`,
  {
    headers: {
      "X-API-Key": "YOUR_API_KEY"
    }
  }
);

const job = await response.json();

// 狀態檢查
if (job.status === 'completed') {
  return [{ json: { done: true, file_uuid: job.file_uuid } }];
} else {
  return [{ json: { done: false, status: job.status } }];
}
```

---

## Step 5: 搜尋測試

處理完成後，資料會入庫到向量資料庫，可進行搜尋測試。

### 測試向量搜尋

```bash
curl -s -X POST "https://api.momentry.ddns.net/api/v1/search" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "測試關鍵字",
    "limit": 5
  }'
```

### 取得分段（Chunk）內容

搜尋結果會返回影片分段（Chunk），包含可播放的時間軸資訊：

```json
{
  "results": [
    {
      "uuid": "39567a0eb16f39fd",
      "chunk_id": "sentence_1471",
      "chunk_type": "sentence",
      "start_time": 5309.08,
      "end_time": 5311.08,
      "text": "influenced by a vital way,",
      "score": 0.68
    }
  ]
}
```

**Chunk 欄位說明**:
| 欄位 | 說明 |
|------|------|
| `uuid` | 影片 UUID（用於取得影片網址） |
| `chunk_id` | 分段 ID |
| `chunk_type` | 分段類型（sentence/cut/time/trace/story） |
| `start_time` | 開始時間（秒） |
| `end_time` | 結束時間（秒） |
| `text` | 語音內容文字 |
| `score` | 相似度分數（0-1） |

### 播放分段

取得 Chunk 後可組合成播放網址：

```
影片網址?start={start_time}&end={end_time}
```

範例：
```
https://wp.momentry.ddns.net/video.mp4?start=5309.08&end=5311.08
```

---

## 完整 n8n Workflow 範例

```
┌──────────────┐
│  觸發 (定時)  │
└──────┬───────┘
       ▼
┌──────────────┐     ┌──────────────┐
│  查詢影片     │────►│  比對新檔案   │
│  /videos     │     │              │
└──────┬───────┘     └──────────────┘
       │                   │
       ▼                   ▼
┌──────────────┐     ┌──────────────┐
│  等待處理     │◄────│  輪詢任務狀態  │
│  /jobs/:uuid │     │  /jobs/:uuid │
└──────┬───────┘     └──────────────┘
       │
       ▼ (completed)
┌──────────────┐
│  搜尋測試     │
│  /search     │
└──────────────┘
```

---

## 快速參考

| 步驟 | API | 用途 |
|------|-----|------|
| 查詢影片 | `GET /api/v1/videos` | 確認上傳成功 |
| 查詢任務 | `GET /api/v1/jobs/:uuid` | 查看處理進度 |
| 搜尋內容 | `POST /api/v1/search` | 測試搜尋功能 |

---

## WordPress PHP 範例

### 基本設定

```php
<?php
class Momentry_API {
    private const API_URL = 'https://api.momentry.ddns.net';
    private const API_KEY = 'YOUR_API_KEY';

    public static function request(string $method, string $endpoint, ?array $data = null): array {
        $url = self::API_URL . $endpoint;
        
        $args = [
            'method'      => $method,
            'headers'     => [
                'X-API-Key'    => self::API_KEY,
                'Content-Type' => 'application/json',
            ],
            'timeout'     => 30,
        ];

        if ($data !== null) {
            $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 static function getVideos(): array {
        return self::request('GET', '/api/v1/videos');
    }

    public static function getVideo(string $uuid): array {
        return self::request('GET', "/api/v1/videos/{$uuid}/details");
    }

    public static function getJob(string $uuid): array {
        return self::request('GET', "/api/v1/jobs/{$uuid}");
    }

    public static function search(string $query, int $topK = 5): array {
        return self::request('POST', '/api/v1/search', [
            'query' => $query,
            'top_k' => $topK,
        ]);
    }
}
```

### Step 3: 確認註冊成功

```php
<?php
// 查詢所有影片
$videos = Momentry_API::getVideos();

foreach ($videos['videos'] as $video) {
    echo "UUID: " . $video['uuid'] . "\n";
    echo "檔案: " . $video['file_name'] . "\n";
    echo "時長: " . $video['duration'] . " 秒\n";
    echo "---\n";
}

// 查詢特定影片
$video = Momentry_API::getVideo('952f5854b9febad1');
print_r($video);
```

### Step 4: 查詢處理進度

```php
<?php
// 取得任務狀態
$job = Momentry_API::getJob('9760d0820f0cf9a7');

switch ($job['status']) {
    case 'pending':
        echo "等待處理中...\n";
        break;
    case 'processing':
        echo "處理中: " . $job['progress'] . "%\n";
        break;
    case 'completed':
        echo "處理完成！\n";
        break;
    case 'failed':
        echo "處理失敗: " . ($job['error'] ?? '未知錯誤') . "\n";
        break;
}
```

### Step 5: 搜尋內容並取得 Chunk

```php
<?php
// 搜尋相關片段
$results = Momentry_API::search('測試關鍵字', 5);

foreach ($results['results'] as $result) {
    echo "影片 UUID: " . $result['uuid'] . "\n";
    echo "Chunk ID: " . $result['chunk_id'] . "\n";
    echo "類型: " . $result['chunk_type'] . "\n";
    echo "開始: " . $result['start_time'] . "s\n";
    echo "結束: " . $result['end_time'] . "s\n";
    echo "內容: " . ($result['text'] ?? '') . "\n";
    echo "相似度: " . $result['score'] . "\n";
    echo "---\n";
}
```

### WordPress Shortcode 範例（可點擊播放）

```php
<?php
// 在 functions.php 中加入
add_shortcode('momentry_search', function($atts) {
    $atts = shortcode_atts([
        'query'   => '',
        'limit'   => 10,
    ], $atts);

    if (empty($atts['query'])) {
        return '<p>請輸入搜尋關鍵字</p>';
    }

    try {
        $results = Momentry_API::search($atts['query'], $atts['limit']);
        
        if (empty($results['results'])) {
            return '<p>找不到相關結果</p>';
        }

        $html = '<div class="momentry-results">';
        $html .= '<h3>搜尋結果: ' . esc_html($atts['query']) . '</h3>';
        $html .= '<ul>';

        foreach ($results['results'] as $result) {
            $file_uuid = $result['uuid'];
            $start = $result['start_time'] ?? 0;
            $end = $result['end_time'] ?? 0;
            $text = $result['text'] ?? '無文字描述';
            
            $html .= '<li>';
            $html .= '<a href="/player?uuid=' . esc_attr($file_uuid) . 
                     '&start=' . esc_attr($start) . 
                     '&end=' . esc_attr($end) . '">';
            $html .= '播放 ' . $start . 's - ' . $end . 's';
            $html .= '</a>';
            $html .= '<br>';
            $html .= '<small>相似度: ' . round($result['score'] * 100) . '%</small>';
            $html .= '<br>';
            $html .= esc_html($text);
            $html .= '</li>';
        }

        $html .= '</ul></div>';
        return $html;

    } catch (Exception $e) {
        return '<p>搜尋服務暫時無法使用</p>';
    }
});
```

**使用方式**:
```html
[momentry_search query="關鍵字" limit="5"]
```

---

## 完整 n8n Workflow 範例

```
┌──────────────┐
│  觸發 (定時)  │
└──────┬───────┘
       ▼
┌──────────────┐     ┌──────────────┐
│  查詢影片     │────►│  比對新檔案   │
│  /videos     │     │              │
└──────┬───────┘     └──────────────┘
       │                   │
       ▼                   ▼
┌──────────────┐     ┌──────────────┐
│  等待處理     │◄────│  輪詢任務狀態  │
│  /jobs/:uuid │     │  /jobs/:uuid │
└──────┬───────┘     └──────────────┘
       │
       ▼ (completed)
┌──────────────┐
│  搜尋測試     │
│  /search     │
└──────────────┘
```

---

**注意**: 
- 處理時間視影片長度而定（1分鐘影片約需 2-5 分鐘處理）
- 大量影片時建議分批上傳

---

## 附錄：版本歷史

| 版本 | 日期 | 內容 | 操作人 |
|------|------|------|--------|
| V1.0 | 2026-03-25 | 初版建立 | OpenCode |
| V1.1 | 2026-03-25 | 新增 Chunk 取得與播放說明、Shortcode 範例 | OpenCode |
| V1.2 | 2026-03-25 | 修正 SFTPGo 主機名稱為 sftpgo.momentry.ddns.net | OpenCode |
