Unlock exclusive introductory pricing for the newly launched Gemini 3.5 Flash.
D

Doubao-Seedance-2-0

Par Seconde:$0.056
Publié:Apr 19, 2026

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 à plans multiples. À l’inverse des 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 du style d’un plan à l’autre, ainsi qu’une synchronisation audio/vidéo native — afin de rendre la vidéo IA utile aux flux de travail professionnels de création et de prévisualisation.

Nouveau
Populaire
Usage commercial

Playground pour Doubao-Seedance-2-0

Explorez le Playground de Doubao-Seedance-2-0 — un environnement interactif pour tester les modèles et exécuter des requêtes en temps réel. Essayez des invites, ajustez les paramètres et itérez instantanément pour accélérer le développement et valider les cas d'utilisation.

Technical specifications of Doubao Seedance 2.0

ItemDetails
Product familyByteDance Seedance video generation family
CometAPI slugdoubao-seedance-2-0
ProviderByteDance / BytePlus ModelArk
Model typeVideo generation model
Input modalitiesText, image
Output typeMP4 video
Output resolution480p, 720p, 1080p
Aspect ratios21:9, 16:9, 4:3, 1:1, 3:4, 9:16
Output duration4–15 seconds
API styleAsynchronous task-based video generation

What is Doubao Seedance 2.0?

Doubao Seedance 2.0 is ByteDance’s flagship multimodal video generation model (released February 2026). It uses a unified audio-video joint generation architecture that allows precise director-level control by referencing multiple images, video clips, and audio files simultaneously. It excels at producing cinematic, motion-stable videos with native audio synchronization — ideal for professional creators needing realistic physics, consistent characters, and complex scene composition.

Main features of Doubao Seedance 2.0 on CometAPI

  • Unified multimodal generation: It accepts text, image, audio, and video inputs in one workflow, so users can direct a scene with richer reference material than a text-only generator.
  • Director-style control: The model is built to follow prompts for performance, lighting, shadow, camera movement, motion rhythm, and sound characteristics.
  • Video editing and extension: Seedance 2.0 is not limited to first-pass generation; it supports editing specific clips, characters, actions, and storylines, plus forward/backward extension.
  • Strong audiovisual sync: ByteDance highlights dual-channel stereo output and synchronized background music, ambient sound, and voiceover behavior for more immersive results.
  • High controllability for complex scenes: It emphasize improved handling of complex interactions, motion scenes, and physical plausibility compared with Seedance 1.5.
  • Production-oriented output: API supports configurable ratio, duration, and watermark settings, which makes the model practical for repeatable content workflows.

Benchmark performance

ByteDance says Seedance 2.0 uses the internal SeedVideoBench-2.0 evaluation and places in the leading position across text-to-video, image-to-video, and multimodal task dimensions. The model improves generation quality, physical accuracy, realism, and controllability versus Seedance 1.5, especially in complex interaction and motion scenes.

Seedance 2.0 API and Seedance 2.0 Fast API Modes on CometAPI

ModelModel Name in CometAPIBest forMain difference
Seedance 2.0doubao-seedance-2-0Highest-quality multimodal video creationBroadest reference stack and strongest controllability in the Seedance 2.0 family.
Seedance 2.0 fastdoubao-seedance-2-0-fastFaster production when quality can be traded a bitByteDance says it keeps the same model capabilities as Seedance 2.0, but generates faster.
Seedance 1.5 Prodoubao-seedance-1-5-proEarlier-generation audio-video creationSeedance 1.5 Pro is positioned as a native joint audio-video model, while Seedance 2.0 expands the multimodal reference and editing stack.

Strengths vs Competitors:

  • vs Kling 3.0: Better multimodal reference control and native audio.
  • vs Sora 2: Superior reference precision and multi-shot capability; slightly lower max duration.
  • vs Veo 3.1: Stronger in character consistency and prompt adherence for reference-heavy workflows; Veo leads in raw cinematic grading and longer clips.

Excels in human-centric and performance-driven videos.

Try Seedance 2.0 AI Video Generator on CometAPI

Step 1: Step 1: Sign Up for API Key

Start directly in the CometAPI Playground to experience Doubao Seedance 2.0 without any setup or coding. Simply log into your CometAPI account, go to the model page for doubao-seedance-2-0, upload your reference images, short video clips, or audio files, add a descriptive prompt, and generate preview videos instantly. This is the fastest way to understand how Seedance 2.0 handles motion consistency, character appearance, camera movements, and native audio synchronization.

Step 2: Get API Access for Seedance 2.0 on CometAPI

Create or use your existing CometAPI key to enable full access to Doubao Seedance 2.0. After logging in, navigate to the API Token section in your console, generate a new key, and copy it. Then visit the Seedance 2.0 model detail page and API doc on CometAPI to review the supported parameters integrating into your projects.

Step 3: Send Your First Request with Seedance 2.0 API

Use the CometAPI endpoint to submit your first video generation request with a clear text prompt and optional reference files (images, video, or audio). The system will process the task asynchronously, return a task ID, and provide a downloadable MP4 video once completed. You can then refine your prompts, adjust settings, and scale up for marketing videos, social media content, automated video pipelines, or creative applications powered by Seedance 2.0.

This workflow gives you quick experimentation in the playground and smooth transition into production use via the CometAPI.

Top Reasons to Choose Seedance 2.0 on CometAPI

Why Use CometAPI for Seedance 2.0

  • Direct access via API or Playground
  • Easy parameter control (duration, resolution, format)
  • Supports both text-to-video and image-to-video workflows
  • Built-in job handling for asynchronous video generation

Unified & Developer-Friendly API

CometAPI offers a clean, standardized endpoint that works seamlessly with familiar OpenAI-style formats or dedicated video task endpoints. You get straightforward task creation, polling, and MP4 downloads without dealing with Volcengine’s complex authentication or regional limitations.

Cost-Effective Pricing

CometAPI typically delivers more competitive per-second rates compared to direct providers, allowing you to generate high-quality videos at scale for marketing, social media, or automated pipelines without breaking your budget.

Fast Testing with Playground

Experiment immediately in the CometAPI Playground. Upload reference images, videos, and audio files, tweak prompts, and preview results in minutes — perfect for iterating on style, motion, and audio sync before going into production.

In short, if you want the creative power of Seedance 2.0 — best-in-class reference control, natural motion, and native audio — without the hassle of direct ByteDance access, CometAPI is currently one of the best platforms to use it.

FAQ

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.

Model480p720p1080p4k
doubao-seedance-2-0$0.056$0.1216$0.2992$0.624
doubao-seedance-2-0-fast$0.0448$0.096
doubao-seedance-2-0-mini$0.032$0.064
doubao-seedance-1-5-pro$0.0192$0.0416$0.0928
doubao-seedance-1-0-pro$0.0192$0.0416$0.0976
doubao-seedance-1-0-pro-fast$0.008$0.016$0.0384

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.

#!/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 $'
%{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 $'
%{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

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

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));
}

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
doubao-seedance-2-0-fast