From 1f6cc7a631288d1333cec47fd566a2ea4216d476 Mon Sep 17 00:00:00 2001 From: Warren Date: Fri, 8 May 2026 09:47:38 +0800 Subject: [PATCH] docs: update API key to official format --- .../RELEASE/RELEASE_API_REFERENCE_v1.0.0.md | 572 ++++++++++-------- 1 file changed, 311 insertions(+), 261 deletions(-) diff --git a/docs_v1.0/API_V1.0.0/RELEASE/RELEASE_API_REFERENCE_v1.0.0.md b/docs_v1.0/API_V1.0.0/RELEASE/RELEASE_API_REFERENCE_v1.0.0.md index 8e4ed65..121209c 100644 --- a/docs_v1.0/API_V1.0.0/RELEASE/RELEASE_API_REFERENCE_v1.0.0.md +++ b/docs_v1.0/API_V1.0.0/RELEASE/RELEASE_API_REFERENCE_v1.0.0.md @@ -1,304 +1,354 @@ --- document_type: "reference_doc" service: "MOMENTRY_CORE" -title: "Momentry Core Release API Reference v1.0.0" -date: "2026-05-08" +title: "Momentry Core Release API 參考文件 V1.0.0 (V3 legacy)" +date: "2026-05-03" +deprecated: true +--- + +> ⚠️ **此文件為 V3.x 歷史參考,含已移除的路由。** +> 請改用 `API_DICTIONARY_V1.0.0.md`(root)取得當前準確的 53 條 API 路由。 version: "V4.0" -status: "active" +status: "outdated" owner: "Warren" +created_by: "OpenCode" +tags: + - "api" + - "reference" + - "release" + - "v1.0.0" + - "marcom" + - "production" +ai_query_hints: + - "Momentry Core Release API 完整列表" + - "API 認證方式與 Base URL(port 3002)" + - "檔案註冊、處理、搜尋、臉部綁定流程" + - "錯誤回應格式(401/400/404)" +related_documents: + - "RELEASE/RELEASE_VERIFICATION_V1.0.0.md" + - "RELEASE/PRODUCTION_VERIFICATION_V1.0.0.md" --- -# Momentry Core API Reference v1.0.0 +# Momentry Core Release API 參考文件 V1.0.0 -56 endpoints across 10 categories, with real curl examples and responses. - -## Base - -| Environment | URL | -|-------------|-----| -| Production | `$BASE` or `https://api.momentry.ddns.net` | -| Development | `http://localhost:3003` | -| Auth | Header `X-API-Key: ` (login endpoint unprotected) | - -### Quick Setup (copy-paste once) - -```bash -BASE=http://localhost:3002 -KEY="X-API-Key: muser_test_apikey" -FILE=3abeee81d94597629ed8cb943f182e94 -``` - -All curl examples below use `$BASE`, `$KEY`, `$FILE`. After running the setup above, you can copy-paste each example directly. +| 項目 | 內容 | +|------|------| +| 建立者 | OpenCode | +| 建立時間 | 2026-05-03 | +| 文件版本 | V4.0 | +| Base URL | `http://localhost:3002` | --- -## 1. System +## 版本歷史 -| # | Method | Path | Description | -|---|--------|------|-------------| -| 1 | GET | `/health` | Server status (ok/degraded) | -| 2 | GET | `/health/detailed` | Per-service health + latency | -| 3 | POST | `/api/v1/auth/login` | Username/password → API key | -| 4 | POST | `/api/v1/auth/logout` | Invalidate session | -| 5 | GET | `/api/v1/stats/ingest` | Ingest statistics | -| 6 | GET | `/api/v1/stats/sftpgo` | SFTPGo status | -| 7 | GET | `/api/v1/stats/inference` | LLM/Embedding health | -| 8 | POST | `/api/v1/config/cache` | Toggle Redis cache | +| 版本 | 日期 | 目的 | 操作人 | 工具/模型 | +|------|------|------|--------|-----------| +| V4.0 | 2026-05-03 | Release 版本:完整 78 端點 API 參考文件 | OpenCode | deepseek-chat | + +--- + +## 認證方式 + +- **Header**: `X-API-Key: ` +- 未提供或無效的 key 回傳 `401 Unauthorized` +- 所有端點(除 `/health` 與 `/health/detailed` 外)都需要 API key + +--- + +## 錯誤回應格式 -```bash -curl $BASE/health -``` ```json -{"status":"ok","version":"1.0.0","uptime_ms":7052517} +// 401 Unauthorized +{ "error": "Unauthorized", "message": "Invalid or missing API key" } + +// 400 Bad Request +{ "error": "Bad Request", "message": "Missing required field: file_path" } + +// 404 Not Found +{ "error": "Not Found", "message": "Video not found: " } ``` --- -## 2. File Management +## 端點列表 -| # | Method | Path | Description | -|---|--------|------|-------------| -| 9 | POST | `/api/v1/files/register` | Register video → file_uuid | -| 10 | POST | `/api/v1/unregister` | Delete file + all data | -| 11 | GET | `/api/v1/files/scan` | Scan directory for new files | -| 12 | GET | `/api/v1/files` | List files (paginated) | -| 13 | GET | `/api/v1/file/:file_uuid` | Single file detail | -| 14 | GET | `/api/v1/file/:file_uuid/probe` | ffprobe metadata | -| 15 | POST | `/api/v1/file/:file_uuid/process` | Start pipeline | -| 16 | GET | `/api/v1/file/:file_uuid/chunks` | List pre-chunks | -| 17 | GET | `/api/v1/progress/:file_uuid` | Processing progress | -| 18 | GET | `/api/v1/jobs` | Monitor jobs (filterable) | +### 1. 系統與認證 + +| # | Method | Path | 說明 | +|---|--------|------|------| +| 1 | GET | `/health` | 系統健康檢查(無需 API key) | +| 2 | GET | `/health/detailed` | 詳細健康狀態(無需 API key) | +| 3 | POST | `/api/v1/auth/login` | 登入 | +| 4 | POST | `/api/v1/auth/logout` | 登出 | + +### 2. 檔案管理 + +| # | Method | Path | 說明 | +|---|--------|------|------| +| 5 | GET | `/api/v1/files` | 檔案列表 | +| 6 | GET | `/api/v1/files/:uuid` | 檔案詳細資訊 | +| 7 | GET | `/api/v1/files/scan` | 掃描目錄中的新檔案 | +| 8 | POST | `/api/v1/files/register` | 註冊檔案 | +| 9 | POST | `/api/v1/unregister` | 取消註冊檔案 | +| 10 | GET | `/api/v1/files/:file_uuid/probe` | 探測檔案資訊(ffprobe) | +| 11 | POST | `/api/v1/files/:file_uuid/process` | 啟動處理 pipeline | +| 12 | GET | `/api/v1/assets/:uuid/status` | 資產處理狀態 | +| 13 | GET | `/api/v1/progress/:uuid` | 處理進度查詢 | +| 14 | GET | `/api/v1/videos/:uuid/details` | 影片詳細資料(含 chunks/pre_chunks) | +| 15 | GET | `/api/v1/videos/:uuid/pre_chunks` | 影片 pre_chunks 列表 | +| 16 | DELETE | `/api/v1/videos/:uuid` | 刪除影片 | + +### 3. 任務與佇列 + +| # | Method | Path | 說明 | +|---|--------|------|------| +| 17 | GET | `/api/v1/jobs` | 任務列表 | +| 18 | GET | `/api/v1/jobs/:job_id` | 任務狀態 | +| 19 | GET | `/api/v1/rules/:rule/status` | Rule 處理狀態 | + +### 4. 搜尋 + +| # | Method | Path | 說明 | +|---|--------|------|------| +| 20 | POST | `/api/v1/search` | 全文搜尋 | +| 21 | POST | `/api/v1/search/hybrid` | 混合搜尋(向量 + BM25) | +| 22 | POST | `/api/v1/search/bm25` | BM25 全文檢索 | +| 23 | POST | `/api/v1/search/universal` | 通用搜尋 | +| 24 | POST | `/api/v1/smart` | 智慧搜尋(多輪對話) | +| 25 | POST | `/api/v1/search/visual` | 視覺搜尋 | +| 26 | POST | `/api/v1/search/visual/class` | 視覺分類搜尋(依物件類別) | +| 27 | POST | `/api/v1/search/visual/density` | 視覺密度搜尋 | +| 28 | POST | `/api/v1/search/visual/stats` | 視覺統計 | +| 29 | POST | `/api/v1/search/visual/combination` | 視覺組合搜尋 | +| 30 | POST | `/api/v1/search/frames` | 影格搜尋 | +| 31 | GET | `/api/v1/search/persons` | 人物搜尋 | +| 32 | GET | `/api/v1/lookup` | UUID 查詢 | + +### 5. 身份(Identity) + +| # | Method | Path | 說明 | +|---|--------|------|------| +| 33 | GET | `/api/v1/identities` | 身份列表 | +| 34 | GET | `/api/v1/identities/:uuid` | 身份詳細資訊 | +| 35 | GET | `/api/v1/identities/:uuid/files` | 身份相關檔案 | +| 36 | GET | `/api/v1/identities/:uuid/chunks` | 身份相關 chunks | +| 37 | POST | `/api/v1/identities/bind` | 綁定身份 | +| 38 | POST | `/api/v1/identities/unbind` | 解除綁定 | +| 39 | POST | `/api/v1/identities/suggest-av` | 建議音視綁定 | +| 40 | POST | `/api/v1/identities/from-face` | 從臉部建立身份 | +| 41 | POST | `/api/v1/identities/from-person` | 從人物建立身份 | +| 42 | GET | `/api/v1/identity/:binding_type/:binding_value` | 依 binding 查詢身份 | + +### 6. 臉部(Face) + +| # | Method | Path | 說明 | +|---|--------|------|------| +| 43 | GET | `/api/v1/faces/candidates` | 臉部候選列表 | +| 44 | POST | `/api/v1/face/recognize` | 臉部辨識 | +| 45 | POST | `/api/v1/face/register` | 註冊臉部 | +| 46 | POST | `/api/v1/face/search` | 臉部搜尋 | +| 47 | GET | `/api/v1/face/list` | 臉部列表 | +| 48 | GET | `/api/v1/face/results/:file_uuid` | 臉部辨識結果 | +| 49 | GET | `/api/v1/files/:file_uuid/faces/:face_id` | 臉部詳細資訊 | +| 50 | DELETE | `/api/v1/files/:file_uuid/faces/:face_id` | 刪除臉部 | +| 51 | GET | `/api/v1/files/:file_uuid/faces/:face_id/thumbnail` | 臉部縮圖 | + +### 7. 信號(Signal) + +| # | Method | Path | 說明 | +|---|--------|------|------| +| 52 | GET | `/api/v1/signals/unbound` | 未綁定信號列表 | +| 53 | GET | `/api/v1/signals/:uuid/:binding_type/:binding_value/timeline` | 信號時間軸 | + +### 8. 檔案身份關聯 + +| # | Method | Path | 說明 | +|---|--------|------|------| +| 54 | GET | `/api/v1/files/:uuid/identities` | 檔案的身份列表 | + +### 9. 快照(Snapshot) + +| # | Method | Path | 說明 | +|---|--------|------|------| +| 55 | GET | `/api/v1/files/:uuid/snapshots` | 取得檔案快照 | +| 56 | POST | `/api/v1/files/:uuid/snapshots` | 產生檔案快照 | +| 57 | GET | `/api/v1/files/:uuid/snapshots/status` | 快照處理狀態 | +| 58 | POST | `/api/v1/files/:uuid/snapshots/migrate` | 遷移快照 | +| 59 | POST | `/api/v1/files/:uuid/snapshots/teardown` | 刪除快照 | +| 60 | GET | `/api/v1/identities/:uuid/snapshots` | 取得身份快照 | +| 61 | POST | `/api/v1/identities/:uuid/snapshots` | 產生身份快照 | + +### 10. Agent + +| # | Method | Path | 說明 | +|---|--------|------|------| +| 62 | POST | `/api/v1/agents/translate` | 翻譯 Agent | +| 63 | POST | `/api/v1/agents/identity/analyze` | 身份分析 Agent | +| 64 | POST | `/api/v1/agents/identity/suggest` | 身份合併建議 | +| 65 | GET | `/api/v1/agents/identity/status` | 身份 Agent 狀態 | +| 66 | POST | `/api/v1/agents/suggest/clustering` | 聚類建議 | +| 67 | POST | `/api/v1/agents/suggest/merge` | 合併建議 | +| 68 | POST | `/api/v1/agents/5w1h/analyze` | 5W1H 分析 | +| 69 | POST | `/api/v1/agents/5w1h/batch` | 5W1H 批量分析 | +| 70 | GET | `/api/v1/agents/5w1h/status` | 5W1H 狀態 | + +### 11. 資源(Resource) + +| # | Method | Path | 說明 | +|---|--------|------|------| +| 71 | POST | `/api/v1/resources/register` | 註冊資源 | +| 72 | POST | `/api/v1/resources/heartbeat` | 資源心跳 | +| 73 | GET | `/api/v1/resources` | 資源列表 | + +### 12. 統計與設定 + +| # | Method | Path | 說明 | +|---|--------|------|------| +| 74 | GET | `/api/v1/stats/ingest` | 攝取統計 | +| 75 | GET | `/api/v1/stats/sftpgo` | SFTPGo 狀態 | +| 76 | GET | `/api/v1/stats/inference` | 推理健康狀態 | +| 77 | POST | `/api/v1/config/cache` | 快取切換 | + +--- + +## 端點範例 + +### GET /health ```bash -curl -X POST $BASE/api/v1/files/register \ - -H "$KEY" \ +curl http://localhost:3002/health +``` + +```json +{ + "status": "ok", + "version": "1.0.0 (build: ...)", + "uptime_ms": 189049 +} +``` + +### POST /api/v1/files/register + +```bash +curl -X POST http://localhost:3002/api/v1/files/register \ -H "Content-Type: application/json" \ - -d '{"file_path":"/sftpgo/data/demo/video.mp4"}' + -H "X-API-Key: " \ + -d '{"file_path": "/path/to/video.mp4"}' ``` + ```json -{"success":true,"file_uuid":"$FILE","duration":5954.0} +{ + "success": true, + "file_uuid": "384b0ff44aaaa1f14cb2cd63b3fea966", + "file_name": "video.mp4", + "duration": 120.5, + "width": 1920, + "height": 1080, + "fps": 30.0 +} ``` +### POST /api/v1/search + ```bash -curl "$BASE/api/v1/files?page=1&page_size=2" -H "$KEY" -``` -```json -{"files":[{"file_name":"Charade (1963)..."}],"total":37} -``` - ---- - -## 3. Search - -| # | Method | Path | Description | -|---|--------|------|-------------| -| 19 | POST | `/api/v1/search/visual` | Visual chunk search | -| 20 | POST | `/api/v1/search/visual/class` | By object class | -| 21 | POST | `/api/v1/search/visual/density` | By spatial density | -| 22 | POST | `/api/v1/search/visual/combination` | Combined visual search | -| 23 | POST | `/api/v1/search/visual/stats` | Visual stats | -| 24 | POST | `/api/v1/search/smart` | Semantic (EmbeddingGemma + pgvector) | -| 25 | POST | `/api/v1/search/universal` | BM25 keyword (requires file_uuid) | -| 26 | POST | `/api/v1/search/frames` | Frame-level search | - -```bash -curl -X POST $BASE/api/v1/search/universal \ - -H "$KEY" \ +curl -X POST http://localhost:3002/api/v1/search \ -H "Content-Type: application/json" \ - -d '{"query":"name","limit":2,"mode":"bm25","uuid":"$FILE"}' -``` -```json -{"count":1,"results":[{"text":"What's your name?","score":0.90}]} + -H "X-API-Key: " \ + -d '{"query": "關鍵字", "uuid": ""}' ``` +```json +{ + "results": [ + { + "chunk_id": "chunk_42", + "text": "轉錄文字內容", + "start_time": 12.5, + "end_time": 15.3, + "score": 0.89 + } + ], + "total": 1 +} +``` + +### GET /api/v1/progress/:uuid + ```bash -curl -X POST $BASE/api/v1/search/universal \ - -H "$KEY" \ +curl http://localhost:3002/api/v1/progress/ \ + -H "X-API-Key: " +``` + +```json +{ + "uuid": "", + "overall_progress": 65, + "processors": [ + {"name": "cut", "status": "completed", "progress": 100}, + {"name": "asr", "status": "running", "progress": 50}, + {"name": "yolo", "status": "pending", "progress": 0} + ] +} +``` + +### POST /api/v1/identities/bind + +```bash +curl -X POST http://localhost:3002/api/v1/identities/bind \ -H "Content-Type: application/json" \ - -d '{"query":"friends","limit":2,"mode":"bm25","uuid":"$FILE"}' + -H "X-API-Key: " \ + -d '{"identity_id": 1, "binding_type": "face", "binding_value": ""}' ``` + ```json -{"count":1,"results":[{"text":"You won't find it difficult to make some new friends.","score":0.90}]} +{ + "success": true, + "message": "Bound face '' to Identity ''" +} +``` + +### GET /api/v1/files/:file_uuid/faces/:face_id/thumbnail + +```bash +curl -o thumbnail.jpg http://localhost:3002/api/v1/files//faces//thumbnail \ + -H "X-API-Key: " +``` + +回傳 JPEG 二進位資料。 + +### GET /api/v1/identities + +```bash +curl "http://localhost:3002/api/v1/identities?page=1&page_size=20" \ + -H "X-API-Key: " +``` + +```json +{ + "identities": [ + {"id": 1, "name": "張三", "binding_count": 5} + ], + "count": 15 +} ``` --- -## 4. Face Trace +## 常見錯誤 -| # | Method | Path | Description | -|---|--------|------|-------------| -| 27 | POST | `/api/v1/file/:file_uuid/face_trace/sortby` | List traces (sorted/filtered) | -| 28 | GET | `/api/v1/file/:file_uuid/trace/:trace_id/faces` | Trace detections (+ interpolation) | - -### sortby — list traces - -Parameters: -- `sort_by`: `face_count` | `duration` | `first_appearance` -- `min_faces`, `min_confidence`, `max_confidence`: filters -- `limit`: max results - -```bash -curl -X POST "$BASE/api/v1/file/$FILE/face_trace/sortby" \ - -H "$KEY" \ - -H "Content-Type: application/json" \ - -d '{"sort_by":"face_count","limit":2}' -``` -```json -{"success":true,"total_traces":6892,"total_faces":108204,"traces":[ - {"trace_id":3128,"face_count":1109,"avg_confidence":0.779}, - {"trace_id":3126,"face_count":743,"avg_confidence":0.758} -]} -``` - -### trace/:trace_id/faces — individual detections - -Parameters: -- `limit`, `offset`: pagination -- `interpolate`: boolean (fills sparse gaps with lerp bbox) - -```bash -curl "$BASE/api/v1/file/$FILE/trace/2/faces?limit=2&interpolate=true" \ - -H "$KEY" -``` -```json -{"success":true,"trace_id":2,"total":1,"faces":[ - {"id":12399,"start_frame":4620,"start_time":184.8,"x":787,"y":582,"width":225,"height":225,"confidence":0.666,"interpolated":false} -]} -``` +| HTTP 狀態 | 原因 | 解決方式 | +|-----------|------|----------| +| 401 | 缺少或無效的 API key | 確認 header `X-API-Key` 已設定 | +| 400 | 請求參數錯誤 | 檢查必要欄位是否遺漏 | +| 404 | 資源不存在 | 確認 file_uuid / identity_id 是否正確 | +| 500 | 伺服器內部錯誤 | 聯繫系統管理員 | --- -## 5. Media +## 重要備註 -| # | Method | Path | Description | -|---|--------|------|-------------| -| 29 | GET | `/api/v1/file/:file_uuid/thumbnail` | Frame JPEG (?frame=&x=&y=&w=&h=) | -| 30 | GET | `/api/v1/file/:file_uuid/video` | Raw video stream (?start=&end=) | -| 31 | GET | `/api/v1/file/:file_uuid/video/bbox` | Bbox overlay (?start=&end=&duration=) | -| 32 | GET | `/api/v1/file/:file_uuid/trace/:trace_id/video` | Trace clip (?padding=) | - -```bash -curl -o thumb.jpg "$BASE/api/v1/file/$FILE/thumbnail?frame=4650" \ - -H "$KEY" -``` -Returns JPEG binary (82KB, 1920×1080). - -```bash -curl -o trace_clip.mp4 "$BASE/api/v1/file/$FILE/trace/2/video" \ - -H "$KEY" -``` -Returns MP4 video binary (3.0MB) with bbox overlay. - ---- - -## 6. Identities - -| # | Method | Path | Description | -|---|--------|------|-------------| -| 33 | GET | `/api/v1/identities` | List all identities | -| 34 | GET | `/api/v1/file/:file_uuid/identities` | Identities in a file | -| 35 | POST | `/api/v1/identity` | Register new identity | -| 36 | GET | `/api/v1/identity/:identity_uuid` | Identity detail | -| 37 | DELETE | `/api/v1/identity/:identity_uuid` | Delete identity | -| 38 | GET | `/api/v1/identity/:identity_uuid/files` | Files for identity | -| 39 | GET | `/api/v1/identity/:identity_uuid/chunks` | Chunks for identity | -| 40 | GET | `/api/v1/faces/candidates` | Unbound face gallery | - -```bash -curl "$BASE/api/v1/identities?page=1&page_size=3" \ - -H "$KEY" -``` -```json -{"identities":[ - {"name":"Cary Grant","tmdb_id":2102}, - {"name":"Audrey Hepburn","tmdb_id":187}, - {"name":"Walter Matthau","tmdb_id":2091} -]} -``` - -```bash -curl "$BASE/api/v1/faces/candidates?page=1&page_size=2" \ - -H "$KEY" -``` -```json -{"total":42,"candidates":[{"frame_number":30,"confidence":0.85},...]} -``` - ---- - -## 7. Identity Binding - -| # | Method | Path | Description | -|---|--------|------|-------------| -| 41 | POST | `/api/v1/identity/:identity_uuid/bind` | Bind face → identity | -| 42 | POST | `/api/v1/identity/:identity_uuid/unbind` | Unbind face from identity | -| 43 | POST | `/api/v1/identity/:from_uuid/mergeinto` | Merge two identities | - -```bash -curl -X POST "$BASE/api/v1/identity/a9a90105-6d6b-46ff-92da-0c3c1a57dff4/bind" \ - -H "$KEY" \ - -H "Content-Type: application/json" \ - -d '{"file_uuid":"$FILE","face_id":"face_42"}' -``` -```json -{"success":true} -``` - ---- - -## 8. Resources - -| # | Method | Path | Description | -|---|--------|------|-------------| -| 44 | POST | `/api/v1/resource/register` | Register processing resource | -| 45 | POST | `/api/v1/resource/heartbeat` | Resource heartbeat | -| 46 | GET | `/api/v1/resources` | List all resources | - -```bash -curl "$BASE/api/v1/resources" \ - -H "$KEY" -``` -```json -{"resources":[{"resource_id":"mxbai-embed-large-v1","resource_type":"embedding_model"}]} -``` - ---- - -## 9. Agents — 5W1H - -| # | Method | Path | Description | -|---|--------|------|-------------| -| 47 | POST | `/api/v1/agents/translate` | AI text translation | -| 48 | POST | `/api/v1/agents/5w1h/analyze` | Single chunk analysis | -| 49 | POST | `/api/v1/agents/5w1h/batch` | Batch analysis | -| 50 | GET | `/api/v1/agents/5w1h/status` | Job status | - -```bash -curl -X POST "$BASE/api/v1/agents/translate" \ - -H "$KEY" \ - -H "Content-Type: application/json" \ - -d '{"text":"Hello world","target_language":"zh-TW"}' -``` -```json -{"success":true,"translated_text":"你好世界"} -``` - ---- - -## 10. Agents — Identity - -| # | Method | Path | Description | -|---|--------|------|-------------| -| 51 | POST | `/api/v1/agents/identity/analyze` | Identify faces in file | -| 52 | GET | `/api/v1/agents/identity/status` | Analysis status | -| 53 | POST | `/api/v1/agents/identity/suggest` | Name suggestions | -| 54 | POST | `/api/v1/agents/suggest/merge` | Suggest merge | -| 55 | POST | `/api/v1/agents/suggest/clustering` | Suggest re-clustering | - ---- - -## Related - -- `API_DICTIONARY_V1.0.0.md` — Quick reference (56 endpoints) -- `API_DOCUMENTATION_v1.0.0.md` — Detailed spec with examples -- `TRACE/TRACE_API_REFERENCE_V1.0.0.md` — Trace-specific reference +- `/:uuid` 與 `/:file_uuid` 均為 32 碼 hex string +- Process 為非同步操作,完成後需透過 Progress 端點輪詢 +- 搜尋端點回傳結果包含 `score`(0.0~1.0),越高越相關 +- 臉部縮圖端點回傳 JPEG binary,非 JSON