ModellerFiyatlandırmaKurumsal
500+ Yapay Zeka Modeli API'si, Hepsi Tek Bir API'de. Sadece CometAPI'de
Modeller API
Geliştirici
Hızlı BaşlangıçDokümantasyonAPI Kontrol Paneli
Şirket
HakkımızdaKurumsal
Kaynaklar
Yapay Zeka ModelleriBlogDeğişiklik GünlüğüDestek
Hizmet ŞartlarıGizlilik Politikası
© 2026 CometAPI · All rights reserved
Home/Models/Doubao/Doubao-Seedance-2-0
D

Doubao-Seedance-2-0

Saniyede:$0.063
Seedance 2.0, ByteDance’in sinematik, çok çekimli anlatı videoları üretimine odaklanan yeni nesil çok modlu video temel modelidir. Tek çekim metinden videoya demoların aksine Seedance 2.0, referans tabanlı kontrolü (görseller, kısa klipler, ses), çekimler arasında tutarlı karakter/stil sürekliliğini ve yerleşik ses/görüntü senkronizasyonunu vurgular — profesyonel yaratıcı ve ön görselleştirme iş akışları için yapay zekâ videolarını kullanışlı kılmayı hedefler.
Yeni
Ticari kullanım
Playground
Genel Bakış
Özellikler
Fiyatlandırma
API
Sürümler

Doubao Seedance 2.0 teknik özellikleri

ÖğeAyrıntılar
Ürün ailesiByteDance Seedance video üretim ailesi
CometAPI slugdoubao-seedance-2-0
SağlayıcıByteDance / BytePlus ModelArk
Model türüVideo üretim modeli
Girdi modaliteleriMetin, görsel
Çıktı türüMP4 video
Çıktı çözünürlüğü480p, 720p, 1080p
En-boy oranları21:9, 16:9, 4:3, 1:1, 3:4, 9:16
Çıktı süresi4–15 saniye
API stiliAsenkron görev tabanlı video üretimi

Doubao Seedance 2.0 nedir?

Doubao Seedance 2.0, ByteDance’in amiral gemisi çok modlu video üretim modelidir (Şubat 2026’da yayımlandı). Aynı anda birden çok görsel, video klibi ve ses dosyasına referans vererek yönetmen seviyesinde hassas kontrol sağlayan birleşik bir ses-görüntü ortak üretim mimarisi kullanır. Yerel ses senkronizasyonuyla sinematik, hareket açısından stabil videolar üretmede üstün bir performans sergiler — gerçekçi fizik, tutarlı karakterler ve karmaşık sahne kompozisyonu gerektiren profesyonel içerik üreticileri için idealdir.

CometAPI üzerinde Doubao Seedance 2.0’ın başlıca özellikleri

  • Birleşik çok modlu üretim: Metin, görsel, ses ve video girdilerini tek bir iş akışında kabul eder; böylece kullanıcılar yalnızca metin tabanlı bir üreticiye kıyasla daha zengin referans materyalle bir sahneyi yönlendirebilir.
  • Yönetmen tarzı kontrol: Model; performans, aydınlatma, gölge, kamera hareketi, hareket ritmi ve ses özelliklerine ilişkin yönergeleri takip edecek şekilde tasarlanmıştır.
  • Video düzenleme ve genişletme: Seedance 2.0 yalnızca ilk geçiş üretimiyle sınırlı değildir; belirli kliplerin, karakterlerin, eylemlerin ve hikâye çizgilerinin düzenlenmesini, ayrıca ileri/geri doğru genişletmeyi destekler.
  • Güçlü görsel-işitsel senkronizasyon: ByteDance, daha sürükleyici sonuçlar için çift kanallı stereo çıkışı ve arka plan müziği, ortam sesleri ve seslendirme davranışlarının senkronize edilmesini vurgular.
  • Karmaşık sahnelerde yüksek kontrol edilebilirlik: Seedance 1.5’e kıyasla karmaşık etkileşimlerin, hareketli sahnelerin ve fiziksel inandırıcılığın daha iyi ele alınmasını vurgular.
  • Üretim odaklı çıktı: API, yapılandırılabilir oran, süre ve filigran ayarlarını destekler; bu da modeli tekrarlanabilir içerik iş akışları için pratik kılar.

Kıyaslama performansı

ByteDance, Seedance 2.0’ın dahili SeedVideoBench-2.0 değerlendirmesini kullandığını ve metinden videoya, görselden videoya ve çok modlu görev boyutlarında lider konumda yer aldığını belirtir. Model, özellikle karmaşık etkileşim ve hareket sahnelerinde, Seedance 1.5’e kıyasla üretim kalitesini, fiziksel doğruluğu, gerçekçiliği ve kontrol edilebilirliği geliştirir.

CometAPI üzerinde Seedance 2.0 API ve Seedance 2.0 Fast API Modları

ModelCometAPI'deki model adıEn uygun kullanımAna fark
Seedance 2.0doubao-seedance-2-0En yüksek kaliteli çok modlu video oluşturmaSeedance 2.0 ailesinde en geniş referans yığını ve en güçlü kontrol edilebilirlik.
Seedance 2.0 fastdoubao-seedance-2-0-fastKaliteden biraz ödün verilebildiğinde daha hızlı üretimByteDance, Seedance 2.0 ile aynı model yeteneklerini koruduğunu, ancak daha hızlı üretim yaptığını belirtir.
Seedance 1.5 Prodoubao-seedance-1-5-proÖnceki nesil ses-görüntü oluşturmaSeedance 1.5 Pro yerel birleşik ses-görüntü modeli olarak konumlanırken, Seedance 2.0 çok modlu referans ve düzenleme yığınını genişletir.

Rakiplere karşı güçlü yönler:

  • vs Kling 3.0: Daha iyi çok modlu referans kontrolü ve yerel ses.
  • vs Sora 2: Daha üstün referans hassasiyeti ve çoklu çekim yeteneği; az biraz daha düşük maksimum süre.
  • vs Veo 3.1: Referans ağırlıklı iş akışlarında karakter tutarlılığı ve yönergeye uyumda daha güçlü; ham sinematik derecelendirme ve daha uzun kliplerde Veo önde.

İnsan merkezli ve performans odaklı videolarda üstün.

CometAPI üzerinde Seedance 2.0 AI Video Generator’ı deneyin

Adım 1: Adım 1: API anahtarı için kaydolun

Herhangi bir kurulum veya kodlama olmadan Doubao Seedance 2.0’ı deneyimlemek için doğrudan CometAPI Playground’da başlayın. Basitçe CometAPI hesabınıza giriş yapın, doubao-seedance-2-0 için model sayfasına gidin, referans görsellerinizi, kısa video kliplerinizi veya ses dosyalarınızı yükleyin, açıklayıcı bir istem ekleyin ve anında önizleme videoları oluşturun. Bu, Seedance 2.0’ın hareket tutarlılığını, karakter görünümünü, kamera hareketlerini ve yerel ses senkronizasyonunu nasıl ele aldığını anlamanın en hızlı yoludur.

Adım 2: CometAPI üzerinde Seedance 2.0 için API erişimi alın

Doubao Seedance 2.0’a tam erişim sağlamak için mevcut CometAPI anahtarınızı kullanın veya yeni bir anahtar oluşturun. Giriş yaptıktan sonra konsolunuzdaki API Token bölümüne gidin, yeni bir anahtar oluşturun ve kopyalayın. Ardından projelerinize entegrasyon için desteklenen parametreleri incelemek üzere CometAPI üzerindeki Seedance 2.0 model detay sayfasını ve API dokümanı sayfasını ziyaret edin.

Adım 3: Seedance 2.0 API ile ilk isteğinizi gönderin

Açık bir metin istemi ve isteğe bağlı referans dosyaları (görseller, video veya ses) ile ilk video üretim isteğinizi göndermek için CometAPI uç noktasını kullanın. Sistem görevi asenkron olarak işler, bir görev kimliği döndürür ve tamamlandığında indirilebilir bir MP4 video sağlar. Sonrasında istemlerinizi iyileştirebilir, ayarları düzenleyebilir ve Seedance 2.0 tarafından desteklenen pazarlama videoları, sosyal medya içerikleri, otomatik video hatları veya yaratıcı uygulamalar için ölçeklendirebilirsiniz.

Bu iş akışı, Playground’da hızlı denemeler yapmanızı ve CometAPI üzerinden üretim kullanımına sorunsuz geçiş yapmanızı sağlar.

CometAPI üzerinde Seedance 2.0’ı seçmek için başlıca nedenler

Seedance 2.0 için neden CometAPI’yi kullanmalısınız

  • API veya Playground üzerinden doğrudan erişim
  • Kolay parametre kontrolü (süre, çözünürlük, format)
  • Hem metinden videoya hem de görselden videoya iş akışlarını destekler
  • Asenkron video üretimi için yerleşik iş/görev yönetimi

Birleşik ve geliştirici dostu API

CometAPI, tanıdık OpenAI tarzı formatlarla veya özel video görev uç noktalarıyla sorunsuz çalışan, sade ve standartlaştırılmış bir uç nokta sunar. Volcengine’in karmaşık kimlik doğrulaması veya bölgesel kısıtlamalarıyla uğraşmadan, doğrudan görev oluşturma, yoklama (polling) ve MP4 indirmeleri elde edersiniz.

Uygun maliyetli fiyatlandırma

CometAPI, genellikle doğrudan sağlayıcılara kıyasla saniye başına daha rekabetçi oranlar sunar; böylece bütçenizi zorlamadan pazarlama, sosyal medya veya otomatik hatlar için ölçekli biçimde yüksek kaliteli videolar üretebilirsiniz.

Playground ile hızlı test

CometAPI Playground’da hemen deney yapın. Referans görselleri, videolar ve ses dosyaları yükleyin, istemleri düzenleyin ve sonuçları birkaç dakika içinde önizleyin — üretime geçmeden önce stil, hareket ve ses senkronizasyonu üzerinde yineleme yapmak için idealdir.

Kısacası, Seedance 2.0’ın yaratıcı gücünü — sınıfının en iyi referans kontrolü, doğal hareket ve yerel ses — doğrudan ByteDance erişiminin zahmeti olmadan istiyorsanız, CometAPI şu anda bunu kullanmak için en iyi platformlardan biridir.

SSS

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

Seedance 2.0, metin istemleri, en fazla 9 görsel, en fazla 3 kısa video klibi ve en fazla 3 ses dosyası dahil olmak üzere çok modlu girdileri destekler; bunlar zengin ve kontrol edilebilir üretim için serbestçe birleştirilebilir.

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

Evet — Seedance 2.0, sahneler arasında tutarlı karakterler, görsel stil ve atmosfer ile uyumlu çok çekimli hikâye anlatımı için tasarlanmıştır; bu da yaygın yapay zekâ video sapması sorunlarını azaltır.

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

Seedance 2.0, yerel ses, senkronize diyalog ve doğal hareket senteziyle sinema kalitesinde videolar (2K çözünürlüğe kadar) üretebilir; genellikle 5–60 saniyelik klipler halinde.

How does Seedance 2.0 handle audio and lip synchronization?

Model, sesi ve videoyu birlikte üretir; doğal konuşma ve ses efektleri için 8+ dilde fonem düzeyinde dudak senkronizasyonu ile yerel ses-görüntü senkronizasyonu sunar.

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

Evet — Seedance 2.0, çok modlu kontrol, çok çekimli süreklilik ve yüksek sadakatli çıktı ile pazarlama videoları, anlatı kısa filmleri, reklamlar ve diğer profesyonel uygulamalar için uygundur.

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

Kullanıcılar referans varlıkları yükleyebilir ve ardından her birinin hareketi, kamera hareketini veya stil öğelerini nasıl etkilemesi gerektiğini doğal dilde açıklayarak oluşturulan içerik üzerinde ince ayarlı kontrol sağlar.

Does Seedance 2.0 allow editing and extension of existing videos?

Evet — model, düzenlenmemiş bölümleri korurken sahne ekleme, karakterleri değiştirme veya belirli bölümleri değiştirme gibi hedefli düzenleme ve video uzatma işlemlerini destekler.

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

Video başına tipik çıktı uzunlukları ~5 ila ~60 saniye arasında değişir ve çok sayıda varlığın birleştirilmesi veya yüksek çözünürlüklü ayarlar, oluşturma süresini artırabilir.

Doubao-Seedance-2-0 için Fiyatlandırma

Doubao-Seedance-2-0 için çeşitli bütçelere ve kullanım ihtiyaçlarına uygun rekabetçi fiyatlandırmayı keşfedin. Esnek planlarımız sadece kullandığınız kadar ödeme yapmanızı sağlar ve ihtiyaçlarınız büyüdükçe kolayca ölçeklendirme imkanı sunar. Doubao-Seedance-2-0'in maliyetleri yönetilebilir tutarken projelerinizi nasıl geliştirebileceğini keşfedin.

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.

Doubao-Seedance-2-0 için örnek kod ve API

Doubao-Seedance-2-0 için kapsamlı örnek kodlara ve API kaynaklarına erişerek entegrasyon sürecinizi kolaylaştırın. Ayrıntılı dokümantasyonumuz adım adım rehberlik sağlayarak projelerinizde Doubao-Seedance-2-0'in tüm potansiyelinden yararlanmanıza yardımcı olur.
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

Doubao-Seedance-2-0 Sürümleri

Doubao-Seedance-2-0'nın birden fazla anlık görüntüye sahip olmasının nedeni; güncellemeler sonrası çıktı varyasyonları nedeniyle tutarlılık için eski anlık görüntülere ihtiyaç duyulması, geliştiricilere uyum ve geçiş için bir geçiş dönemi sağlanması ve kullanıcı deneyimini optimize etmek için küresel veya bölgesel uç noktalara karşılık gelen farklı anlık görüntüler içerebilir. Sürümler arasındaki detaylı farklar için lütfen resmi belgelere başvurun.
version
doubao-seedance-2-0
doubao-seedance-2-0-fast