Owl3D Cloud API

Die API wandelt ein 2D-Video in Side-by-Side-3D um. Ihr Code holt einen Preis, lädt die Datei hoch, wartet auf den Auftrag und lädt das Ergebnis herunter. Sie führt dieselbe Umwandlung aus wie Owl3D Cloud.

Ein KI-Coding-Agent kann diese Seite als reinen Text unter /llms.txt lesen.

Aktualisiert am

Vor dem Start

  1. Melden Sie sich unter app.owl3d.com an und bestätigen Sie Ihre E-Mail-Adresse.
  2. Wählen Sie einen Tarif oder kaufen Sie Credits. Ein Auftrag verbraucht zuerst die monatlichen Credits Ihres Tarifs, dann gekaufte Credits. Test-Credits zählen ebenfalls.
  3. Öffnen Sie API-Schlüssel und erstellen Sie einen Schlüssel. Die Seite zeigt den Schlüssel nur einmal an.

Legen Sie den Schlüssel in der Umgebungsvariable OWL3D_API_KEY ab. Alle Beispiele auf dieser Seite lesen ihn von dort.

Für die Nutzung der API gelten die Owl3D Cloud API Terms (auf Englisch).

Shell
export OWL3D_API_KEY="o3d_live_..."

Authentifizierung

Element Wert
Basis-URL https://api.owl3d.com
Schlüsselformat o3d_live_<keyId>_<secret>
Anmelde-Header Authorization: Bearer <key>

Schreiben Sie Bearer mit großem B und einem Leerzeichen. Andere Formen erhalten 401.

Jede Route braucht einen Scope: jobs:read oder jobs:write. Die Routentabelle nennt den Scope jeder Route.

Halten Sie den API-Schlüssel geheim. Er kann Ihre Credits ausgeben. Wenn ein Schlüssel offengelegt wurde, widerrufen Sie ihn auf der Seite für API-Schlüssel. Ein widerrufener Schlüssel wird innerhalb von 60 Sekunden ungültig.

GET /v1/jobs/{id}

curl
curl https://api.owl3d.com/v1/jobs/job_... \
  -H "Authorization: Bearer $OWL3D_API_KEY"
Antwort200
{"id": "job_...", "status": "converting"}

Ein Video umwandeln

Laden Sie ein Skript herunter und führen Sie es mit Ihrem Video aus. Jedes Skript führt alle folgenden Schritte aus.

Skript Voraussetzungen Aufruf
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

Die Skripte sind optional. Ihr eigener Code kann jede Sprache verwenden. Er braucht HTTPS-Aufrufe, SHA-256 und die Dateiangaben. Mit Upload zuerst braucht er nur HTTPS-Aufrufe.

Der Ablauf hat sechs Schritte:

  1. Dateiangaben lesen und den Fingerabdruck erstellen.
  2. POST /v1/estimates: den Preis abfragen. Es wird nichts berechnet.
  3. POST /v1/jobs: den Preis bestätigen. Dies reserviert die Credits.
  4. Jeden Teil per PUT an seine Upload-URL senden, dann POST /v1/jobs/{id}/upload-complete.
  5. GET /v1/jobs/{id} alle 15 Sekunden abfragen.
  6. GET /v1/jobs/{id}/result: einen Download-Link abrufen. Der Link gilt 15 Minuten und nur für GET.

Upload zuerst lässt die Schritte 1 und 2 weg. Ihr Code sendet Dateiname und Dateigröße an POST /v1/jobs. Nach dem Upload liest der Server die Datei und legt den Preis fest.

Fehler

Die meisten Fehlerantworten haben einen JSON-Body mit error, einem kurzen Code.

Status Bedeutung
400 Ungültige Anfrage, zum Beispiel bad_fingerprint
401 Kein Token, ein falsches Token oder ein widerrufener Schlüssel
402 short_of_credits: Tarif-Credits, Test-Credits und gekaufte Credits reichen zusammen nicht für den Preis
403 insufficient_scope oder die Route ist nicht öffentlich
404 no_job. In der Cloud-App erstellte Aufträge sind für die API nicht sichtbar
409 Zustandskonflikt, zum Beispiel not_uploading oder endpoint_exists
410 Das Ergebnis ist abgelaufen, oder insufficient_credits_expired: Der Auftrag hat 24 Stunden auf Credits gewartet
429 Ein Limit ist voll. Siehe Limits

Regeln für Wiederholungen:

  1. Bei 429 warten Sie Retry-After Sekunden und senden dieselbe Anfrage erneut.
  2. Bei 5xx oder einem Netzwerkfehler erhöhen Sie die Wartezeit schrittweise von 1 Sekunde bis 60 Sekunden.
  3. Bei jedem anderen 4xx korrigieren Sie die Anfrage.
curl
curl -i https://api.owl3d.com/v1/jobs/job_unknown \
  -H "Authorization: Bearer $OWL3D_API_KEY"
Antwort404
{"error": "no_job"}

Limits

Limit Wert Antwort
Laufende Aufträge 10 für alle API-Schlüssel eines Kontos zusammen. 15 für das ganze Konto, alle Kanäle zusammen. Optional ein Limit pro Schlüssel 429 concurrency_limit, Retry-After: 15
Anfragen 120 pro Minute und Schlüssel 429, Retry-After: 60
Burst Jede Route 10 pro Sekunde, Burst 20, für alle Aufrufer zusammen 429 throttled, Retry-After: 1
Tägliches Credit-Limit Optional pro Schlüssel 429 daily_credit_cap, bis 00:00 UTC
Aktive Schlüssel 10 pro Konto Erstellen abgelehnt
Eingabe 100 GB, 3 Stunden, 4096 x 2160, 60 fps Preisabfrage abgelehnt
Container MP4, MOV, MKV, M4V Preisabfrage abgelehnt

Der Body einer 429 concurrency_limit nennt das volle Limit. scope ist api (alle API-Schlüssel des Kontos), account (alle Aufträge des Kontos) oder key (dieser Schlüssel). Starten Sie den nächsten Auftrag, wenn einer endet.

Antwort429
{
  "error": "concurrency_limit",
  "scope": "api",
  "limit": 10,
  "inProgress": 10
}

Preise

POST /v1/estimates nennt den genauen Preis einer Datei, bevor Sie bezahlen.

Auf beiden Wegen liest der Server die hochgeladene Datei und legt daraus den endgültigen Preis fest. Mit Upload zuerst sehen Sie den Preis erst nach dem Upload. Wenn das Guthaben den Preis nicht deckt, wartet der Auftrag. Siehe Zu wenig Credits.

Routen

Methode und Pfad Scope Funktion
POST /v1/estimates jobs:write Preis und Dauer. Es wird nichts berechnet. 1 Stunde gültig, für einen Auftrag
POST /v1/jobs jobs:write Reserviert Credits und gibt den Upload-Plan zurück. Mit estimateId, oder mit filename und sizeBytes (Upload zuerst)
GET /v1/jobs/{id}/upload jobs:read Upload-Status: done, missing und neue parts-URLs
POST /v1/jobs/{id}/upload-complete jobs:write Sendet die ETags und stellt den Auftrag in die Warteschlange
GET /v1/jobs/{id} jobs:read Status, Fortschritt, verbleibende Zeit
POST /v1/jobs/{id}/cancel jobs:write Bricht den Auftrag ab
POST /v1/jobs/{id}/resume jobs:write Setzt einen Auftrag mit insufficient_credits fort, nachdem Sie Credits hinzugefügt haben. Kein neuer Upload
GET /v1/jobs/{id}/result jobs:read Download-Link, 15 Minuten

Preisabfragen

POST /v1/estimates nennt Preis und Dauer für eine Datei. Es wird nichts berechnet. Eine Preisabfrage gilt 1 Stunde, für einen Auftrag.

Feld Wert
name, size Der Dateiname und die Größe in Bytes
durationSeconds, width, height, fps Mit einem beliebigen Werkzeug aus der Datei gelesen, etwa ffprobe oder MediaInfo
codec Einer von H.264, HEVC, AV1, VP9
bitDepth, chroma Aus der Datei gelesen. chroma ist 4:2:0
fingerprint {size, headSha256, tailSha256, edgeBytes}
  • edgeBytes ist 4194304 oder bei einer kleineren Datei die Dateigröße.
  • headSha256 und tailSha256 sind die Hashes der ersten und der letzten edgeBytes der Datei.

In der Antwort bedeutet "ok": false, dass die Preisabfrage abgelehnt wird. Lesen Sie reason. Ist credits.shortBy größer als 0, braucht das Konto mehr Credits. credits.fromPlan, credits.fromTrial und credits.fromPurchased zeigen, welche Credits den Preis bezahlen.

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
    }
  }'
Antwort200
{
  "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}
}

Aufträge

POST /v1/jobs mit {"estimateId": "est_..."} bestätigt den Preis. Dies reserviert die Credits. Die Antwort enthält die id des Auftrags und den Upload-Plan: upload.partSize und die URLs in upload.parts.

Ausgabeoptionen

POST /v1/jobs akzeptiert zusätzlich output: {layout, max_height}.

  • layout: full_sbs (Standard).
  • max_height: "source" (Standard), 2160 oder 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"}}'
Antwort201
{
  "id": "job_...",
  "status": "uploading",
  "upload": {
    "partSize": 67108864,
    "parts": ["https://...", "https://..."],
    "completeUrl": "/v1/jobs/job_.../upload-complete"
  }
}

Upload zuerst

Senden Sie POST /v1/jobs ohne estimateId. Ihr Code liest die Datei nicht und erstellt keinen Fingerabdruck.

Feld Wert
filename Der Dateiname, höchstens 255 Zeichen. Er endet auf .mp4, .mov, .mkv oder .m4v
sizeBytes Die Dateigröße in Bytes
output Optional. Siehe Ausgabeoptionen
  1. Das Guthaben muss den Mindestpreis decken. Sonst lautet die Antwort 402 short_of_credits, und es entsteht kein Auftrag.
  2. Die Antwort 201 enthält zusätzlich reservedCredits und "priceAfterUpload": true.
  3. Nach dem Upload liest der Server die Datei und legt den Preis fest.
  4. Wenn der Server die Datei nicht umwandeln kann, geht der Auftrag auf failed. Es wird nichts berechnet, und die Datei wird gelöscht.

HDR10-Videos brauchen eine Preisabfrage. Ohne sie lautet die Antwort 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)}"
Antwort201
{
  "id": "job_...",
  "status": "uploading",
  "upload": {
    "partSize": 67108864,
    "parts": ["https://...", "https://..."],
    "completeUrl": "/v1/jobs/job_.../upload-complete"
  },
  "reservedCredits": 15,
  "priceAfterUpload": true
}

Zu wenig Credits

Wenn der Preis über dem Guthaben liegt, geht der Auftrag auf insufficient_credits. Es wird nichts berechnet. Das gilt für beide Wege, mit oder ohne Preisabfrage.

  1. GET /v1/jobs/{id} zeigt shortBy (die fehlenden Credits), neededCredits, deleteAt und resumeUrl.
  2. Fügen Sie Credits hinzu und senden Sie dann POST /v1/jobs/{id}/resume. Laden Sie die Datei nicht erneut hoch.
  3. Solange das Guthaben noch nicht reicht, antwortet resume mit 402 short_of_credits und shortBy.
  4. Ohne resume vor deleteAt (24 Stunden) geht der Auftrag auf failed mit insufficient_credits_expired. Die Datei wird gelöscht.

POST /v1/jobs/{id}/resume

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

Uploads

  1. Teilen Sie die Datei in Teile von upload.partSize Bytes. Teil 1 beginnt bei Byte 0.
  2. Senden Sie jeden Teil per PUT an seine URL in upload.parts. Behalten Sie den ETag-Header jeder Antwort samt Anführungszeichen.
  3. Senden Sie POST /v1/jobs/{id}/upload-complete mit {"etags": [...]} in der Reihenfolge der Teile.

Jede URL ist für eine genaue Länge signiert. Ein Teil muss partSize Bytes groß sein, der letzte Teil enthält den Rest. Der Speicher antwortet mit 403 bei jeder anderen Länge und bei einem Chunked-Body. Senden Sie Content-Length.

Wenn ein Upload abbricht, beginnen Sie nicht von vorn:

  1. Rufen Sie GET /v1/jobs/{id}/upload auf.
  2. Lesen Sie done. Jeder Eintrag hat partNumber, etag und size.
  3. Lesen Sie missing. Es listet Teilnummern.
  4. Laden Sie jeden fehlenden Teil an parts[partNumber - 1] hoch. Diese URLs sind 1 Stunde lang gültig.
  5. Schließen Sie mit allen ETags in der Reihenfolge der Teile ab. Verwenden Sie dieselbe Datei.

Schließen Sie einen Upload innerhalb von 24 Stunden ab. Danach entfernt der Speicher die Teile eines nicht abgeschlossenen Uploads.

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>\""]}'
Antwort200
{"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"
Antwort200
{
  "id": "job_...",
  "partSize": 67108864,
  "parts": ["https://...", "https://..."],
  "completeUrl": "/v1/jobs/job_.../upload-complete",
  "done": [{"partNumber": 1, "etag": "\"...\"", "size": 67108864}],
  "missing": [2]
}

Auftragsstatus

GET /v1/jobs/{id} nennt Status, Fortschritt und verbleibende Zeit. Fragen Sie alle 15 Sekunden ab.

status Bedeutung
uploading Der Auftrag wartet auf die Datei
queued Der Auftrag wartet auf eine GPU. Ein Auftrag kann kurz von converting zurück zu queued wechseln
converting progress geht von 0 bis 1
delayed Auf unserer Seite angehalten. Die Credits bleiben reserviert
insufficient_credits Der Preis liegt über dem Guthaben. Fügen Sie shortBy Credits hinzu und rufen Sie dann resume auf. Siehe Zu wenig Credits
done Fertig. result enthält Name, Größe und Link-Pfad
failed error enthält einen code. Die Credits wurden zurückgebucht
cancelled Vom Aufrufer abgebrochen

GET /v1/jobs/{id}

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

Ergebnisse

GET /v1/jobs/{id}/result gibt einen Download-Link für einen Auftrag mit done. Der Link gilt 15 Minuten und nur für GET. Für einen neuen Link rufen Sie die Route erneut auf. Ist das Ergebnis abgelaufen, lautet die Antwort 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>"
Antwort200
{
  "url": "https://...",
  "filename": "...",
  "sizeBytes": 209715200,
  "expiresInS": 900
}

Abbrechen

POST /v1/jobs/{id}/cancel bricht einen Auftrag ab. Ein Auftrag, der vor dem Start der Umwandlung abgebrochen wird, kostet nichts. Danach kostet er den Preis x progress, aufgerundet, mindestens 1 Credit.

POST /v1/jobs/{id}/cancel

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

Bleib auf dem Laufenden!

Owl3D
© 2026 Owl3D. Alle Rechte vorbehalten.