Owl3D Cloud API

该 API 可将 2D 视频转成左右并排 3D。你的代码获取报价、上传文件、等待任务完成,再下载结果。转换方式与 Owl3D Cloud 相同。

AI 编程代理可在 /llms.txt 以纯文本读取本页。

更新于

开始之前

  1. 在 app.owl3d.com 登录,并验证你的邮箱地址。
  2. 订阅套餐或购买积分。任务先使用套餐的每月积分,再使用已购买的积分。试用积分也可以使用。
  3. 打开 API 密钥页面并创建密钥。页面只显示密钥一次。

将密钥放在环境变量 OWL3D_API_KEY 中。本页所有示例都从这里读取密钥。

使用 API 须遵守 Owl3D Cloud API Terms(英文)。

Shell
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。路由表列出每个路由的范围。

请保密密钥。密钥可以花掉你的积分。密钥泄露时,请在 API 密钥页面吊销。吊销的密钥会在 60 秒内失效。

GET /v1/jobs/{id}

curl
curl https://api.owl3d.com/v1/jobs/job_... \
  -H "Authorization: Bearer $OWL3D_API_KEY"
响应200
{"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
curl -O https://www.owl3d.com/docs/api/convert.sh
bash convert.sh my-video.mp4

脚本是可选的。你自己的代码可以用任何语言。它只需要 HTTPS 调用、SHA-256 和文件信息。使用先上传时,只需要 HTTPS 调用。

流程共六步:

  1. 读取文件信息并生成指纹。
  2. POST /v1/estimates:获取报价。不会扣费。
  3. POST /v1/jobs:确认报价。这会预留积分。
  4. 将每个分片 PUT 到它的上传 URL,然后 POST /v1/jobs/{id}/upload-complete。
  5. 每 15 秒轮询 GET /v1/jobs/{id}。
  6. GET /v1/jobs/{id}/result:获取下载链接。链接有效 15 分钟,且只能用 GET。

先上传会跳过第 1 步和第 2 步。你的代码把文件名和文件大小发送到 POST /v1/jobs。上传后,服务器读取文件并决定价格。

错误

大多数错误响应的请求体是 JSON,其中 error 是简短的代码。

状态 含义
400 请求错误,例如 bad_fingerprint
401 没有令牌、令牌错误,或密钥已吊销
402 short_of_credits:套餐积分、试用积分和已购买积分合计仍不够支付价格
403 insufficient_scope,或该路由未公开
404 no_job。在 Cloud 应用中创建的任务,API 看不到
409 状态冲突,例如 not_uploading 或 endpoint_exists
410 输出已过期,或 insufficient_credits_expired:任务等积分已满 24 小时
429 某个上限已满。请见限制

重试规则:

  1. 收到 429 时,等待 Retry-After 秒,再发送相同的请求。
  2. 收到 5xx 或网络错误时,退避重试,间隔从 1 秒增加到 60 秒。
  3. 收到其他 4xx 时,请修正请求。
curl
curl -i https://api.owl3d.com/v1/jobs/job_unknown \
  -H "Authorization: Bearer $OWL3D_API_KEY"
响应404
{"error": "no_job"}

限制

限制 值 响应
进行中的任务 账户的所有 API 密钥合计 10 个。账户所有渠道合计 15 个。每个密钥可另设上限 429 concurrency_limit、Retry-After: 15
请求 每个密钥每分钟 120 次 429、Retry-After: 60
突发 每个路由每秒 10 次,突发 20 次,所有调用方合计 429 throttled、Retry-After: 1
每日积分上限 每个密钥可选 429 daily_credit_cap,直到 00:00 UTC
有效密钥 每个账户 10 个 拒绝创建
输入 100 GB、3 小时、4096 x 2160、60 fps 报价被拒绝
容器格式 MP4, MOV, MKV, M4V 报价被拒绝

429 concurrency_limit 的响应体会写出已满的上限。scope 为 api(账户的所有 API 密钥)、account(账户的所有任务)或 key(此密钥)。等一个任务结束后,再开始下一个。

响应429
{
  "error": "concurrency_limit",
  "scope": "api",
  "limit": 10,
  "inProgress": 10
}

价格

付款前,POST /v1/estimates 会给出文件的确切价格。

两种方式都一样:服务器读取上传的文件,并按文件决定最终价格。使用先上传时,上传后才能看到价格。余额不够支付价格时,任务会等待。请见积分不足。

路由

方法和路径 范围 用途
POST /v1/estimates jobs:write 报价和预计时间。不会扣费。有效 1 小时,仅限一个任务
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 下载链接,15 分钟

报价

POST /v1/estimates 给出一个文件的价格和时间。不会扣费。报价有效 1 小时,仅限一个任务。

字段 值
name、size 文件名,以及以字节计的大小
durationSeconds、width、height、fps 用任何工具从文件读取,例如 ffprobe 或 MediaInfo
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
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
    }
  }'
响应200
{
  "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
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"}}'
响应201
{
  "id": "job_...",
  "status": "uploading",
  "upload": {
    "partSize": 67108864,
    "parts": ["https://...", "https://..."],
    "completeUrl": "/v1/jobs/job_.../upload-complete"
  }
}

先上传

发送 POST /v1/jobs 时不带 estimateId。你的代码不用读取文件,也不用生成指纹。

字段 值
filename 文件名,最多 255 个字符。以 .mp4、.mov、.mkv 或 .m4v 结尾
sizeBytes 文件大小,单位为字节
output 可选。请见输出选项
  1. 余额必须够支付最低价格。否则返回 402 short_of_credits,也不会创建任务。
  2. 201 响应另外有 reservedCredits 和 "priceAfterUpload": true。
  3. 上传后,服务器读取文件并决定价格。
  4. 如果服务器无法转换这个文件,任务会变成 failed。不会扣费,文件也会删除。

HDR10 视频需要报价。没有报价时,返回 400 hdr_needs_estimate。

POST /v1/jobs (upload first)

curl
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)}"
响应201
{
  "id": "job_...",
  "status": "uploading",
  "upload": {
    "partSize": 67108864,
    "parts": ["https://...", "https://..."],
    "completeUrl": "/v1/jobs/job_.../upload-complete"
  },
  "reservedCredits": 15,
  "priceAfterUpload": true
}

积分不足

价格高于余额时,任务会变成 insufficient_credits。不会扣费。有报价和没有报价的任务都一样。

  1. GET /v1/jobs/{id} 会显示 shortBy(要补充的积分)、neededCredits、deleteAt 和 resumeUrl。
  2. 补充积分后,发送 POST /v1/jobs/{id}/resume。不要重新上传文件。
  3. 余额仍不够时,resume 返回 402 short_of_credits 并附带 shortBy。
  4. 在 deleteAt(24 小时)前没有 resume,任务会变成 failed,代码是 insufficient_credits_expired。文件会删除。

POST /v1/jobs/{id}/resume

curl
curl -X POST https://api.owl3d.com/v1/jobs/job_.../resume \
  -H "Authorization: Bearer $OWL3D_API_KEY"
响应200
{
  "id": "job_...",
  "status": "queued"
}
响应402
{
  "error": "short_of_credits",
  "shortBy": 120,
  "neededCredits": 450,
  "deleteAt": "2026-11-04T09:00:00.000Z"
}

上传

  1. 将文件切成每片 upload.partSize 字节的分片。第 1 片从字节 0 开始。
  2. 将每个分片 PUT 到 upload.parts 中对应的 URL。保留每个响应的 ETag 头,连同引号。
  3. 以 {"etags": [...]} 调用 POST /v1/jobs/{id}/upload-complete,ETag 按分片顺序排列。

每个 URL 只签名一个固定长度。每片必须是 partSize 字节,最后一片放剩下的部分。长度不符或使用 chunked 请求体时,存储服务会返回 403。请发送 Content-Length。

上传中断时,不要重新开始:

  1. 调用 GET /v1/jobs/{id}/upload。
  2. 读取 done。每一项含 partNumber、etag 和 size。
  3. 读取 missing。它列出分片编号。
  4. 将每个缺少的分片上传到 parts[partNumber - 1]。这些 URL 有效 1 小时。
  5. 按分片顺序带上所有 ETag 完成上传。使用同一个文件。

请在 24 小时内完成上传。超过时间后,存储会移除未完成上传的分片。

PUT upload.parts[n] · POST /v1/jobs/{id}/upload-complete

curl
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>\""]}'
响应200
{"id": "job_...", "status": "queued"}

GET /v1/jobs/{id}/upload

curl
curl https://api.owl3d.com/v1/jobs/job_.../upload \
  -H "Authorization: Bearer $OWL3D_API_KEY"
响应200
{
  "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} 给出状态、进度和剩余时间。每 15 秒轮询一次。

status 含义
uploading 任务在等待文件
queued 任务在等待 GPU。任务可能短暂地从 converting 回到 queued
converting progress 从 0 到 1
delayed 由我们这边暂缓。积分仍预留
insufficient_credits 价格高于余额。补充 shortBy 积分后再 resume。请见积分不足
done 完成。result 含名称、大小和链接路径
failed error 含 code。积分已退回
cancelled 已被调用方取消

GET /v1/jobs/{id}

curl
curl https://api.owl3d.com/v1/jobs/job_... \
  -H "Authorization: Bearer $OWL3D_API_KEY"
响应200
{
  "id": "job_...",
  "status": "converting",
  "progress": 0.42,
  "etaSeconds": 310
}

结果

GET /v1/jobs/{id}/result 为 done 的任务给出下载链接。链接有效 15 分钟,且只能用 GET。需要新链接时,再调用一次此路由。输出已过期时,响应为 410。

GET /v1/jobs/{id}/result

curl
curl https://api.owl3d.com/v1/jobs/job_.../result \
  -H "Authorization: Bearer $OWL3D_API_KEY"
curl -o output.mp4 "<url>"
响应200
{
  "url": "https://...",
  "filename": "...",
  "sizeBytes": 209715200,
  "expiresInS": 900
}

取消

POST /v1/jobs/{id}/cancel 会取消任务。转换开始前取消的任务不收费。开始后取消,费用为报价 x progress,向上取整,至少 1 积分。

POST /v1/jobs/{id}/cancel

curl
curl -X POST https://api.owl3d.com/v1/jobs/job_.../cancel \
  -H "Authorization: Bearer $OWL3D_API_KEY"
响应200
{"id": "job_...", "status": "cancelled"}

第一时间获取最新动态!

Owl3D
© 2026 Owl3D 版权所有。