Owl3D Cloud API
此 API 可
AI 程式
開始之前
- 在 app.owl3d.com 登入,
並 驗 證你 的 電子 郵件。 - 訂
閱 方案 或 購買 點數。 工作 會 先 使用 方案 的 每 月 點數, 再 使用 已 購買 的 點數。 試用 點數 也 可以 使用。 - 開啟 API 金鑰
頁面 並 建立 金鑰。 頁面 只會 顯示 金鑰 一 次。
將OWL3D_API_KEY。
使用 API 須
export OWL3D_API_KEY="o3d_live_..."驗證
| 項目 | 值 |
|---|---|
| Base URL | https://api.owl3d.com |
| 金鑰格式 | o3d_live_<keyId>_<secret> |
| 驗 |
Authorization: Bearer <key> |
Bearer 的 B 要401。
每jobs:read 或 jobs:write。
請
GET /v1/jobs/{id}
curl https://api.owl3d.com/v1/jobs/job_... \
-H "Authorization: Bearer $OWL3D_API_KEY"{"id": "job_...", "status": "converting"}轉換一支影片
下載
| 腳本 | 需求 | 執行 |
|---|---|---|
| convert.sh | bash, curl, jq, ffprobe | bash convert.sh my-video.mp4 |
| convert.py | Python 3.9+, requests, ffprobe |
python3 convert.py my-video.mp4 |
| convert.mjs | Node.js 20+, ffprobe | node convert.mjs my-video.mp4 |
convert.sh · convert.py · convert.mjs
curl -O https://www.owl3d.com/docs/api/convert.sh
bash convert.sh my-video.mp4腳本
流程
- 讀取
檔案 資訊 並 產生 指紋。 POST /v1/estimates:取得 報價。 不會 扣款。 POST /v1/jobs:同意 報價。 這 會 保留 點數。 - 將
每 個 分段 PUT到它 的 上傳 URL, 然 後 POST /v1/jobs/{id}/upload-complete。 - 每 15 秒
輪詢 GET /v1/jobs/{id}。 GET /v1/jobs/{id}/result:取得 下 載 連結。 連結 有 效 15 分鐘, 且 只 能 用 GET。
先POST /v1/jobs。
錯誤
大多數error 是
| 狀態 | 意義 |
|---|---|
400 |
請求bad_fingerprint |
401 |
沒有 token、 |
402 |
short_of_credits: |
403 |
insufficient_scope, |
404 |
no_job。 |
409 |
狀態not_uploading 或 endpoint_exists |
410 |
輸出insufficient_credits_expired: |
429 |
某 |
重試
- 收到
429時,等 待 Retry-After秒,再 送出 相同 的 請求。 - 收到
5xx或網路 錯誤 時, 以 退避 方式 重試, 間 隔 從 1 秒 增加 到 60 秒。 - 收到
其他 4xx時,請 修正 請求。
curl -i https://api.owl3d.com/v1/jobs/job_unknown \
-H "Authorization: Bearer $OWL3D_API_KEY"{"error": "no_job"}限制
| 限制 | 值 | 回 |
|---|---|---|
| 進行 |
帳號 |
429 concurrency_limit、Retry-After: 15 |
| 請求 | 每 |
429、Retry-After: 60 |
| 突 |
每 |
429 throttled、Retry-After: 1 |
| 每 |
每 |
429 daily_credit_cap, |
| 啟用 |
每 |
拒絕 |
| 輸入 | 100 GB、 |
報價 |
| 容器格式 | MP4, MOV, MKV, M4V | 報價 |
429 concurrency_limit 的scope 為 api(帳號account(帳號key(此
{
"error": "concurrency_limit",
"scope": "api",
"limit": 10,
"inProgress": 10
}路由
| 方法 |
範圍 | 用 |
|---|---|---|
POST /v1/estimates |
jobs:write |
報價 |
POST /v1/jobs |
jobs:write |
保留點數estimateId,filename 和 sizeBytes(先 |
GET /v1/jobs/{id}/upload |
jobs:read |
上done、missing 和parts URL |
POST /v1/jobs/{id}/upload-complete |
jobs:write |
送出 ETag 並 |
GET /v1/jobs/{id} |
jobs:read |
狀態、 |
POST /v1/jobs/{id}/cancel |
jobs:write |
取消 |
POST /v1/jobs/{id}/resume |
jobs:write |
補點數insufficient_credits 的 |
GET /v1/jobs/{id}/result |
jobs:read |
下 |
報價
POST /v1/estimates 提供
| 欄 |
值 |
|---|---|
name、size |
檔案 |
durationSeconds、width、height、fps |
用 |
codec |
H.264、HEVC、AV1、VP9 其中 |
bitDepth、chroma |
從chroma 為 4:2:0 |
fingerprint |
{size, headSha256, tailSha256, edgeBytes} |
edgeBytes為 4194304;檔案 較 小 時, 則 為 檔案 大小。 headSha256和tailSha256是檔案 前 edgeBytes位元組 與 最後 edgeBytes位元組 的 雜湊。
回"ok": false 表示reason。credits.shortBy 大於 0 表示credits.fromPlan、credits.fromTrial 和 credits.fromPurchased 表示
POST /v1/estimates
curl https://api.owl3d.com/v1/estimates \
-H "Authorization: Bearer $OWL3D_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "my-video.mp4",
"size": 104857600,
"durationSeconds": 120,
"width": 1920, "height": 1080, "fps": 24,
"codec": "H.264", "bitDepth": 8, "chroma": "4:2:0",
"fingerprint": {
"size": 104857600,
"headSha256": "<SHA-256 of the first 4194304 bytes>",
"tailSha256": "<SHA-256 of the last 4194304 bytes>",
"edgeBytes": 4194304
}
}'{
"ok": true,
"id": "est_...",
"credits": {
"total": 60,
"fromPlan": 60,
"fromTrial": 0,
"fromPurchased": 0,
"shortBy": 0
},
"etaMinutes": 6,
"hdr": {"detected": false},
"output": {"format": "FULL_SBS", "width": 3840, "height": 1080}
}工作
以 {"estimateId": "est_..."} 呼叫 POST /v1/jobs,id 和upload.partSize 和 upload.parts 的 URL。
輸出選項
POST /v1/jobs 也output: {layout, max_height}。
layout:full_sbs(預設)。 max_height:"source"(預設)、 2160或1080。
POST /v1/jobs
curl https://api.owl3d.com/v1/jobs \
-H "Authorization: Bearer $OWL3D_API_KEY" \
-H "Content-Type: application/json" \
-d '{"estimateId": "est_...", "output": {"layout": "full_sbs", "max_height": "source"}}'{
"id": "job_...",
"status": "uploading",
"upload": {
"partSize": 67108864,
"parts": ["https://...", "https://..."],
"completeUrl": "/v1/jobs/job_.../upload-complete"
}
}先上傳
送出 POST /v1/jobs 時estimateId。
| 欄 |
值 |
|---|---|
filename |
檔名,.mp4、.mov、.mkv 或 .m4v |
sizeBytes |
檔案 |
output |
選用。 |
- 餘額
必須 足以 支付 最 低 價格。 否 則 回應 是 402 short_of_credits,也 不會 建立 工作。 201回應 另外 有 reservedCredits和"priceAfterUpload": true。- 上
傳 後, 伺服器 讀取 檔案 並 決定 價格。 - 如果
伺服器 無法 轉換 這 個 檔案, 工作 會 變成 failed。不會 扣款, 檔案 也 會 刪除。
HDR10 影片400 hdr_needs_estimate。
POST /v1/jobs (upload first)
curl https://api.owl3d.com/v1/jobs \
-H "Authorization: Bearer $OWL3D_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"filename\": \"my-video.mp4\", \"sizeBytes\": $(wc -c < my-video.mp4)}"{
"id": "job_...",
"status": "uploading",
"upload": {
"partSize": 67108864,
"parts": ["https://...", "https://..."],
"completeUrl": "/v1/jobs/job_.../upload-complete"
},
"reservedCredits": 15,
"priceAfterUpload": true
}點數不足
價格insufficient_credits。
GET /v1/jobs/{id}會顯示 shortBy(要補 的 點數)、 neededCredits、deleteAt和resumeUrl。- 補點數
後, 送出 POST /v1/jobs/{id}/resume。不要 重新 上 傳 檔案。 - 餘額
仍 不 足 時, resume 回 應 402 short_of_credits並附上 shortBy。 - 在
deleteAt(24 小時)前沒有 resume, 工作 會 變成 failed,代碼 是 insufficient_credits_expired。檔案 會 刪除。
POST /v1/jobs/{id}/resume
curl -X POST https://api.owl3d.com/v1/jobs/job_.../resume \
-H "Authorization: Bearer $OWL3D_API_KEY"{
"id": "job_...",
"status": "queued"
}{
"error": "short_of_credits",
"shortBy": 120,
"neededCredits": 450,
"deleteAt": "2026-11-04T09:00:00.000Z"
}上傳
- 將
檔案 切成 每 段 upload.partSize位元組 的 分段。 第 1 段 從 位 元組 0 開始。 - 將
每 個 分段 PUT到upload.parts中對 應 的 URL。 保留 每 個 回應 的 ETag標頭,連同 引號。 - 以
{"etags": [...]}呼叫POST /v1/jobs/{id}/upload-complete,ETag 依 分段 順序 排列。
每partSize 位Content-Length。
上
- 呼叫
GET /v1/jobs/{id}/upload。 - 讀取
done。每 個 項目 含 partNumber、etag和size。 - 讀取
missing。它 列出 分段 編號。 - 將
每 個 缺少 的 分段 上 傳到 parts[partNumber - 1]。這些 URL 有效 1 小時。 - 依
分段 順序 帶入 所有 ETag 完成 上 傳。 使用 同 一 個 檔案。
請
PUT upload.parts[n] · POST /v1/jobs/{id}/upload-complete
split -b 67108864 my-video.mp4 part_
curl -sS -D - -o /dev/null -X PUT --upload-file part_aa "<upload.parts[0]>" | grep -i '^etag'
curl -sS -D - -o /dev/null -X PUT --upload-file part_ab "<upload.parts[1]>" | grep -i '^etag'
curl https://api.owl3d.com/v1/jobs/job_.../upload-complete \
-H "Authorization: Bearer $OWL3D_API_KEY" \
-H "Content-Type: application/json" \
-d '{"etags": ["\"<etag of part 1>\"", "\"<etag of part 2>\""]}'{"id": "job_...", "status": "queued"}GET /v1/jobs/{id}/upload
curl https://api.owl3d.com/v1/jobs/job_.../upload \
-H "Authorization: Bearer $OWL3D_API_KEY"{
"id": "job_...",
"partSize": 67108864,
"parts": ["https://...", "https://..."],
"completeUrl": "/v1/jobs/job_.../upload-complete",
"done": [{"partNumber": 1, "etag": "\"...\"", "size": 67108864}],
"missing": [2]
}工作狀態
GET /v1/jobs/{id} 提供
status |
意義 |
|---|---|
uploading |
工作 |
queued |
工作converting 回到 queued |
converting |
progress 從 0 到 1 |
delayed |
由 |
insufficient_credits |
價格shortBy 點後 |
done |
完成。result 含 |
failed |
error 含 code。 |
cancelled |
已 |
GET /v1/jobs/{id}
curl https://api.owl3d.com/v1/jobs/job_... \
-H "Authorization: Bearer $OWL3D_API_KEY"{
"id": "job_...",
"status": "converting",
"progress": 0.42,
"etaSeconds": 310
}結果
GET /v1/jobs/{id}/result 為 done 的GET。410。
GET /v1/jobs/{id}/result
curl https://api.owl3d.com/v1/jobs/job_.../result \
-H "Authorization: Bearer $OWL3D_API_KEY"
curl -o output.mp4 "<url>"{
"url": "https://...",
"filename": "...",
"sizeBytes": 209715200,
"expiresInS": 900
}取消
POST /v1/jobs/{id}/cancel 會progress,
POST /v1/jobs/{id}/cancel
curl -X POST https://api.owl3d.com/v1/jobs/job_.../cancel \
-H "Authorization: Bearer $OWL3D_API_KEY"{"id": "job_...", "status": "cancelled"}