ModèlesTarificationEntreprise
500+ API de modèles IA, toutes en une seule API. Simplement avec CometAPI
API des modèles
Développeur
Démarrage rapideDocumentationTableau de bord API
Entreprise
À proposEntreprise
Ressources
Modèles d'IABlogJournal des modificationsSupport
Conditions d'utilisationPolitique de confidentialité
© 2026 CometAPI · All rights reserved
Home/Models/Doubao/Doubao-Seedance-2-0
D

Doubao-Seedance-2-0

Par Seconde:$0.063
Seedance 2.0 est le modèle de fondation vidéo multimodal de nouvelle génération de ByteDance, axé sur la génération de vidéos narratives cinématographiques à plusieurs plans. Contrairement aux démonstrations texte-vers-vidéo à plan unique, Seedance 2.0 met l’accent sur un contrôle basé sur des références (images, clips courts, audio), la cohérence des personnages et des styles d’un plan à l’autre, ainsi qu’une synchronisation audio/vidéo native — visant à rendre la vidéo générée par IA utile aux workflows professionnels de création et de prévisualisation.
Nouveau
Usage commercial
Playground
Aperçu
Fonctionnalités
Tarification
API
Versions

Spécifications techniques de Doubao Seedance 2.0

ÉlémentDétails
Famille de produitsFamille de génération vidéo ByteDance Seedance
Slug CometAPIdoubao-seedance-2-0
FournisseurByteDance / BytePlus ModelArk
Type de modèleModèle de génération vidéo
Modalités d’entréeTexte, image
Type de sortieVidéo MP4
Résolution de sortie480p, 720p, 1080p
Rapports d’aspect21:9, 16:9, 4:3, 1:1, 3:4, 9:16
Durée de sortie4–15 secondes
Style d’APIGénération vidéo asynchrone basée sur des tâches

Qu’est-ce que Doubao Seedance 2.0 ?

Doubao Seedance 2.0 est le modèle phare multimodal de génération vidéo de ByteDance (sorti en février 2026). Il utilise une architecture unifiée de génération audio‑vidéo conjointe qui permet un contrôle de niveau réalisateur en s’appuyant simultanément sur plusieurs images, clips vidéo et fichiers audio. Il excelle dans la production de vidéos cinématographiques au mouvement stable avec une synchronisation audio native — idéal pour les créateurs professionnels qui ont besoin d’une physique réaliste, de personnages cohérents et d’une composition de scènes complexe.

Principales fonctionnalités de Doubao Seedance 2.0 sur CometAPI

  • Génération multimodale unifiée : il accepte des entrées texte, image, audio et vidéo dans un seul flux de travail, afin que les utilisateurs puissent diriger une scène avec un matériel de référence plus riche qu’un générateur texte‑seul.
  • Contrôle de style réalisateur : le modèle est conçu pour suivre des prompts liés au jeu, à l’éclairage, aux ombres, aux mouvements de caméra, au rythme du mouvement et aux caractéristiques sonores.
  • Montage et extension vidéo : Seedance 2.0 ne se limite pas à une génération en premier jet ; il prend en charge la modification de clips, personnages, actions et trames spécifiques, ainsi que l’extension vers l’avant/vers l’arrière.
  • Synchronisation audiovisuelle solide : ByteDance met en avant une sortie stéréo à deux canaux et la synchronisation de la musique de fond, des sons d’ambiance et du comportement de la voix off pour des résultats plus immersifs.
  • Haut degré de contrôlabilité pour les scènes complexes : il met l’accent sur une meilleure gestion des interactions complexes, des scènes en mouvement et de la plausibilité physique par rapport à Seedance 1.5.
  • Sortie orientée production : l’API prend en charge des paramètres configurables (rapport d’aspect, durée, filigrane), ce qui rend le modèle pratique pour des workflows de contenu répétables.

Performances de référence

ByteDance indique que Seedance 2.0 utilise l’évaluation interne SeedVideoBench-2.0 et se classe en position de tête sur les dimensions des tâches texte‑vers‑vidéo, image‑vers‑vidéo et multimodales. Le modèle améliore la qualité de génération, la précision physique, le réalisme et la contrôlabilité par rapport à Seedance 1.5, en particulier dans les scènes d’interaction complexe et de mouvement.

Modes Seedance 2.0 API et Seedance 2.0 Fast API sur CometAPI

ModèleNom du modèle dans CometAPIIdéal pourDifférence principale
Seedance 2.0doubao-seedance-2-0Création vidéo multimodale de la plus haute qualitéPile de références la plus large et contrôlabilité la plus forte de la famille Seedance 2.0.
Seedance 2.0 fastdoubao-seedance-2-0-fastProduction plus rapide quand on peut sacrifier un peu de qualitéByteDance indique qu’il conserve les mêmes capacités que Seedance 2.0, mais génère plus vite.
Seedance 1.5 Prodoubao-seedance-1-5-proCréation audio‑vidéo d’une génération antérieureSeedance 1.5 Pro est positionné comme un modèle audio‑vidéo natif conjoint, tandis que Seedance 2.0 étend la pile de référence multimodale et d’édition.

Forces par rapport aux concurrents :

  • vs Kling 3.0 : Meilleur contrôle des références multimodales et audio natif.
  • vs Sora 2 : Précision de référence supérieure et capacité multi‑plans ; durée max légèrement inférieure.
  • vs Veo 3.1 : Plus fort en cohérence des personnages et respect des prompts pour des workflows riches en références ; Veo domine en étalonnage cinématographique brut et en clips plus longs.

Excelle dans les vidéos centrées sur l’humain et axées sur la performance.

Essayez le générateur vidéo IA Seedance 2.0 sur CometAPI

Étape 1 : Étape 1 : Inscrivez‑vous pour obtenir une clé API

Commencez directement dans le CometAPI Playground pour découvrir Doubao Seedance 2.0 sans configuration ni code. Connectez‑vous simplement à votre compte CometAPI, rendez‑vous sur la page du modèle doubao-seedance-2-0, téléversez vos images de référence, des clips vidéo courts ou des fichiers audio, ajoutez un prompt descriptif, et générez instantanément des vidéos d’aperçu. C’est la manière la plus rapide de comprendre comment Seedance 2.0 gère la cohérence du mouvement, l’apparence des personnages, les mouvements de caméra et la synchronisation audio native.

Étape 2 : Obtenez l’accès à l’API pour Seedance 2.0 sur CometAPI

Créez ou utilisez votre clé CometAPI existante pour activer l’accès complet à Doubao Seedance 2.0. Après vous être connecté, accédez à la section API Token de votre console, générez une nouvelle clé et copiez‑la. Rendez‑vous ensuite sur la page de détails du modèle Seedance 2.0 et la documentation de l’API sur CometAPI pour consulter les paramètres pris en charge et les intégrer à vos projets.

Étape 3 : Envoyez votre première requête avec l’API Seedance 2.0

Utilisez le point de terminaison CometAPI pour soumettre votre première requête de génération vidéo avec un prompt textuel clair et des fichiers de référence optionnels (images, vidéo ou audio). Le système traitera la tâche de manière asynchrone, renverra un ID de tâche et fournira une vidéo MP4 téléchargeable une fois terminé. Vous pourrez ensuite affiner vos prompts, ajuster les paramètres et passer à l’échelle pour des vidéos marketing, du contenu pour les réseaux sociaux, des pipelines vidéo automatisés ou des applications créatives propulsées par Seedance 2.0.

Ce flux de travail vous offre une expérimentation rapide dans le Playground et une transition fluide vers un usage en production via CometAPI.

Principales raisons de choisir Seedance 2.0 sur CometAPI

Pourquoi utiliser CometAPI pour Seedance 2.0

  • Accès direct via l’API ou le Playground
  • Contrôle facile des paramètres (durée, résolution, format)
  • Prend en charge les workflows texte‑vers‑vidéo et image‑vers‑vidéo
  • Gestion intégrée des tâches pour la génération vidéo asynchrone

API unifiée et conviviale pour les développeurs

CometAPI propose un point de terminaison propre et standardisé qui fonctionne de manière transparente avec des formats de type OpenAI familiers ou des points de terminaison dédiés aux tâches vidéo. Vous bénéficiez d’une création de tâches, d’un polling et de téléchargements MP4 simples, sans avoir à gérer l’authentification complexe ni les limitations régionales de Volcengine.

Tarification avantageuse

CometAPI propose généralement des tarifs à la seconde plus compétitifs que les fournisseurs directs, vous permettant de générer des vidéos de haute qualité à grande échelle pour le marketing, les réseaux sociaux ou des pipelines automatisés sans exploser votre budget.

Tests rapides avec le Playground

Expérimentez immédiatement dans le CometAPI Playground. Téléversez des images, des vidéos et des fichiers audio de référence, ajustez les prompts et prévisualisez les résultats en quelques minutes — idéal pour itérer sur le style, le mouvement et la synchronisation audio avant la mise en production.

En bref, si vous voulez la puissance créative de Seedance 2.0 — contrôle de référence de premier ordre, mouvement naturel et audio natif — sans les tracas d’un accès direct à ByteDance, CometAPI est actuellement l’une des meilleures plateformes pour l’utiliser.

FAQ

What kinds of inputs does Seedance 2.0 support for video generation?

Seedance 2.0 prend en charge des entrées multimodales, notamment des prompts textuels, jusqu’à 9 images, jusqu’à 3 courts clips vidéo et jusqu’à 3 fichiers audio, qui peuvent être librement combinés pour une génération riche et contrôlable.

Can Seedance 2.0 maintain character and style consistency across multiple video shots?

Oui — Seedance 2.0 est conçu pour une narration multi-plans cohérente, avec des personnages, un style visuel et une atmosphère constants d’une scène à l’autre, réduisant les problèmes courants de dérive des vidéos IA.

What outputs and quality levels can I expect from Seedance 2.0 videos?

Seedance 2.0 peut générer des vidéos de qualité cinématographique (jusqu’à une résolution 2K) avec audio natif, dialogues synchronisés et synthèse de mouvements naturels, généralement sous forme de clips de 5–60 secondes.

How does Seedance 2.0 handle audio and lip synchronization?

Le modèle génère l’audio et la vidéo conjointement, offrant une synchronisation audiovisuelle native avec une synchronisation labiale au niveau des phonèmes dans plus de 8 langues, pour une parole et des effets sonores naturels.

Is Seedance 2.0 suitable for professional creative projects like marketing or narrative shorts?

Oui — le contrôle multimodal, la continuité multi-plans et le rendu de haute fidélité de Seedance 2.0 le rendent adapté aux vidéos marketing, aux courts métrages narratifs, aux publicités et à d’autres applications professionnelles.

How do referencing assets (images, video clips) work in Seedance 2.0 prompts?

Les utilisateurs peuvent importer des ressources de référence, puis décrire en langage naturel comment chacune doit influencer le mouvement, les mouvements de caméra ou les éléments stylistiques, offrant un contrôle granulaire sur le contenu généré.

Does Seedance 2.0 allow editing and extension of existing videos?

Oui — le modèle prend en charge l’extension de vidéos et le montage ciblé, comme l’ajout de scènes, le remplacement de personnages ou la modification de segments spécifiques, tout en préservant les parties non modifiées.

What are known limitations or typical generation lengths with Seedance 2.0?

Les longueurs de sortie typiques vont de ~5 à ~60 secondes par vidéo, et la combinaison de nombreux éléments ou de paramètres en haute résolution peut augmenter le temps de génération.

Tarification pour Doubao-Seedance-2-0

Découvrez des tarifs compétitifs pour Doubao-Seedance-2-0, conçus pour s'adapter à différents budgets et besoins d'utilisation. Nos formules flexibles garantissent que vous ne payez que ce que vous utilisez, ce qui facilite l'adaptation à mesure que vos besoins évoluent. Découvrez comment Doubao-Seedance-2-0 peut améliorer vos projets tout en maîtrisant les coûts.

doubao-seedance Video Generation Pricing

Parameters

ParameterDescription
Duration (seconds)4–15 seconds, default 5 seconds
sizeRefer to documentation

*1080p is available for all models except doubao-seedance-2-0-fast

Pricing (Per Second)

Model480p720p1080p
doubao-seedance-2-0$0.063$0.1368$0.3366
doubao-seedance-2-0-fast$0.0504$0.108—
doubao-seedance-1-5-pro$0.024$0.052$0.118
doubao-seedance-1-0-pro$0.032$0.084$0.1992

💡 Billed per second. Total cost = price per second × video duration (seconds). Duration range: 4–15 seconds.

Exemple de code et API pour Doubao-Seedance-2-0

Accédez à des exemples de code complets et aux ressources API pour Doubao-Seedance-2-0 afin de simplifier votre processus d'intégration. Notre documentation détaillée fournit des instructions étape par étape pour vous aider à exploiter tout le potentiel de Doubao-Seedance-2-0 dans vos projets.
POST
/v1/videos
Python
JavaScript
Curl
import json
import os
import time

import requests

# Get your CometAPI key from https://www.cometapi.com/console/token, and paste it here
COMETAPI_KEY = os.environ.get("COMETAPI_KEY") or "<YOUR_COMETAPI_KEY>"
BASE_URL = "https://api.cometapi.com"
OUTPUT_DIR = "./output"
POLL_INTERVAL_SECONDS = 10
RETRY_DELAY_SECONDS = 5
MAX_CREATE_ATTEMPTS = 5
MAX_QUERY_ATTEMPTS = 3
TERMINAL_STATUSES = {"success", "completed", "failed", "error"}
SUCCESS_STATUSES = {"success", "completed"}

def is_progress_complete(progress):
    if isinstance(progress, int):
        return progress >= 100
    if isinstance(progress, float):
        return progress >= 100
    if isinstance(progress, str):
        try:
            return float(progress.rstrip("%")) >= 100
        except ValueError:
            return False
    return False

def is_transient_status(status_code):
    return status_code == 429 or 500 <= status_code < 600

def create_task(files):
    for attempt in range(1, MAX_CREATE_ATTEMPTS + 1):
        response = requests.post(
            f"{BASE_URL}/v1/videos",
            headers=headers,
            files=files,
            timeout=30,
        )
        if response.ok:
            return response
        if not is_transient_status(response.status_code) or attempt == MAX_CREATE_ATTEMPTS:
            response.raise_for_status()
        print(f"Create request returned {response.status_code}, retrying...")
        time.sleep(RETRY_DELAY_SECONDS)

    raise SystemExit("Failed to create task.")

def get_task(task_id):
    for attempt in range(1, MAX_QUERY_ATTEMPTS + 1):
        response = requests.get(
            f"{BASE_URL}/v1/videos/{task_id}",
            headers=headers,
            timeout=15,
        )
        if response.ok:
            return response
        if not is_transient_status(response.status_code) or attempt == MAX_QUERY_ATTEMPTS:
            response.raise_for_status()
        print(f"Status request returned {response.status_code}, retrying...")
        time.sleep(RETRY_DELAY_SECONDS)

    raise SystemExit("Failed to query task.")

if COMETAPI_KEY == "<YOUR_COMETAPI_KEY>":
    print("Set COMETAPI_KEY before running this example.")
    raise SystemExit(0)

headers = {"Authorization": f"Bearer {COMETAPI_KEY}"}

create_response = create_task(
    {
        "prompt": (None, "A slow cinematic camera push across a coastal landscape at sunrise."),
        "model": (None, "doubao-seedance-2-0"),
        "seconds": (None, "5"),
        "size": (None, "16:9"),
    }
)
create_response.raise_for_status()
create_result = create_response.json()

task_id = create_result.get("id") or create_result.get("task_id")
if not task_id:
    print(json.dumps(create_result, indent=2))
    raise SystemExit("No task id returned.")

print(f"Task created: {task_id}")
print(f"Initial status: {create_result.get('status')}")

while True:
    task_response = get_task(task_id)
    task_response.raise_for_status()
    task = task_response.json()
    status = str(task.get("status") or "unknown")
    normalized_status = status.lower()
    progress = task.get("progress")
    should_try_download = normalized_status in SUCCESS_STATUSES or (
        normalized_status == "unknown" and is_progress_complete(progress)
    )

    print(f"Status: {status}, progress: {progress}")

    if should_try_download or normalized_status in TERMINAL_STATUSES:
        if should_try_download:
            video_url = task.get("video_url") or ""
            content_url = f"{BASE_URL}/v1/videos/{task_id}/content"
            output_path = os.path.join(OUTPUT_DIR, f"{task_id}.mp4")

            os.makedirs(OUTPUT_DIR, exist_ok=True)
            with requests.get(
                content_url,
                headers=headers,
                timeout=120,
                stream=True,
            ) as video_response:
                video_response.raise_for_status()
                with open(output_path, "wb") as output_file:
                    for chunk in video_response.iter_content(chunk_size=8192):
                        if chunk:
                            output_file.write(chunk)

            print(f"Video URL: {video_url}")
            print(f"Content endpoint: {content_url}")
            print(f"Saved to {output_path}")
            print(f"File size: {os.path.getsize(output_path)} bytes")
        else:
            print(json.dumps(task, indent=2))
            raise SystemExit(1)
        break

    time.sleep(POLL_INTERVAL_SECONDS)

Python Code Example

import json
import os
import time

import requests

# Get your CometAPI key from https://www.cometapi.com/console/token, and paste it here
COMETAPI_KEY = os.environ.get("COMETAPI_KEY") or "<YOUR_COMETAPI_KEY>"
BASE_URL = "https://api.cometapi.com"
OUTPUT_DIR = "./output"
POLL_INTERVAL_SECONDS = 10
RETRY_DELAY_SECONDS = 5
MAX_CREATE_ATTEMPTS = 5
MAX_QUERY_ATTEMPTS = 3
TERMINAL_STATUSES = {"success", "completed", "failed", "error"}
SUCCESS_STATUSES = {"success", "completed"}


def is_progress_complete(progress):
    if isinstance(progress, int):
        return progress >= 100
    if isinstance(progress, float):
        return progress >= 100
    if isinstance(progress, str):
        try:
            return float(progress.rstrip("%")) >= 100
        except ValueError:
            return False
    return False


def is_transient_status(status_code):
    return status_code == 429 or 500 <= status_code < 600


def create_task(files):
    for attempt in range(1, MAX_CREATE_ATTEMPTS + 1):
        response = requests.post(
            f"{BASE_URL}/v1/videos",
            headers=headers,
            files=files,
            timeout=30,
        )
        if response.ok:
            return response
        if not is_transient_status(response.status_code) or attempt == MAX_CREATE_ATTEMPTS:
            response.raise_for_status()
        print(f"Create request returned {response.status_code}, retrying...")
        time.sleep(RETRY_DELAY_SECONDS)

    raise SystemExit("Failed to create task.")


def get_task(task_id):
    for attempt in range(1, MAX_QUERY_ATTEMPTS + 1):
        response = requests.get(
            f"{BASE_URL}/v1/videos/{task_id}",
            headers=headers,
            timeout=15,
        )
        if response.ok:
            return response
        if not is_transient_status(response.status_code) or attempt == MAX_QUERY_ATTEMPTS:
            response.raise_for_status()
        print(f"Status request returned {response.status_code}, retrying...")
        time.sleep(RETRY_DELAY_SECONDS)

    raise SystemExit("Failed to query task.")

if COMETAPI_KEY == "<YOUR_COMETAPI_KEY>":
    print("Set COMETAPI_KEY before running this example.")
    raise SystemExit(0)

headers = {"Authorization": f"Bearer {COMETAPI_KEY}"}

create_response = create_task(
    {
        "prompt": (None, "A slow cinematic camera push across a coastal landscape at sunrise."),
        "model": (None, "doubao-seedance-2-0"),
        "seconds": (None, "5"),
        "size": (None, "16:9"),
    }
)
create_response.raise_for_status()
create_result = create_response.json()

task_id = create_result.get("id") or create_result.get("task_id")
if not task_id:
    print(json.dumps(create_result, indent=2))
    raise SystemExit("No task id returned.")

print(f"Task created: {task_id}")
print(f"Initial status: {create_result.get('status')}")

while True:
    task_response = get_task(task_id)
    task_response.raise_for_status()
    task = task_response.json()
    status = str(task.get("status") or "unknown")
    normalized_status = status.lower()
    progress = task.get("progress")
    should_try_download = normalized_status in SUCCESS_STATUSES or (
        normalized_status == "unknown" and is_progress_complete(progress)
    )

    print(f"Status: {status}, progress: {progress}")

    if should_try_download or normalized_status in TERMINAL_STATUSES:
        if should_try_download:
            video_url = task.get("video_url") or ""
            content_url = f"{BASE_URL}/v1/videos/{task_id}/content"
            output_path = os.path.join(OUTPUT_DIR, f"{task_id}.mp4")

            os.makedirs(OUTPUT_DIR, exist_ok=True)
            with requests.get(
                content_url,
                headers=headers,
                timeout=120,
                stream=True,
            ) as video_response:
                video_response.raise_for_status()
                with open(output_path, "wb") as output_file:
                    for chunk in video_response.iter_content(chunk_size=8192):
                        if chunk:
                            output_file.write(chunk)

            print(f"Video URL: {video_url}")
            print(f"Content endpoint: {content_url}")
            print(f"Saved to {output_path}")
            print(f"File size: {os.path.getsize(output_path)} bytes")
        else:
            print(json.dumps(task, indent=2))
            raise SystemExit(1)
        break

    time.sleep(POLL_INTERVAL_SECONDS)

JavaScript Code Example

import fs from "fs";
import path from "path";

// Get your CometAPI key from https://www.cometapi.com/console/token, and paste it here
const api_key = process.env.COMETAPI_KEY || "<YOUR_COMETAPI_KEY>";
const base_url = "https://api.cometapi.com";
const output_dir = "./output";
const poll_interval_ms = 10_000;
const retry_delay_ms = 5_000;
const max_create_attempts = 5;
const max_query_attempts = 3;
const terminal_statuses = new Set(["success", "completed", "failed", "error"]);
const success_statuses = new Set(["success", "completed"]);

function is_progress_complete(progress) {
  if (typeof progress === "number") {
    return progress >= 100;
  }

  if (typeof progress === "string") {
    const numeric = Number(progress.replace(/%$/, ""));
    return Number.isFinite(numeric) && numeric >= 100;
  }

  return false;
}

function is_transient_status(status) {
  return status === 429 || status >= 500;
}

async function fetch_with_retry(url, options, attempts, label) {
  for (let attempt = 1; attempt <= attempts; attempt += 1) {
    const response = await fetch(url, options);
    if (response.ok) {
      return response;
    }

    if (!is_transient_status(response.status) || attempt === attempts) {
      return response;
    }

    console.log(`${label} returned ${response.status}, retrying...`);
    await new Promise((resolve) => setTimeout(resolve, retry_delay_ms));
  }

  throw new Error(`${label} failed`);
}

if (api_key === "<YOUR_COMETAPI_KEY>") {
  console.log("Set COMETAPI_KEY before running this example.");
  process.exit(0);
}

const headers = {
  Authorization: `Bearer ${api_key}`,
};

const form = new FormData();
form.set("prompt", "A slow cinematic camera push across a coastal landscape at sunrise.");
form.set("model", "doubao-seedance-2-0");
form.set("seconds", "5");
form.set("size", "16:9");

const create_response = await fetch_with_retry(`${base_url}/v1/videos`, {
  method: "POST",
  headers,
  body: form,
}, max_create_attempts, "Create request");

if (!create_response.ok) {
  console.log(await create_response.text());
  process.exit(1);
}

const create_result = await create_response.json();
const task_id = create_result.id || create_result.task_id;

if (!task_id) {
  console.log(JSON.stringify(create_result, null, 2));
  process.exit(1);
}

console.log(`Task created: ${task_id}`);
console.log(`Initial status: ${create_result.status}`);

while (true) {
  const task_response = await fetch_with_retry(`${base_url}/v1/videos/${task_id}`, {
    headers,
  }, max_query_attempts, "Status request");

  if (!task_response.ok) {
    console.log(await task_response.text());
    process.exit(1);
  }

  const task = await task_response.json();
  const status = String(task.status || "unknown");
  const normalized_status = status.toLowerCase();
  const progress = task.progress;
  const should_try_download = success_statuses.has(normalized_status) || (
    normalized_status === "unknown" && is_progress_complete(progress)
  );

  console.log(`Status: ${status}, progress: ${progress}`);

  if (should_try_download || terminal_statuses.has(normalized_status)) {
    if (should_try_download) {
      const video_url = task.video_url || "";
      const content_url = `${base_url}/v1/videos/${task_id}/content`;
      const output_path = path.join(output_dir, `${task_id}.mp4`);

      if (!fs.existsSync(output_dir)) {
        fs.mkdirSync(output_dir, { recursive: true });
      }

      const video_response = await fetch(content_url, { headers });
      if (!video_response.ok) {
        console.log(await video_response.text());
        process.exit(1);
      }

      const video_buffer = Buffer.from(await video_response.arrayBuffer());
      fs.writeFileSync(output_path, video_buffer);

      console.log(`Video URL: ${video_url}`);
      console.log(`Content endpoint: ${content_url}`);
      console.log(`Saved to ${output_path}`);
      console.log(`File size: ${fs.statSync(output_path).size} bytes`);
    } else {
      console.log(JSON.stringify(task, null, 2));
      process.exit(1);
    }
    break;
  }

  await new Promise((resolve) => setTimeout(resolve, poll_interval_ms));
}

Curl Code Example

#!/bin/bash

set -euo pipefail

# Get your CometAPI key from https://www.cometapi.com/console/token
# Export it as: export COMETAPI_KEY="your-key-here"

if [[ -z "${COMETAPI_KEY:-}" ]]; then
  echo "Set COMETAPI_KEY before running this example."
  exit 0
fi

BASE_URL="https://api.cometapi.com"
OUTPUT_DIR="./output"
POLL_INTERVAL_SECONDS=10
RETRY_DELAY_SECONDS=5
MAX_CREATE_ATTEMPTS=5
MAX_QUERY_ATTEMPTS=3

is_progress_complete() {
  local progress="$1"
  local normalized="${progress%%%}"

  if [[ -z "$normalized" ]]; then
    return 1
  fi

  [[ "$normalized" =~ ^[0-9]+([.][0-9]+)?$ ]] || return 1
  awk -v value="$normalized" 'BEGIN { exit !(value >= 100) }'
}

create_task() {
  local attempt=1
  while (( attempt <= MAX_CREATE_ATTEMPTS )); do
    local response
    local status_code
    response=$(curl -sS -w $'\n%{http_code}' "${BASE_URL}/v1/videos" \
      -H "Authorization: Bearer $COMETAPI_KEY" \
      -F 'prompt="A slow cinematic camera push across a coastal landscape at sunrise."' \
      -F 'model="doubao-seedance-2-0"' \
      -F 'seconds="5"' \
      -F 'size="16:9"')

    status_code=$(echo "$response" | tail -n 1)
    CREATE_RESPONSE=$(echo "$response" | sed '$d')

    if [[ "$status_code" =~ ^2 ]]; then
      return 0
    fi

    if [[ "$status_code" == "429" || "$status_code" =~ ^5 ]] && (( attempt < MAX_CREATE_ATTEMPTS )); then
      echo "Create request returned ${status_code}, retrying..."
      sleep "$RETRY_DELAY_SECONDS"
      (( attempt += 1 ))
      continue
    fi

    echo "$CREATE_RESPONSE"
    return 1
  done
}

get_task() {
  local task_id="$1"
  local attempt=1
  while (( attempt <= MAX_QUERY_ATTEMPTS )); do
    local response
    local status_code
    response=$(curl -sS -w $'\n%{http_code}' "${BASE_URL}/v1/videos/${task_id}" \
      -H "Authorization: Bearer $COMETAPI_KEY")

    status_code=$(echo "$response" | tail -n 1)
    TASK_RESPONSE=$(echo "$response" | sed '$d')

    if [[ "$status_code" =~ ^2 ]]; then
      return 0
    fi

    if [[ "$status_code" == "429" || "$status_code" =~ ^5 ]] && (( attempt < MAX_QUERY_ATTEMPTS )); then
      echo "Status request returned ${status_code}, retrying..."
      sleep "$RETRY_DELAY_SECONDS"
      (( attempt += 1 ))
      continue
    fi

    echo "$TASK_RESPONSE"
    return 1
  done
}

create_task

TASK_ID=$(echo "$CREATE_RESPONSE" | jq -r '.id // .task_id // empty')

if [[ -z "$TASK_ID" ]]; then
  echo "$CREATE_RESPONSE" | jq .
  echo "No task id returned."
  exit 1
fi

echo "Task created: $TASK_ID"
echo "Initial status: $(echo "$CREATE_RESPONSE" | jq -r '.status // empty')"

while true; do
  get_task "$TASK_ID"

  STATUS=$(echo "$TASK_RESPONSE" | jq -r '.status // empty')
  NORMALIZED_STATUS=$(echo "$STATUS" | tr '[:upper:]' '[:lower:]')
  PROGRESS=$(echo "$TASK_RESPONSE" | jq -r '.progress // empty')
  SHOULD_TRY_DOWNLOAD=0

  if [[ "$NORMALIZED_STATUS" == "success" || "$NORMALIZED_STATUS" == "completed" ]]; then
    SHOULD_TRY_DOWNLOAD=1
  elif [[ "$NORMALIZED_STATUS" == "unknown" ]] && is_progress_complete "$PROGRESS"; then
    SHOULD_TRY_DOWNLOAD=1
  fi

  echo "Status: ${STATUS}, progress: ${PROGRESS}"

  if [[ "$SHOULD_TRY_DOWNLOAD" == "1" || "$NORMALIZED_STATUS" == "failed" || "$NORMALIZED_STATUS" == "error" ]]; then
    if [[ "$SHOULD_TRY_DOWNLOAD" == "1" ]]; then
      VIDEO_URL=$(echo "$TASK_RESPONSE" | jq -r '.video_url // empty')
      CONTENT_URL="${BASE_URL}/v1/videos/${TASK_ID}/content"
      OUTPUT_PATH="${OUTPUT_DIR}/${TASK_ID}.mp4"

      mkdir -p "$OUTPUT_DIR"
      curl -fsS "$CONTENT_URL" \
        -H "Authorization: Bearer $COMETAPI_KEY" \
        -o "$OUTPUT_PATH"

      if [[ ! -s "$OUTPUT_PATH" ]]; then
        echo "Failed to download video"
        exit 1
      fi

      echo "Video URL: ${VIDEO_URL}"
      echo "Content endpoint: ${CONTENT_URL}"
      echo "Saved to ${OUTPUT_PATH}"
      echo "File size: $(wc -c < "$OUTPUT_PATH" | tr -d ' ') bytes"
    else
      echo "$TASK_RESPONSE" | jq .
      exit 1
    fi
    break
  fi

  sleep "$POLL_INTERVAL_SECONDS"
done

Versions de Doubao-Seedance-2-0

La raison pour laquelle Doubao-Seedance-2-0 dispose de plusieurs instantanés peut inclure des facteurs potentiels tels que des variations de sortie après des mises à jour nécessitant des instantanés plus anciens pour la cohérence, offrant aux développeurs une période de transition pour l'adaptation et la migration, et différents instantanés correspondant à des points de terminaison globaux ou régionaux pour optimiser l'expérience utilisateur. Pour les différences détaillées entre les versions, veuillez consulter la documentation officielle.
version
doubao-seedance-2-0-fast
doubao-seedance-2-0