Aller au contenu

Seedance

Seedance est la famille de génération vidéo de ByteDance, servie par des canaux Volcengine Ark. RouteAPI convertit votre requête en appel Ark /api/v3/contents/generations/tasks, si bien que chaque tâche suit le même parcours — soumission, interrogation, téléchargement — que les autres modèles vidéo : voir Créer une tâche et Obtenir une tâche. Cette page décrit ce que l’adaptateur Seedance lit, les limites par modèle, la lecture d’un enregistrement de tâche Seedance et le calcul du coût.

La génération vidéo est asynchrone : soumettez, conservez le task_id, interrogez toutes les 10 à 15 secondes, puis téléchargez quand le statut est SUCCESS. Un clip de 4 secondes en 480p prend généralement une à cinq minutes ; une résolution plus élevée ou une durée plus longue prend plus de temps.

ID de modèleModèle ArkRésolutionDuréeRemarques
seedance-2.5doubao-seedance-2-5-260628480p / 720p / 1080p4–30 sAperçu brouillon, modes référence/édition/extension, sortie mov
seedance-2.0doubao-seedance-2-0-260128480p / 720p / 1080p / 4k4–15 sMatériel de référence image, vidéo et audio
seedance-2.0-fastdoubao-seedance-2-0-fast-260128480p / 720p4–15 sVariante 2.0 plus rapide et moins chère
seedance-2.0-minidoubao-seedance-2-0-mini-260615480p / 720p4–15 sVariante 2.0 à bas coût

Envoyez l’ID renvoyé par GET /v1/models. Un canal qui sert ces modèles mappe cet ID sur le nom de modèle Ark correspondant de la deuxième colonne, ce qui explique que l’adaptateur accepte les deux conventions de nommage. Les modèles utilisables par votre compte et leurs prix sont définis dans la console RouteAPI.

Les colonnes résolution et durée sont les plages propres à chaque modèle chez ByteDance. RouteAPI ne les valide pas : la seule vérification de durée de notre côté est la règle commune selon laquelle un duration / seconds de premier niveau doit rester entre 0 et 3600 (voir Limites et erreurs). Tout le reste est appliqué par Ark — une requête de 30 secondes sur un modèle 2.0, une résolution non prise en charge ou un nombre excessif de clips de référence est soumise, puis rejetée par Ark et remontée comme fail_to_fetch_task avec le statut et le message d’Ark. RouteAPI ne complète pas non plus un resolution ou un duration absent : Ark applique sa propre valeur par défaut. L’estimation de coût utilise 1080p et 5 secondes dans ce cas, le montant réservé est donc une estimation, pas la valeur par défaut d’Ark.

Seedance 1.x (doubao-seedance-1-0-*, doubao-seedance-1-5-*) n’est plus servi. Une requête qui se mappe sur un nom 1.x est rejetée avec 400 et le code model_not_supported après le mapping du modèle, mais avant toute réservation ou envoi en amont.

Champ d’enveloppeCe que fait l’adaptateur Seedance
promptAjouté comme élément text final, sauf si metadata.content contient déjà un élément text ou si content est un draft_task 2.5. Requis dans chaque requête
images / imageUn élément image_url sans role par image. Ignoré quand metadata.content est présent
ratioEnvoyé comme ratio Ark
resolutionEnvoyé comme resolution Ark
durationEnvoyé comme duration Ark ; un seconds de premier niveau qui s’analyse en entier positif le remplace
generate_audioEnvoyé comme generate_audio ; un false explicite est transmis
metadataDécodé dans une structure typée ; ses valeurs priment sur les équivalents de premier niveau

size, input_reference et mode font partie de l’enveloppe commune mais l’adaptateur Seedance ne les lit pas : utilisez resolution / ratio, et images ou content.

Les types de metadata sont validés avant soumission : un type incorrect (content en objet, image_url en chaîne nue, duration: "abc") renvoie 400 et rien n’est débité. Le message commence par unmarshal metadata failed. Les valeurs numériques et booléennes de metadata acceptent aussi leur forme chaîne ("duration": "6", "watermark": "false") ; les champs scalaires de premier niveau doivent utiliser leur type JSON.

Ces champs sont lus au premier niveau du corps, la même forme qu’envoyée à d’autres fournisseurs fonctionne donc sans les envelopper dans metadata :

ChampTypeDescription
ratiostringRatio d’aspect : 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 ou adaptive
resolutionstring480p, 720p, 1080p ou 4k, selon le modèle
durationintegerDurée en secondes. 0 signifie « non défini » et n’est pas envoyé ; utilisez metadata pour transmettre un zéro explicite
generate_audiobooleanGénérer une bande-son ; false est transmis explicitement
secondsstringAncienne forme de la durée ; lorsqu’elle s’analyse en entier positif, elle remplace duration et metadata.duration. Une valeur non numérique est ignorée
ChampTypeDescription
contentarrayMatériel d’entrée ; remplace images. Voir metadata.content
ratio, resolution, duration, generate_audiocomme au premier niveauPriment sur la valeur de premier niveau. Un seconds positif reste prioritaire pour la durée finale
seedintegerGraine aléatoire ; 0 est transmis comme valeur explicite
framesintegerNombre d’images. Quand il est défini, il remplace la durée dans l’estimation de coût, et Ark l’utilise à la place de la durée
camera_fixedbooleanFixe la caméra
watermarkbooleanFiligrane côté fournisseur sur la sortie. ByteDance documente false par défaut
return_last_framebooleanRenvoie aussi la dernière image sous forme d’image
service_tierstringNiveau de service du fournisseur, par exemple default. Transmis tel quel
execution_expires_afterintegerExpiration de la tâche en secondes. ByteDance documente 3600–259200, 172800 par défaut ; Ark l’applique
priorityintegerPriorité de file côté fournisseur, 0–9, la plus haute s’exécute en premier. Ark n’ordonne que les tâches de votre propre compte
safety_identifierstringIdentifiant de votre utilisateur final, 64 caractères maximum. Transmis à Ark, qui applique la limite
draftbooleanAperçu brouillon Seedance 2.5 — voir Aperçu de brouillon
output_formatstringConteneur de sortie, transmis tel quel. Seedance 2.5 accepte mp4 (par défaut) ou mov
omni_reference_task_typestringMode de référence Seedance 2.5, transmis tel quel : auto, reference, edit ou extend

callback_url n’est pas transmis et aucun callback n’est envoyé — interrogez le résultat. tools est également supprimé ; la recherche web en amont n’est pas disponible via cette API. Les clés non reconnues, y compris celles-ci, ne provoquent pas d’erreur ; elles sont ignorées. metadata.model n’est pas lu : le model du corps est toujours le nom de modèle amont du canal.

content est un tableau ordonné d’éléments d’entrée. Chaque élément a un type, le champ de charge utile correspondant et un role facultatif :

typeCharge utileValeurs de role
texttext—
image_urlimage_url.urlfirst_frame, last_frame, reference_image
video_urlvideo_url.urlreference_video
audio_urlaudio_url.urlreference_audio
draft_taskdraft_task.id—

RouteAPI valide la forme de l’élément (un type de charge utile erroné donne un 400) mais pas le nom du role ; un role inconnu est transmis et Ark décide de le rejeter ou non. Les URL peuvent être des liens http(s) publics, des URI data: pour les images et l’audio, ou des références asset://<asset_id> — voir Assets pour téléverser du matériel et pour les images de personnes réelles, qui doivent provenir d’un groupe d’assets vérifié.

Règles issues de la conversion :

  • Si content est présent, il est utilisé tel quel ; les images de premier niveau sont ignorées et non fusionnées. Un tableau content vide compte comme absent, les images de premier niveau s’appliquent donc toujours.
  • Si content n’a pas d’élément text, le prompt de premier niveau est ajouté comme élément texte final. La seule exception est une requête 2.5 dont le content est un draft_task : aucun prompt n’est ajouté, mais prompt doit tout de même être présent dans le corps.
  • Référencez le matériel par son ordinal dans le prompt (« image 1 », « video 1 »), compté par type dans l’ordre de content.
  • Le premier cadre, le premier/dernier cadre et le matériel multi-référence sont trois modes différents. Ne les mélangez pas sans avoir vérifié que le modèle accepte la combinaison.

Les limites de référence ci-dessous sont celles d’Ark, pas des vérifications de RouteAPI : une requête au-delà des limites est soumise puis rejetée en amont.

ÉlémentSeedance 2.5Série 2.0
Images de réf.1–301–9
Vidéos de réf.Jusqu’à 10 clips, ≤30 s au totalJusqu’à 3 clips, ≤15 s au total
Audio de réf.Jusqu’à 10 clips, ≤30 s au totalJusqu’à 3 clips, ≤15 s au total, et doit accompagner une image ou une vidéo
Image uniqueMoins de 30 Mo, 300–6000 px par côtéIdentique
Vidéo uniquemp4 / mov, moins de 200 MoIdentique
Audio uniquewav / mp3, moins de 15 MoIdentique

Seedance 2.x rejette les images et vidéos de référence contenant le visage d’une personne réelle. Pour utiliser la ressemblance d’une personne réelle, effectuez d’abord la vérification d’identité, puis référencez le matériel vérifié avec asset:// — Assets couvre la session de vérification, le groupe vérifié et les règles de requête.

Fenêtre de terminal
curl https://api.routeapi.ai/v1/video/generations \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.0-fast",
"prompt": "A paper boat drifting down a rain-soaked street, cinematic lighting",
"ratio": "16:9",
"resolution": "720p",
"duration": 5,
"generate_audio": false
}'

Une image unique dans images devient un élément image sans role, que Seedance traite comme la première image :

Fenêtre de terminal
curl https://api.routeapi.ai/v1/video/generations \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.0",
"prompt": "The camera slowly pushes in as the person looks up and smiles",
"images": ["https://cdn.example.com/first.jpg"],
"ratio": "adaptive",
"resolution": "720p",
"duration": 5
}'

Pour contrôler explicitement la première et la dernière image, utilisez content et placez le prompt à l’intérieur :

Fenêtre de terminal
curl https://api.routeapi.ai/v1/video/generations \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.0",
"prompt": "The bud slowly opens into a full bloom",
"metadata": {
"content": [
{ "type": "text", "text": "The bud slowly opens into a full bloom" },
{ "type": "image_url", "image_url": { "url": "https://cdn.example.com/bud.jpg" }, "role": "first_frame" },
{ "type": "image_url", "image_url": { "url": "https://cdn.example.com/flower.jpg" }, "role": "last_frame" }
],
"ratio": "adaptive",
"resolution": "720p",
"duration": 5
}
}'

Les images, vidéos et audios de référence se mélangent dans un seul tableau content avec les roles reference_*. Numérotez le matériel par type, dans l’ordre de content, et référencez-le ainsi dans le prompt :

Fenêtre de terminal
curl https://api.routeapi.ai/v1/video/generations \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.0",
"prompt": "The person in image 1 dances following the moves in video 1, with audio 1 as background music",
"metadata": {
"content": [
{ "type": "text", "text": "The person in image 1 dances following the moves in video 1, with audio 1 as background music" },
{ "type": "image_url", "image_url": { "url": "https://cdn.example.com/person.jpg" }, "role": "reference_image" },
{ "type": "video_url", "video_url": { "url": "https://cdn.example.com/dance.mp4" }, "role": "reference_video" },
{ "type": "audio_url", "audio_url": { "url": "https://cdn.example.com/bgm.mp3" }, "role": "reference_audio" }
],
"ratio": "16:9",
"resolution": "720p",
"duration": 10
}
}'

Une requête qui inclut une entrée vidéo est facturée au tarif d’entrée vidéo du modèle — voir Facturation. Le nombre, la durée et le format des références sont appliqués par Ark ; voir le tableau des limites sous metadata.content.

Seedance 2.5 ajoute un sélecteur de mode et un choix de conteneur. Les deux sont transmis sans modification pour tous les modèles Seedance, et Ark décide s’il les accepte :

Fenêtre de terminal
curl https://api.routeapi.ai/v1/video/generations \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.5",
"prompt": "Continue the scene as the camera pulls back over the harbour",
"metadata": {
"omni_reference_task_type": "extend",
"output_format": "mov",
"content": [
{ "type": "text", "text": "Continue the scene as the camera pulls back over the harbour" },
{ "type": "video_url", "video_url": { "url": "https://cdn.example.com/scene.mp4" }, "role": "reference_video" }
],
"ratio": "16:9",
"duration": 8
}
}'

omni_reference_task_type prend auto (par défaut), reference, edit ou extend. La combinaison d’entrées attendue par chaque mode relève du contrat de ByteDance ; RouteAPI ne fait que transmettre la valeur.

Un brouillon est un aperçu peu coûteux. Générer la vidéo finale à partir de lui est une seconde tâche, facturée séparément.

  1. Soumettez avec "metadata": { "draft": true, ... } et attendez SUCCESS.
  2. Lisez l’ID de tâche amont dans l’enregistrement de tâche : GET /v1/video/generations/{task_id} → data.data.id.
  3. Soumettez une nouvelle tâche dont le content est un seul draft_task.

Étape 1 :

Fenêtre de terminal
curl https://api.routeapi.ai/v1/video/generations \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.5",
"prompt": "An astronaut walks slowly on the moon",
"metadata": { "draft": true, "duration": 5, "ratio": "16:9" }
}'

Étape 2, une fois la tâche brouillon passée à SUCCESS. data.data.id est l’ID de tâche Ark et non le data.task_id externe :

Fenêtre de terminal
curl -s https://api.routeapi.ai/v1/video/generations/task_G2RdWGt4t1nck5fYqTjwREKJo8Ze4RAV \
-H "Authorization: Bearer $ROUTEAPI_KEY" | jq -r .data.data.id

Étape 3 :

Fenêtre de terminal
curl https://api.routeapi.ai/v1/video/generations \
-H "Authorization: Bearer $ROUTEAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.5",
"prompt": "x",
"metadata": {
"content": [ { "type": "draft_task", "draft_task": { "id": "cgt-xxxxxxxx" } } ],
"resolution": "1080p",
"duration": 5
}
}'

prompt reste obligatoire ; il n’est pas envoyé comme texte dans cette forme, n’importe quel texte de remplissage non vide convient donc. Une continuation de type draft_task sans duration explicite est réservée comme si elle devait durer le plafond automatique du modèle (30 secondes sur 2.5, 15 secondes sur 2.0) puis réglée sur l’usage réel.

Les ID de brouillon appartiennent à Ark. ByteDance documente une durée de vie de 7 jours ; RouteAPI ne la vérifie pas, un ID expiré échoue donc en amont.

Fenêtre de terminal
curl https://api.routeapi.ai/v1/video/generations/task_G2RdWGt4t1nck5fYqTjwREKJo8Ze4RAV \
-H "Authorization: Bearer $ROUTEAPI_KEY"
{
"code": "success",
"message": "",
"data": {
"id": 4512,
"created_at": 1792048450,
"updated_at": 1792048569,
"task_id": "task_G2RdWGt4t1nck5fYqTjwREKJo8Ze4RAV",
"platform": "54",
"user_id": 1024,
"group": "default",
"channel_id": 18,
"quota": 108900,
"action": "generate",
"status": "SUCCESS",
"progress": "100%",
"fail_reason": "",
"result_url": "https://ark-content.example/xxxx.mp4",
"submit_time": 1792048458,
"start_time": 1792048461,
"finish_time": 1792048569,
"properties": {
"input": "{\"model\":\"doubao-seedance-2-0-fast-260128\",\"content\":[{\"type\":\"text\",\"text\":\"An orange cat stretching on a windowsill at sunrise\"}],\"generate_audio\":false,\"resolution\":\"720p\",\"ratio\":\"16:9\",\"duration\":5}",
"origin_model_name": "seedance-2.0-fast",
"upstream_model_name": "doubao-seedance-2-0-fast-260128"
},
"data": {
"id": "cgt-20261023100444-9kz46",
"model": "doubao-seedance-2-0-fast-260128",
"status": "succeeded",
"content": { "video_url": "https://ark-content.example/xxxx.mp4" },
"seed": 8202,
"resolution": "720p",
"duration": 5,
"ratio": "16:9",
"framespersecond": 24,
"usage": { "completion_tokens": 108900, "total_tokens": 108900 },
"created_at": 1792048458,
"updated_at": 1792048569
}
}
}

Les champs externes sont ceux de RouteAPI, et Obtenir une tâche les décrit tous. Pour Seedance, lisez data.status, data.progress, data.result_url, data.fail_reason et data.quota, qui contient le montant facturé jusqu’ici — après une tâche réussie, c’est le montant réglé. data.properties.input est un instantané du JSON exact que RouteAPI a envoyé à Ark (les URL de média de plus de 512 octets sont remplacées par [omitted, N bytes]), le moyen le plus rapide de confirmer qu’une requête est bien partie à la résolution voulue. data.platform est le type de canal : 54 pour un canal vidéo Doubao, 45 pour un canal Volcengine.

data.data est le corps de tâche propre à Ark, stocké tel que renvoyé, et peut être incomplet avant la fin de la tâche. Si l’amont du canal répond via une enveloppe de passerelle ({"code": 200, "data": {...}}), les champs ci-dessous se trouvent un niveau plus bas, sous data.data.data — jugez l’achèvement par data.status, pas par la présence d’un champ. Les champs à lire :

ChampSignification
data.data.idID de tâche Ark, différent du data.task_id externe. Sert à la génération finale depuis un brouillon 2.5
data.data.content.video_urlURL vidéo renvoyée par Ark ; la même valeur que le data.result_url externe
data.data.content.last_frame_urlImage de la dernière frame. Présente seulement si return_last_frame était activé. RouteAPI stocke cette charge utile telle quelle et n’en analyse que content.video_url
data.data.duration / resolution / ratio / framespersecond / seedParamètres réels de génération
data.data.usage.completion_tokens / total_tokensTokens mesurés par Ark ; total_tokens est la quantité utilisée pour le règlement
data.data.errorCode et message d’erreur d’Ark en cas d’échec

Les statuts d’Ark se mappent ainsi sur l’enregistrement de tâche ; un statut non reconnu par RouteAPI est traité comme toujours en cours :

status ArkStatut de l’enregistrementProgression
pending, queuedQUEUED10%
processing, runningIN_PROGRESS50%
succeededSUCCESS100%
failed, expired, cancelledFAILURE100%
autreIN_PROGRESS30%

Si Ark signale succeeded avant d’avoir une video_url, RouteAPI maintient la tâche en IN_PROGRESS et interroge à nouveau au lieu de régler une tâche sans résultat. En FAILURE, fail_reason est le message d’erreur d’Ark, avec task failed en repli ; une tâche expired ou cancelled sans objet d’erreur indique task expired ou task cancelled. Si le délai d’expiration propre à RouteAPI (24 heures par défaut) se déclenche d’abord, le statut est aussi FAILURE avec un message de la plateforme, et la réservation est remboursée dans les deux cas.

data.result_url est l’URL propre à Ark, et Ark la fait expirer selon son propre calendrier (environ 24 heures selon la documentation ByteDance) — téléchargez-la rapidement. Le point de terminaison de contenu de RouteAPI récupère l’URL enregistrée au moment de l’appel : il vous évite de suivre des liens expirants, mais ne peut pas ressusciter un lien déjà expiré :

Fenêtre de terminal
curl -L -o out.mp4 \
https://api.routeapi.ai/v1/videos/task_G2RdWGt4t1nck5fYqTjwREKJo8Ze4RAV/content \
-H "Authorization: Bearer $ROUTEAPI_KEY"

L’endpoint de contenu ne sert que les tâches terminées appartenant à l’appelant : une tâche inachevée donne un 400 nommant son statut actuel, un task_id inconnu ou étranger donne un 404, et un échec de récupération chez Ark donne un 502. Ses erreurs utilisent la forme {"error": {"message": "...", "type": "..."}} sans champ code. Si return_last_frame était activé, data.data.content.last_frame_url expire aussi selon le calendrier d’Ark — téléchargez-la en même temps.

Les modèles Seedance sont facturés au token, pas par requête ni par seconde. Le prix de la console est indiqué par million de tokens de sortie pour un palier de résolution ; une requête comportant une entrée vidéo est facturée au tarif d’entrée vidéo du modèle.

À la soumission, RouteAPI estime les tokens de sortie à partir de la résolution et du nombre d’images demandés :

frames = 24 × duration + 1 (frames replaces duration when metadata.frames is set)
tokens = pixels × frames / 1024
pixels = 480p: 864×496, 720p: 1280×720, 1080p: 1920×1080, 4k: 3840×2160

La durée vaut 5 secondes par défaut si elle est omise, et le plafond automatique du modèle (30 secondes sur 2.5, 15 secondes sur 2.0) lorsque content est un draft_task sans durée explicite. Une résolution omise ou non reconnue est estimée à 1080p. La durée automatique de ByteDance (-1) est rejetée au premier niveau par le contrôle 0–3600 ; envoyée en chaîne "-1" dans metadata, elle est transmise et l’estimation utilise le même plafond automatique. L’estimation est multipliée par le ratio du modèle, le ratio du groupe et le multiplicateur d’entrée vidéo, et ce montant est réservé. Pour un modèle facturé au ratio plutôt qu’à prix fixe, l’estimation est comparée au pré-débit normal et le plus grand montant est réservé. Le règlement au token à l’achèvement ne s’exécute que si le modèle a un ratio configuré ; sans ratio, le montant réservé fait foi (et si le modèle n’a ni ratio ni prix fixe, les requêtes sont refusées sauf si les modèles sans ratio sont autorisés pour votre compte).

RequêteRéservé à la soumissionEn cas de succès
duration fournitokens estimés × prixusage.total_tokens d’Ark × prix, différence débitée ou rendue
duration omisestimation à 5 smême règlement
metadata.frames définiestimation sur le nombre d’imagesmême règlement
draft_task sans durationestimation à 30 s / 15 smême règlement
Prix fixe par tâche configuréle prix fixeinchangé ; pas de règlement au token
SUCCESS sans usage—la réservation est conservée
FAILURE, expired, cancelled—réservation remboursée
400rien de réservérien de facturé

Le prix au token dépend du palier de résolution, de la présence d’une entrée vidéo et — sur les modèles dont la table de prix définit cette dimension — de la génération audio. Lorsqu’une table de prix de modèle est utilisée et que le multiplicateur obtenu n’est pas 1.0, l’en-tête X-New-Api-Other-Ratios de la réponse de soumission le porte comme entrée video_input. La table de repli intégrée donne au modèle 2.0 des paliers base (480p / 720p), 1080p et 4k et un tarif d’entrée vidéo pour chacun ; la variante fast n’a qu’un palier base et un ratio d’entrée vidéo de 22/37. seedance-2.5 et seedance-2.0-mini n’ont pas de table de prix intégrée : leurs paliers viennent de la configuration de la console. Un canal peut aussi remplacer les ratios par une table VideoPrice indexée sur l’ID de modèle que vous demandez. Les prix et paliers affichés dans la console font foi.

Exemple chiffré (prix hypothétiques ; utilisez la console pour les prix réels). Supposons seedance-2.0-fast à 2 $ par million de tokens de sortie en 720p et un ratio de groupe de 1 :

  1. Soumission en 720p, duration: 5. Estimation : 1280 × 720 = 921 600 pixels, 24 × 5 + 1 = 121 images, 921 600 × 121 / 1024 = 108 900 tokens, réservé à 0,2178 $.
  2. Ark renvoie usage.total_tokens: 105000, le montant réglé est donc 0,21 $ et 0,0078 $ sont rendus.
  3. Si la même requête incluait un élément reference_video, la table intégrée de la variante fast appliquerait un multiplicateur d’entrée vidéo de 22/37 ≈ 0,5946 à l’estimation comme au règlement : réservation ≈ 0,1295 $, règlement ≈ 0,1249 $.

Une requête dont le solde ou le quota de la clé ne couvre pas la réservation est rejetée avant tout envoi en amont : 403 insufficient_user_quota pour le portefeuille, 403 pre_consume_token_quota_failed pour le quota de la clé.

StatutCodeSignification
400invalid_requestprompt absent ou vide, JSON malformé, ou champ metadata au mauvais type
400invalid_secondsduration / seconds de premier niveau, ou metadata.duration numérique, négatif ou supérieur à 3600
400model_not_supportedLa requête se mappe sur un modèle Seedance 1.x, qui n’est plus servi
400task_not_existLe task_id est inconnu ou appartient à un autre compte
403insufficient_user_quota, pre_consume_token_quota_failedLe solde du portefeuille ou le quota de la clé ne couvre pas la réservation
429—Capacité amont épuisée ; le message devient Upstream load is saturated, please try again later
500build_request_failed, do_request_failed, invalid_responseConversion échouée, amont injoignable, ou Ark n’a renvoyé aucun ID de tâche
500get_channel_failedLa sélection du canal a échoué côté relais (par exemple, l’enregistrement du canal a disparu en cours de requête)
503get_channel_failedLe canal a rencontré une panne d’identifiants ou de facturation en amont ; les détails sont masqués
statut amontfail_to_fetch_taskArk a rejeté la soumission ; le statut HTTP et le message sont ceux d’Ark

Messages 400 courants, exactement tels que renvoyés :

messageCause
prompt is requiredprompt absent, vide ou composé d’espaces seulement
seconds must be between 1 and 3600duration / seconds de premier niveau, ou metadata.duration numérique, négatif ou trop grand
unmarshal metadata failed: ...Un champ metadata a le mauvais type ; la suite du message le nomme
model <id> is not supported by this channelLe nom de modèle d’origine ou amont correspond à un Seedance 1.x retiré
task_not_existL’ID de tâche est inconnu, ou appartient à un autre compte

Les échecs après soumission (modération, expiration côté fournisseur, annulation) n’apparaissent pas comme erreurs HTTP. Ils remontent en FAILURE avec un fail_reason sur l’enregistrement de tâche, et le montant réservé est remboursé. expired et cancelled sont signalés de la même manière.

  • Les endpoints sont différents. RouteAPI n’expose pas /api/v3/contents/generations/tasks, donc pointer le SDK Volcengine vers notre URL de base ne fonctionne pas.
  • Les paramètres propres à Ark vont dans metadata ; les champs communs (prompt, images, ratio, resolution, duration, generate_audio) peuvent aussi être envoyés au premier niveau et sont mappés pour vous.
  • Le task_id renvoyé est celui de RouteAPI, pas celui d’Ark. L’ID d’Ark est data.data.id sur l’enregistrement de tâche.
  • Le modèle envoyé est un ID de catalogue ; le canal le mappe sur le nom de modèle Ark, vous n’adressez donc jamais directement les ID d’endpoint Ark (ep-...).
  • La liste des tâches, l’annulation, les callbacks et la recherche web ne sont pas pris en charge ; callback_url et tools sont supprimés.
  • La facturation se fait au token selon la table de prix de la console, pas selon la facturation propre à Ark.

Nécessite bash, curl et jq.

#!/usr/bin/env bash
set -euo pipefail
: "${ROUTEAPI_KEY:?set ROUTEAPI_KEY first}"
BASE="${ROUTEAPI_BASE:-https://api.routeapi.ai}"
AUTH="Authorization: Bearer $ROUTEAPI_KEY"
TASK_ID=$(curl -sS -X POST "$BASE/v1/video/generations" \
-H "$AUTH" -H "Content-Type: application/json" \
-d '{"model":"seedance-2.0-fast","prompt":"An orange cat stretching on a windowsill at sunrise","duration":5,"resolution":"720p","ratio":"16:9","generate_audio":false}' \
| jq -er .task_id)
echo "task: $TASK_ID"
for _ in $(seq 1 60); do
RESP=$(curl -sS "$BASE/v1/video/generations/$TASK_ID" -H "$AUTH")
STATUS=$(printf '%s' "$RESP" | jq -r .data.status)
echo "status: $STATUS $(printf '%s' "$RESP" | jq -r .data.progress)"
case "$STATUS" in
SUCCESS)
curl -sSL -o "$TASK_ID.mp4" "$BASE/v1/videos/$TASK_ID/content" -H "$AUTH"
echo "saved: $TASK_ID.mp4"
exit 0
;;
FAILURE)
echo "failed: $(printf '%s' "$RESP" | jq -r .data.fail_reason)"
exit 1
;;
esac
sleep 15
done
echo "timed out waiting for the task"
exit 1

La boucle attend 15 minutes ; augmentez le compteur pour les tâches longues ou en haute résolution.