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

Doubao-Seedance-2-0

Mỗi Giây:$0.056
Ngày phát hành:Apr 19, 2026

Seedance 2.0 là mô hình nền tảng video đa phương thức thế hệ mới của ByteDance, tập trung vào việc tạo sinh video mang tính điện ảnh, theo mạch truyện nhiều cảnh. Khác với các bản demo chuyển văn bản thành video một cảnh, Seedance 2.0 nhấn mạnh điều khiển dựa trên tham chiếu (hình ảnh, clip ngắn, âm thanh), duy trì nhân vật và phong cách nhất quán, liền mạch giữa các cảnh, cùng đồng bộ âm thanh–hình ảnh tích hợp sẵn — nhằm biến video AI trở nên hữu ích cho các quy trình sáng tạo chuyên nghiệp và tiền trực quan hóa.

Mới
Phổ biến
Sử dụng thương mại

Playground cho Doubao-Seedance-2-0

Khám phá Playground của Doubao-Seedance-2-0 — môi trường tương tác để kiểm tra mô hình và chạy truy vấn theo thời gian thực. Thử prompts, điều chỉnh tham số và lặp lại ngay lập tức để tăng tốc phát triển và xác thực các trường hợp sử dụng.

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.

Câu Hỏi Thường Gặp

Giá cả cho Doubao-Seedance-2-0

Khám phá mức giá cạnh tranh cho Doubao-Seedance-2-0, được thiết kế để phù hợp với nhiều ngân sách và nhu cầu sử dụng khác nhau. Các gói linh hoạt của chúng tôi đảm bảo bạn chỉ trả tiền cho những gì bạn sử dụng, giúp dễ dàng mở rộng quy mô khi yêu cầu của bạn tăng lên. Khám phá cách Doubao-Seedance-2-0 có thể nâng cao các dự án của bạn trong khi vẫn kiểm soát được chi phí.

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

Mã mẫu và API cho Doubao-Seedance-2-0

Truy cập mã mẫu toàn diện và tài nguyên API cho Doubao-Seedance-2-0 để tối ưu hóa quy trình tích hợp của bạn. Tài liệu chi tiết của chúng tôi cung cấp hướng dẫn từng bước, giúp bạn khai thác toàn bộ tiềm năng của Doubao-Seedance-2-0 trong các dự án của mình.

#!/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));
}

Các phiên bản của Doubao-Seedance-2-0

Lý do Doubao-Seedance-2-0 có nhiều snapshot có thể bao gồm các yếu tố tiềm năng như: sự thay đổi đầu ra sau các bản cập nhật cần các snapshot cũ để đảm bảo tính nhất quán, cung cấp cho nhà phát triển thời gian chuyển tiếp để thích ứng và di chuyển, cũng như các snapshot khác nhau tương ứng với các endpoint toàn cầu hoặc khu vực nhằm tối ưu hóa trải nghiệm người dùng. Để biết chi tiết về sự khác biệt giữa các phiên bản, vui lòng tham khảo tài liệu chính thức.

Version
doubao-seedance-2-0
doubao-seedance-2-0-fast