Owl3D Cloud API

이 API는 2D 영상을 사이드 바이 사이드 3D로 변환합니다. 코드에서 가격을 받고, 파일을 업로드하고, 작업이 끝나기를 기다린 뒤 결과를 다운로드합니다. 변환 방식은 Owl3D Cloud와 같습니다.

AI 코딩 에이전트는 /llms.txt에서 이 페이지를 일반 텍스트로 읽을 수 있습니다. AI 에이전트는 Owl3D MCP 서버로 코드 없이 동영상을 변환할 수도 있습니다.

업데이트:

시작하기 전에

  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. 각 파트를 업로드 URL에 PUT한 다음 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"
  }
}

먼저 업로드

estimateId 없이 POST /v1/jobs를 보냅니다. 코드는 파일을 읽지 않고 핑거프린트도 만들지 않습니다.

필드 값
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은 shortBy와 함께 402 short_of_credits를 반환합니다.
  4. deleteAt(24시간)까지 resume하지 않으면 작업은 insufficient_credits_expired로 failed가 됩니다. 파일은 삭제됩니다.

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. 각 파트를 upload.parts의 해당 URL에 PUT합니다. 각 응답의 ETag 헤더를 따옴표까지 그대로 보관합니다.
  3. 파트 순서대로 {"etags": [...]}를 담아 POST /v1/jobs/{id}/upload-complete를 호출합니다.

각 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. All rights reserved.