Mô hìnhGiáDoanh nghiệp
500+ API Mô hình AI, Tất cả trong Một API. Chỉ cần CometAPI
API Mô hình
Nhà phát triển
Bắt đầu nhanhTài liệuBảng Điều Khiển API
Công ty
Về chúng tôiDoanh nghiệp
Tài nguyên
Mô hình AIBlogNhật ký thay đổiHỗ trợ
Điều khoản Dịch vụChính sách Bảo mật
© 2026 CometAPI · All rights reserved
Home/Models/Doubao/Doubao-Seedance-2-0
D

Doubao-Seedance-2-0

Mỗi Giây:$0.08
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 khả năng tạo video kể chuyện đa cảnh mang phong cách điện ảnh. Khác với các bản demo chuyển văn bản thành video chỉ 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), đảm bảo tính nhất quán mạch lạc về nhân vật và phong cách xuyên suốt các cảnh quay, cùng khả năng đồng bộ âm thanh–hình ảnh ở mức gốc — nhằm khiế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
Sử dụng thương mại
Tổng quan
Tính năng
Giá cả
API
Phiên bản

Thông số kỹ thuật của Doubao Seedance 2.0

MụcChi tiết
Dòng sản phẩmDòng tạo video ByteDance Seedance
CometAPI slugdoubao-seedance-2-0
Nhà cung cấpByteDance / BytePlus ModelArk
Loại mô hìnhMô hình tạo video
Các dạng đầu vàoVăn bản, hình ảnh, âm thanh, video
Khả năng tham chiếuTối đa 9 hình ảnh, 3 đoạn video và 3 đoạn âm thanh trong một yêu cầu đa phương thức
Loại đầu raVideo MP4
Độ phân giải đầu ra480p, 720p, 1080p
Tỷ lệ khung hình21:9, 16:9, 4:3, 1:1, 3:4, 9:16
Thời lượng đầu ra4–15 giây
Kiểu APITạo video bất đồng bộ dựa trên tác vụ

Doubao Seedance 2.0 là gì?

Doubao Seedance 2.0 là mô hình tạo video đa phương thức chủ lực của ByteDance (ra mắt tháng 2/2026). Mô hình sử dụng kiến trúc tạo đồng thời âm thanh–hình ảnh thống nhất cho phép kiểm soát chính xác ở cấp độ đạo diễn bằng cách tham chiếu đồng thời nhiều hình ảnh, đoạn video và tệp âm thanh. Nó xuất sắc trong việc tạo các video giàu tính điện ảnh, chuyển động ổn định với đồng bộ âm thanh bản địa — lý tưởng cho nhà sáng tạo chuyên nghiệp cần vật lý chân thực, nhân vật nhất quán và dàn cảnh phức tạp.

Tính năng chính của Doubao Seedance 2.0 trên CometAPI

  • Tạo đa phương thức thống nhất: Chấp nhận đầu vào văn bản, hình ảnh, âm thanh và video trong một quy trình, giúp người dùng đạo diễn cảnh với tư liệu tham chiếu phong phú hơn so với trình tạo chỉ dựa trên văn bản.
  • Kiểm soát kiểu đạo diễn: Mô hình được xây dựng để tuân thủ prompt về diễn xuất, ánh sáng, đổ bóng, chuyển động camera, nhịp điệu chuyển động và đặc tính âm thanh.
  • Chỉnh sửa và mở rộng video: Seedance 2.0 không chỉ tạo lần đầu; nó hỗ trợ chỉnh sửa clip, nhân vật, hành động và tuyến truyện cụ thể, cùng mở rộng tiến/lùi.
  • Đồng bộ nghe–nhìn mạnh mẽ: ByteDance nhấn mạnh đầu ra stereo hai kênh và sự đồng bộ giữa nhạc nền, âm thanh môi trường và hành vi lồng tiếng để mang lại trải nghiệm sống động hơn.
  • Khả năng kiểm soát cao cho cảnh phức tạp: Cải thiện xử lý tương tác phức tạp, cảnh chuyển động và tính hợp lý vật lý so với Seedance 1.5.
  • Đầu ra định hướng sản xuất: API hỗ trợ cấu hình tỷ lệ, thời lượng và watermark, giúp mô hình phù hợp cho quy trình nội dung lặp lại.

Hiệu năng benchmark

ByteDance cho biết Seedance 2.0 sử dụng bộ đánh giá nội bộ SeedVideoBench-2.0 và đứng ở vị trí hàng đầu trên các chiều tác vụ văn bản sang video, hình ảnh sang video và đa phương thức. Mô hình cải thiện chất lượng tạo, độ chính xác vật lý, tính chân thực và khả năng kiểm soát so với Seedance 1.5, đặc biệt trong các cảnh tương tác và chuyển động phức tạp.

Chế độ Seedance 2.0 API và Seedance 2.0 Fast API trên CometAPI

Mô hìnhTên mô hình trên CometAPIPhù hợp nhất choKhác biệt chính
Seedance 2.0doubao-seedance-2-0Tạo video đa phương thức chất lượng cao nhấtNgăn xếp tham chiếu rộng nhất và khả năng kiểm soát mạnh nhất trong họ Seedance 2.0.
Seedance 2.0 fastdoubao-seedance-2-0-fastSản xuất nhanh hơn khi có thể đánh đổi chất lượngByteDance cho biết giữ nguyên năng lực mô hình như Seedance 2.0 nhưng tạo nhanh hơn.
Seedance 1.5 Prodoubao-seedance-1-5-proTạo âm thanh–hình ảnh thế hệ trướcSeedance 1.5 Pro được định vị là mô hình âm thanh–hình ảnh bản địa, trong khi Seedance 2.0 mở rộng ngăn xếp tham chiếu và chỉnh sửa.

Thế mạnh so với đối thủ:

  • vs Kling 3.0: Kiểm soát tham chiếu đa phương thức tốt hơn và âm thanh bản địa.
  • vs Sora 2: Độ chính xác tham chiếu và khả năng đa cảnh vượt trội; thời lượng tối đa hơi thấp hơn.
  • vs Veo 3.1: Mạnh hơn về tính nhất quán nhân vật và tuân thủ prompt trong quy trình nặng tham chiếu; Veo dẫn trước ở phối màu điện ảnh và clip dài hơn.

Vượt trội ở các video tập trung vào con người và dựa trên biểu diễn.

Dùng thử Seedance 2.0 AI Video Generator trên CometAPI

Step 1: Step 1: Đăng ký nhận khóa API

Bắt đầu trực tiếp trong CometAPI Playground để trải nghiệm Doubao Seedance 2.0 mà không cần thiết lập hay viết mã. Chỉ cần đăng nhập tài khoản CometAPI, vào trang mô hình doubao-seedance-2-0, tải lên hình ảnh tham chiếu, đoạn video ngắn hoặc tệp âm thanh, thêm prompt mô tả và tạo video xem trước ngay lập tức. Đây là cách nhanh nhất để hiểu Seedance 2.0 xử lý tính nhất quán chuyển động, diện mạo nhân vật, chuyển động camera và đồng bộ âm thanh bản địa.

Step 2: Nhận quyền truy cập API cho Seedance 2.0 trên CometAPI

Tạo hoặc dùng khóa CometAPI hiện có để kích hoạt quyền truy cập đầy đủ vào Doubao Seedance 2.0. Sau khi đăng nhập, điều hướng đến mục API Token trong bảng điều khiển, tạo khóa mới và sao chép. Sau đó truy cập trang chi tiết mô hình Seedance 2.0 và Tài liệu API trên CometAPI để xem các tham số hỗ trợ khi tích hợp vào dự án.

Step 3: Gửi yêu cầu đầu tiên với Seedance 2.0 API

Sử dụng endpoint CometAPI để gửi yêu cầu tạo video đầu tiên với prompt văn bản rõ ràng và các tệp tham chiếu tùy chọn (hình ảnh, video hoặc âm thanh). Hệ thống sẽ xử lý tác vụ bất đồng bộ, trả về task ID và cung cấp video MP4 có thể tải xuống khi hoàn tất. Bạn có thể tinh chỉnh prompt, điều chỉnh thiết lập và mở rộng quy mô cho video marketing, nội dung mạng xã hội, pipeline video tự động hoặc ứng dụng sáng tạo chạy trên Seedance 2.0.

Quy trình này giúp bạn thử nghiệm nhanh trong Playground và chuyển đổi mượt sang môi trường sản xuất qua CometAPI.

Lý do hàng đầu để chọn Seedance 2.0 trên CometAPI

Vì sao nên dùng CometAPI cho Seedance 2.0

  • Truy cập trực tiếp qua API hoặc Playground
  • Điều chỉnh tham số dễ dàng (thời lượng, độ phân giải, định dạng)
  • Hỗ trợ cả quy trình text-to-video và image-to-video
  • Xử lý tác vụ tích hợp cho tạo video bất đồng bộ

API thống nhất & thân thiện với lập trình viên

CometAPI cung cấp endpoint sạch, chuẩn hóa, hoạt động mượt mà với các định dạng kiểu OpenAI quen thuộc hoặc các endpoint tác vụ video chuyên dụng. Bạn có luồng tạo tác vụ, thăm dò (polling) và tải xuống MP4 đơn giản mà không phải xử lý xác thực phức tạp hay giới hạn khu vực của Volcengine.

Giá thành hiệu quả

CometAPI thường mang lại mức giá tính theo giây cạnh tranh hơn so với nhà cung cấp trực tiếp, cho phép bạn tạo video chất lượng cao ở quy mô lớn cho marketing, mạng xã hội hoặc pipeline tự động mà không vượt ngân sách.

Thử nghiệm nhanh với Playground

Thử nghiệm ngay trong CometAPI Playground. Tải lên hình ảnh, video và âm thanh tham chiếu, tinh chỉnh prompt và xem trước kết quả trong vài phút — rất phù hợp để lặp nhanh về phong cách, chuyển động và đồng bộ âm thanh trước khi vào sản xuất.

Tóm lại, nếu bạn muốn sức mạnh sáng tạo của Seedance 2.0 — kiểm soát tham chiếu hàng đầu, chuyển động tự nhiên và âm thanh bản địa — mà không phải vất vả với truy cập trực tiếp ByteDance, thì CometAPI hiện là một trong những nền tảng tốt nhất để sử dụng.

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

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

Seedance 2.0 hỗ trợ đầu vào đa phương thức bao gồm lời nhắc văn bản, tối đa 9 hình ảnh, tối đa 3 đoạn video ngắn và tối đa 3 tệp âm thanh, có thể tự do kết hợp để tạo nội dung phong phú, có thể kiểm soát.

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

Có — Seedance 2.0 được thiết kế cho kể chuyện nhiều cảnh mạch lạc, với nhân vật, phong cách thị giác và bầu không khí nhất quán xuyên suốt các cảnh, giảm thiểu hiện tượng trôi lệch thường gặp ở video AI.

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

Seedance 2.0 có thể tạo video chất lượng điện ảnh (độ phân giải lên đến 2K) với âm thanh gốc, lời thoại đồng bộ và tổng hợp chuyển động tự nhiên, thường ở các đoạn 5–60 giây.

How does Seedance 2.0 handle audio and lip synchronization?

Mô hình tạo đồng thời âm thanh và hình ảnh, mang đến đồng bộ âm thanh–hình ảnh gốc với khớp khẩu hình ở cấp độ âm vị trong hơn 8 ngôn ngữ, cho lời nói và hiệu ứng âm thanh tự nhiên.

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

Có — khả năng điều khiển đa phương thức, tính liên tục nhiều cảnh và chất lượng đầu ra trung thực cao của Seedance 2.0 khiến nó phù hợp cho video marketing, phim ngắn kể chuyện, quảng cáo và các ứng dụng chuyên nghiệp khác.

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

Người dùng có thể tải lên tài nguyên tham chiếu rồi mô tả bằng ngôn ngữ tự nhiên cách từng tài nguyên nên ảnh hưởng đến chuyển động, chuyển động máy quay hoặc các yếu tố phong cách, qua đó cho phép kiểm soát chi tiết đối với nội dung được tạo.

Does Seedance 2.0 allow editing and extension of existing videos?

Có — mô hình hỗ trợ mở rộng video và chỉnh sửa có mục tiêu như thêm cảnh, thay thế nhân vật hoặc thay đổi các đoạn cụ thể, đồng thời giữ nguyên những phần không chỉnh sửa.

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

Độ dài đầu ra điển hình dao động từ khoảng ~5 đến ~60 giây mỗi video, và việc kết hợp nhiều tài nguyên hoặc thiết lập độ phân giải cao có thể làm tăng thời gian tạo.

Tính năng cho Doubao-Seedance-2-0

Khám phá các tính năng chính của Doubao-Seedance-2-0, được thiết kế để nâng cao hiệu suất và khả năng sử dụng. Tìm hiểu cách các khả năng này có thể mang lại lợi ích cho dự án của bạn và cải thiện trải nghiệm người dùng.

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í.

doubao-seedance Video Generation Pricing

Parameters

ParameterDescription
Duration (seconds)4–15 seconds, default 5 seconds
Aspect Ratio (size)21:9 / 16:9 / 4:3 / 1:1 / 3:4 / 9:16, default 16:9
Resolution480p / 720p / 1080p*, default 720p

*1080p only available for doubao-seedance-1-5-pro and doubao-seedance-1-0-pro

Pricing (Per Second)

Model480p720p1080p
doubao-seedance-2-0$0.08$0.24—
doubao-seedance-2-0-fast$0.064$0.192—
doubao-seedance-1-5-pro$0.018$0.04147$0.09331
doubao-seedance-1-0-pro$0.01875$0.0432$0.0972

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

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.
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"),
        "resolution": (None, "720p"),
    }
)
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"),
        "resolution": (None, "720p"),
    }
)
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");
form.set("resolution", "720p");

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"' \
      -F 'resolution="720p"')

    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

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

Thêm mô hình

O

Sora 2 Pro

Mỗi Giây:$0.24
Sora 2 Pro là mô hình tạo sinh đa phương tiện tiên tiến và mạnh mẽ nhất của chúng tôi, có khả năng tạo video với âm thanh được đồng bộ hóa. Nó có thể tạo các đoạn video chi tiết, sinh động từ ngôn ngữ tự nhiên hoặc hình ảnh.
O

Sora 2

Mỗi Giây:$0.08
Mô hình tạo video siêu mạnh mẽ, kèm hiệu ứng âm thanh, hỗ trợ định dạng chat.
M

mj_fast_video

Theo Yêu cầu:$0.6
Midjourney video generation
X

Grok Imagine Video

Mỗi Giây:$0.04
Tạo video từ prompt văn bản, làm động ảnh tĩnh hoặc chỉnh sửa video hiện có bằng ngôn ngữ tự nhiên. API hỗ trợ cấu hình thời lượng, tỷ lệ khung hình và độ phân giải cho các video được tạo — với SDK tự động xử lý việc thăm dò bất đồng bộ.
G

Veo 3.1 Pro

Mỗi Giây:$0.25
Veo 3.1-Pro đề cập đến quyền truy cập/cấu hình có khả năng cao của dòng Veo 3.1 của Google — một thế hệ mô hình video dạng ngắn, có hỗ trợ âm thanh, bổ sung âm thanh gốc phong phú hơn, các điều khiển tường thuật/chỉnh sửa được cải thiện và các công cụ mở rộng cảnh.
G

Veo 3.1

Mỗi Giây:$0.05
Veo 3.1 là bản cập nhật tiệm tiến nhưng đáng kể của Google cho dòng Veo chuyển đổi văn bản và hình ảnh→video, bổ sung âm thanh gốc phong phú hơn, đầu ra video dài hơn và dễ kiểm soát hơn, cùng khả năng chỉnh sửa tinh vi và điều khiển ở cấp độ cảnh.

Blog liên quan

Cách sử dụng API Seedance 2.0
Apr 17, 2026

Cách sử dụng API Seedance 2.0

Seedance 2.0 API là mô hình tạo video AI đa phương thức mới nhất của ByteDance (ra mắt ngày 9 tháng 4 năm 2026). Nó chấp nhận văn bản, hình ảnh, clip video và âm thanh trong một yêu cầu duy nhất để tạo ra các video MP4 4–15 giây theo phong cách điện ảnh, với đồng bộ âm thanh gốc, kiểm soát camera ở cấp độ đạo diễn và tính nhất quán chuyển động vượt trội. Cách sử dụng: đăng ký trên CometAPI.com, nhận khóa API, gửi một tác vụ bất đồng bộ qua REST, thăm dò cho đến khi hoàn tất và tải xuống video tại URL.
HappyHorse-1.0 là gì? Làm thế nào để so sánh Seedance 2.0?
Apr 11, 2026
seedance-2-0

HappyHorse-1.0 là gì? Làm thế nào để so sánh Seedance 2.0?

Tìm hiểu HappyHorse-1.0 là gì, vì sao nó đứng đầu bảng xếp hạng video Artificial Analysis, cách nó so sánh với Seedance 2.0, và các bảng xếp hạng mới nhất có ý nghĩa gì đối với việc tạo video bằng AI.
Seedance 2.0 là gì? Phân tích toàn diện
Mar 24, 2026
seedance-2-0

Seedance 2.0 là gì? Phân tích toàn diện

Seedance 2.0 là một mô hình tạo video AI đa phương thức thế hệ mới do ByteDance phát triển, có thể tạo ra các video chất lượng cao mang phong cách điện ảnh từ văn bản, hình ảnh, âm thanh và video tham chiếu. Sản phẩm này nổi bật với khả năng tạo đồng bộ âm thanh–hình ảnh, độ ổn định chuyển động và chỉnh sửa dựa trên tham chiếu, và đã nhanh chóng leo lên các bảng xếp hạng toàn cầu như bảng xếp hạng Artificial Analysis, qua đó khẳng định vị thế trong nhóm các mô hình video AI hàng đầu năm 2026.