API Owl3D Cloud

L'API convertit une vidéo 2D en 3D côte à côte. Votre code obtient un prix, envoie le fichier, attend la tâche et télécharge le résultat. Elle exécute la même conversion qu'Owl3D Cloud.

Un agent de code IA peut lire cette page en texte brut à l'adresse /llms.txt.

Mis à jour le

Avant de commencer

  1. Connectez-vous sur app.owl3d.com et vérifiez votre adresse e-mail.
  2. Prenez un forfait ou achetez des crédits. Une tâche dépense d'abord les crédits mensuels du forfait, puis les crédits achetés. Les crédits d'essai comptent aussi.
  3. Ouvrez Clés API et créez une clé. La page affiche la clé une seule fois.

Gardez la clé dans la variable d'environnement OWL3D_API_KEY. Tous les exemples de cette page la lisent à cet endroit.

L'utilisation de l'API est soumise aux Owl3D Cloud API Terms (en anglais).

Shell
export OWL3D_API_KEY="o3d_live_..."

Authentification

Élément Valeur
URL de base https://api.owl3d.com
Format de la clé o3d_live_<keyId>_<secret>
En-tête d'authentification Authorization: Bearer <key>

Écrivez Bearer avec un B majuscule et une seule espace. Les autres formes reçoivent 401.

Chaque route demande un scope : jobs:read ou jobs:write. Le tableau des routes donne le scope de chaque route.

Gardez la clé API secrète. Elle peut dépenser vos crédits. Si une clé fuit, révoquez-la sur la page des clés API. Une clé révoquée cesse de fonctionner en 60 secondes.

GET /v1/jobs/{id}

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

Convertir une vidéo

Téléchargez un script et exécutez-le sur votre vidéo. Chaque script effectue toutes les étapes ci-dessous.

Script Prérequis Exécution
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

Les scripts sont facultatifs. Votre code peut utiliser n'importe quel langage. Il lui faut des appels HTTPS, SHA-256 et les informations du fichier. Avec l'envoi d'abord, il lui faut seulement des appels HTTPS.

Le déroulement comporte six étapes :

  1. Lire les informations du fichier et calculer l'empreinte.
  2. POST /v1/estimates : obtenir le prix. Rien n'est facturé.
  3. POST /v1/jobs : approuver le prix. Cela réserve les crédits.
  4. Envoyer chaque partie par PUT à son URL d'envoi, puis POST /v1/jobs/{id}/upload-complete.
  5. Interroger GET /v1/jobs/{id} toutes les 15 secondes.
  6. GET /v1/jobs/{id}/result : obtenir un lien de téléchargement. Le lien est valable 15 minutes et uniquement pour GET.

L'envoi d'abord saute les étapes 1 et 2. Votre code envoie le nom et la taille du fichier à POST /v1/jobs. Après l'envoi, le serveur lit le fichier et fixe le prix.

Erreurs

La plupart des réponses d'erreur ont un corps JSON avec error, un code court.

Statut Signification
400 Requête incorrecte, par exemple bad_fingerprint
401 Pas de jeton, un jeton incorrect ou une clé révoquée
402 short_of_credits : ensemble, les crédits du forfait, d'essai et achetés ne couvrent pas le prix
403 insufficient_scope, ou la route n'est pas publique
404 no_job. Les tâches créées dans l'application Cloud ne sont pas visibles pour l'API
409 Conflit d'état, par exemple not_uploading ou endpoint_exists
410 Le résultat a expiré, ou insufficient_credits_expired : la tâche a attendu des crédits pendant 24 heures
429 Une limite est atteinte. Voir Limites

Règles de nouvelle tentative :

  1. Sur 429, attendez Retry-After secondes et renvoyez la même requête.
  2. Sur 5xx ou une erreur réseau, augmentez progressivement le délai de 1 seconde à 60 secondes.
  3. Sur tout autre 4xx, corrigez la requête.
curl
curl -i https://api.owl3d.com/v1/jobs/job_unknown \
  -H "Authorization: Bearer $OWL3D_API_KEY"
Réponse404
{"error": "no_job"}

Limites

Limite Valeur Réponse
Tâches en cours 10 pour toutes les clés API d'un compte ensemble. 15 pour tout le compte, tous canaux ensemble. Limite facultative par clé 429 concurrency_limit, Retry-After: 15
Requêtes 120 par minute et par clé 429, Retry-After: 60
Rafale Chaque route 10 par seconde, rafale de 20, pour tous les appelants ensemble 429 throttled, Retry-After: 1
Plafond quotidien de crédits Facultatif par clé 429 daily_credit_cap, jusqu'à 00:00 UTC
Clés actives 10 par compte Création refusée
Entrée 100 Go, 3 heures, 4096 x 2160, 60 fps Estimation refusée
Conteneurs MP4, MOV, MKV, M4V Estimation refusée

Le corps d'une réponse 429 concurrency_limit nomme la limite atteinte. scope vaut api (toutes les clés API du compte), account (toutes les tâches du compte) ou key (cette clé). Lancez la tâche suivante quand une tâche se termine.

Réponse429
{
  "error": "concurrency_limit",
  "scope": "api",
  "limit": 10,
  "inProgress": 10
}

Tarifs

POST /v1/estimates donne le prix exact d'un fichier avant que vous payiez.

Dans les deux cas, le serveur lit le fichier envoyé et fixe le prix final à partir de ce fichier. Avec l'envoi d'abord, vous voyez le prix seulement après l'envoi. Si le solde ne couvre pas le prix, la tâche attend. Voir Crédits insuffisants.

Routes

Méthode et chemin Scope Fonction
POST /v1/estimates jobs:write Prix et durée. Rien n'est facturé. Valable 1 heure, pour une seule tâche
POST /v1/jobs jobs:write Réserve des crédits et renvoie le plan d'envoi. Avec estimateId, ou avec filename et sizeBytes (envoi d'abord)
GET /v1/jobs/{id}/upload jobs:read État de l'envoi : done, missing et de nouvelles URL parts
POST /v1/jobs/{id}/upload-complete jobs:write Envoie les ETags et met la tâche en file d'attente
GET /v1/jobs/{id} jobs:read Statut, progression, temps restant
POST /v1/jobs/{id}/cancel jobs:write Annule la tâche
POST /v1/jobs/{id}/resume jobs:write Reprend une tâche insufficient_credits après l'ajout de crédits. Aucun nouvel envoi
GET /v1/jobs/{id}/result jobs:read Lien de téléchargement, 15 minutes

Estimations

POST /v1/estimates donne le prix et la durée d'un fichier. Rien n'est facturé. Une estimation est valable 1 heure, pour une seule tâche.

Champ Valeur
name, size Le nom du fichier et sa taille en octets
durationSeconds, width, height, fps Lus dans le fichier avec n'importe quel outil, comme ffprobe ou MediaInfo
codec H.264, HEVC, AV1 ou VP9
bitDepth, chroma Lus dans le fichier. chroma vaut 4:2:0
fingerprint {size, headSha256, tailSha256, edgeBytes}
  • edgeBytes vaut 4194304, ou la taille du fichier pour un fichier plus petit.
  • headSha256 et tailSha256 sont les hachages des premiers et des derniers edgeBytes du fichier.

Dans la réponse, "ok": false signifie que l'estimation est refusée. Lisez reason. Si credits.shortBy est supérieur à 0, le compte a besoin de plus de crédits. credits.fromPlan, credits.fromTrial et credits.fromPurchased indiquent quels crédits paient le prix.

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
    }
  }'
Réponse200
{
  "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}
}

Tâches

POST /v1/jobs avec {"estimateId": "est_..."} approuve le prix. Cela réserve les crédits. La réponse contient l'id de la tâche et le plan d'envoi : upload.partSize et les URL de upload.parts.

Options de sortie

POST /v1/jobs accepte aussi output: {layout, max_height}.

  • layout : full_sbs (par défaut).
  • max_height : "source" (par défaut), 2160 ou 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"}}'
Réponse201
{
  "id": "job_...",
  "status": "uploading",
  "upload": {
    "partSize": 67108864,
    "parts": ["https://...", "https://..."],
    "completeUrl": "/v1/jobs/job_.../upload-complete"
  }
}

Envoi d'abord

Envoyez POST /v1/jobs sans estimateId. Votre code ne lit pas le fichier et ne crée pas d'empreinte.

Champ Valeur
filename Le nom du fichier, 255 caractères au plus. Il se termine par .mp4, .mov, .mkv ou .m4v
sizeBytes La taille du fichier en octets
output Facultatif. Voir Options de sortie
  1. Le solde doit couvrir le prix minimum. Sinon, la réponse est 402 short_of_credits et aucune tâche n'est créée.
  2. La réponse 201 contient aussi reservedCredits et "priceAfterUpload": true.
  3. Après l'envoi, le serveur lit le fichier et fixe le prix.
  4. Si le serveur ne peut pas convertir le fichier, la tâche passe à failed. Rien n'est facturé et le fichier est supprimé.

Une vidéo HDR10 a besoin d'une estimation. Sans estimation, la réponse est 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)}"
Réponse201
{
  "id": "job_...",
  "status": "uploading",
  "upload": {
    "partSize": 67108864,
    "parts": ["https://...", "https://..."],
    "completeUrl": "/v1/jobs/job_.../upload-complete"
  },
  "reservedCredits": 15,
  "priceAfterUpload": true
}

Crédits insuffisants

Si le prix dépasse le solde, la tâche passe à insufficient_credits. Rien n'est facturé. C'est la même chose avec ou sans estimation.

  1. GET /v1/jobs/{id} affiche shortBy (les crédits à ajouter), neededCredits, deleteAt et resumeUrl.
  2. Ajoutez des crédits, puis envoyez POST /v1/jobs/{id}/resume. N'envoyez pas le fichier une deuxième fois.
  3. Tant que le solde reste trop bas, resume répond 402 short_of_credits avec shortBy.
  4. Sans resume avant deleteAt (24 heures), la tâche passe à failed avec insufficient_credits_expired. Le fichier est supprimé.

POST /v1/jobs/{id}/resume

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

Envois

  1. Découpez le fichier en parties de upload.partSize octets. La partie 1 commence à l'octet 0.
  2. Envoyez chaque partie par PUT à son URL dans upload.parts. Conservez l'en-tête ETag de chaque réponse, avec ses guillemets.
  3. Envoyez POST /v1/jobs/{id}/upload-complete avec {"etags": [...]} dans l'ordre des parties.

Chaque URL est signée pour une longueur exacte. Une partie doit faire partSize octets, et la dernière partie contient le reste. Le stockage répond 403 pour toute autre longueur et pour un corps en transfert fractionné (chunked). Envoyez Content-Length.

Si un envoi s'arrête, ne recommencez pas depuis le début :

  1. Appelez GET /v1/jobs/{id}/upload.
  2. Lisez done. Chaque élément contient partNumber, etag et size.
  3. Lisez missing. Il liste des numéros de partie.
  4. Envoyez chaque partie manquante à parts[partNumber - 1]. Ces URL sont valables 1 heure.
  5. Terminez avec tous les ETags dans l'ordre des parties. Utilisez le même fichier.

Terminez un envoi dans les 24 heures. Ensuite, le stockage supprime les parties d'un envoi non terminé.

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

Statut de la tâche

GET /v1/jobs/{id} donne le statut, la progression et le temps restant. Interrogez-le toutes les 15 secondes.

status Signification
uploading La tâche attend le fichier
queued La tâche attend un GPU. Une tâche peut repasser brièvement de converting à queued
converting progress va de 0 à 1
delayed Retenue de notre côté. Les crédits restent réservés
insufficient_credits Le prix dépasse le solde. Ajoutez shortBy crédits, puis appelez resume. Voir Crédits insuffisants
done Terminée. result contient le nom, la taille et le chemin du lien
failed error contient un code. Les crédits ont été restitués
cancelled Annulée par l'appelant

GET /v1/jobs/{id}

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

Résultats

GET /v1/jobs/{id}/result donne un lien de téléchargement pour une tâche done. Le lien est valable 15 minutes et uniquement pour GET. Appelez de nouveau la route pour obtenir un nouveau lien. Quand le résultat a expiré, la réponse est 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>"
Réponse200
{
  "url": "https://...",
  "filename": "...",
  "sizeBytes": 209715200,
  "expiresInS": 900
}

Annulation

POST /v1/jobs/{id}/cancel annule une tâche. Une tâche annulée avant le début de la conversion ne coûte rien. Ensuite, elle coûte le prix x progress, arrondi à l'unité supérieure, au minimum 1 crédit.

POST /v1/jobs/{id}/cancel

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

Restez informé de nos actualités !

Owl3D
© 2026 Owl3D. Tous droits réservés.