Seedance 2.0 视频生成 API 怎么调:快速上手(2026)

Seedance 2.0 API 快速上手:一把 ofox key,POST /v1/videos,轮询到 completed,读 unsigned_urls[0]。Python + Node 代码,价格 $0.07/s 起。

Seedance 2.0 视频生成 API 怎么调:快速上手(2026)

Seedance 2.0 是 ByteDance 的文生视频与图生视频模型,而调用它最快的方式是走 ofox:一把 API key、美元计费、一个异步 REST 端点。你向 POST https://api.ofox.io/v1/videos 发一个 model ID 加一段 prompt,拿回一个 polling_url,轮询到状态变成 completed,再从 unsigned_urls[0] 读出片段。不用为每家厂商单开账号,也不用装单独的 SDK。本文剩下的部分就是一份能跑通的快速上手:鉴权、Python 和 Node 各一个文生视频调用、异步生命周期、图像与参考输入,以及一段片段实际要花多少钱。

端点POST https://api.ofox.io/v1/videos(异步)
鉴权一把 ofox Bearer key
模型 IDbytedance/seedance-2.0-fast-mini
首个片段耗时约 5 分钟
取回结果轮询 GET /v1/videos/{id},读 unsigned_urls[0]

你需要准备什么

三样东西,如果你已经用 ofox 做过 chat 或图像调用,那其中两样你早就有了。

  1. 一把 ofox API key。 base URL 是 https://api.ofox.io/v1,鉴权用标准的 Authorization: Bearer 头。你做 OpenAI 兼容的 chat 和图像请求用的那把 key,同样能提交视频任务,所以不用另开账号,也不用装厂商 SDK。
  2. 端点。 一切都走 POST /v1/videosGET /v1/videos/{id}。整个操作面就这么大。
  3. 一个 model ID。 bytedance/seedance-2.0 是旗舰档:文生视频、图生视频、视频生视频、同步音轨、4 到 15 秒的片段、最高 4K。bytedance/seedance-2.0-fastbytedance/seedance-2.0-mini 是更便宜的档位,两者都封顶 720p。

把 key 设一次:

export OFOX_API_KEY="sk-..."

你的第一个请求:文生视频

视频生成不像 chat completion 那样是个阻塞调用。片段需要渲染时间,所以 POST /v1/videos 会立刻返回一个 202 Accepted 和一个 polling_url,你轮询那个 URL 直到任务进入终态。模式由你发送的字段推断:没有图像字段就是文生视频。

下面是一次完整的 Python 往返。它提交任务,以合理的节奏轮询,再从 unsigned_urls[0] 取出片段。

import os, time, requests

BASE = "https://api.ofox.io/v1"
HEAD = {"Authorization": f"Bearer {os.environ['OFOX_API_KEY']}"}
TERMINAL = {"completed", "failed", "cancelled", "expired"}

job = requests.post(f"{BASE}/videos", headers=HEAD, json={
    "model": "bytedance/seedance-2.0",
    "prompt": "A red kayak cuts through morning fog on a still lake, slow dolly forward.",
    "duration": 8,
    "resolution": "1080p",
    "aspect_ratio": "16:9",
})
job.raise_for_status()                     # 202 Accepted
task_url = job.json()["polling_url"]

while True:
    task = requests.get(task_url, headers=HEAD).json()
    if task["status"] in TERMINAL:         # 命中全部四个终态都要跳出
        break
    time.sleep(2)                          # 每 1-2s 轮询一次,别用死循环猛打

if task["status"] == "completed":
    print("clip:", task["unsigned_urls"][0])   # 没有 output_url 字段
    print("billed:", task["usage"]["video_cost"], "USD",
          "for", task["usage"]["video_seconds"], "s")
else:
    print("job ended as:", task["status"])

用 Node 的 fetch 是同样的结构:

const BASE = "https://api.ofox.io/v1";
const HEAD = {
  Authorization: `Bearer ${process.env.OFOX_API_KEY}`,
  "Content-Type": "application/json",
};
const TERMINAL = ["completed", "failed", "cancelled", "expired"];

const job = await fetch(`${BASE}/videos`, {
  method: "POST",
  headers: HEAD,
  body: JSON.stringify({
    model: "bytedance/seedance-2.0",
    prompt: "A red kayak cuts through morning fog on a still lake, slow dolly forward.",
    duration: 8,
    resolution: "1080p",
    aspect_ratio: "16:9",
  }),
});
const { polling_url } = await job.json();          // 202 Accepted

let task;
do {
  await new Promise((r) => setTimeout(r, 2000));   // 每 1-2s 轮询一次
  task = await (await fetch(polling_url, { headers: HEAD })).json();
} while (!TERMINAL.includes(task.status));

if (task.status === "completed") {
  console.log("clip:", task.unsigned_urls[0]);     // 不是 output_url
  console.log("billed:", task.usage.video_cost, "USD");
}

有两件事会绊倒第一次调用的人。第一是去取 resp["output_url"]——它并不存在,在 Python 里返回 None、在 Node 里返回 undefined。片段在 unsigned_urls[0] 里。第二是只检查 completed 的轮询循环。一个以 failedexpired 收尾的任务永远不会置为 completed,所以忽略其他终态的循环会一直空转。四个终态都要跳出。

处理异步生命周期

一个 Seedance 任务会走过一组固定的状态。三个是过渡态,四个是终态。没有 processing 这个状态,所以别去检查它。

状态阶段该做什么
pending已受理,尚未排队每 1-2s 继续轮询
queued已排队待渲染每 1-2s 继续轮询
in_progress渲染中每 1-2s 继续轮询
completed完成,已附 URLunsigned_urls[0] 下载
failed生成出错读错误,重试或回退
cancelled你取消了它停止轮询
expired任务过期重新提交

轮询节奏很重要。GET /v1/videos/{id} 不要快于每秒一次;大约每一到两秒是最佳区间。在死循环里猛打只会浪费配额,也不会让结果更早出来,因为片段无论如何都在上游渲染。

结果 URL 有保质期,所以把 completed 当作下载的信号。unsigned_urls 在任务结束后约 24 小时过期。mirror_urls 是持久的,但每个签名链接仍带自己的 TTL。实操上:当状态翻到 completed,立刻把 unsigned_urls[0] 拉进你自己的存储桶(S3、R2、GCS),而不是把 API URL 存下来之后再发给客户端。

生产环境通常应该用 webhook,而不是一个轮询线程。创建时传一个 callback_url,任务进入终态时 ofox 会 POST 一个 HMAC 签名的负载过来。这个地址必须是公开 HTTPS;私有、回环或其他不可达的主机会在提交时被拒,返回 400 invalid_callback_url。轮询和 webhook 并不互斥,所以常见做法是 happy path 用 webhook,再加一个慢速轮询兜底。

需要提前停掉一个任务?DELETE /v1/videos/{id} 会取消它,任务随后落到 cancelled

图生视频与参考图

想让一张静图动起来,或用参考帧引导生成,你都不用换端点。同一个 POST /v1/videos,同样的轮询。请求模式由你带上哪些字段推断。

  • 不带图像字段 就是文生视频,也就是上面那个调用。
  • frame_images 就是图生视频。传一个 URL 作为单个起始帧,或传首帧和尾帧让模型在两者之间做插值。
  • input_references 就是参考引导生成,你提供一些图像来锚定身份、风格或某个产品的外观。

从起始帧做图生视频:

job = requests.post(f"{BASE}/videos", headers=HEAD, json={
    "model": "bytedance/seedance-2.0",
    "prompt": "The logo tilts up and catches a rim light, subtle rotation.",
    "frame_images": ["https://your-cdn.com/first-frame.png"],
    "duration": 8,
    "resolution": "1080p",
    "aspect_ratio": "16:9",
})

后续一切都相同:202、一个 polling_url、同一组状态,以及在 unsigned_urls[0] 里的片段。三档都会生成音轨,所以在 prompt 里点名你想要的声音,否则你就得接受模型自己推断出来的结果。

定价:按分辨率,不是固定档价

这是大家最容易算错的数字。目录里 Seedance 2.0 旁边那个 $0.07/s 起 是 480p 的底价,不是一个固定费率。价格随你请求的分辨率上涨,所以一段片段的真实成本,是你所在分辨率的每秒费率乘以片段时长。下面是旗舰文生视频的费率表:

分辨率bytedance/seedance-2.0(文生视频)
480p$0.07/s
720p$0.16/s
1080p$0.34/s
4K$1.37/s

计费按输出秒数,completed 响应会在 usage.video_cost 里告诉你确切的费用。所以一段 8 秒 1080p 片段是 8 x $0.34 = $2.72,同一段片段在 4K 下是 8 x $1.37 = $10.96。视频生视频在每个分辨率上都比文生视频每秒略贵一点,模型页里有完整说明。

更便宜的档位用分辨率换成本,两者都封顶 720p:bytedance/seedance-2.0-fast 是 480p $0.06/s、720p $0.13/s,而 bytedance/seedance-2.0-mini 是 480p $0.04/s、720p $0.08/s。如果你的输出大多落在一个反正会降采样到 720p 的 feed 上,那 Mini 的 $0.08/s 是三档里最低的 720p 费率。

因为三档共用同一个端点,只在 model 字符串上不同,你可以把草稿路由到 Mini,把旗舰留给母版。要看完整的正面对比,包括 Fast 相对 Mini 的溢价什么时候值得,读 Seedance 2.0 三档对比;要看完整的分辨率分级矩阵,看 Seedance 2.0 模型页

一把 key,所有视频模型

这份快速上手之所以短,是因为 ofox 把整个视频栈收敛成了一套鉴权和一套 schema。你已经掌握了这个套路:提交到 /v1/videos,轮询,下载。换模型只是改个字符串。

用你手上已有的 key 在 Seedance 2.0 上生成视频。 开始使用 ofox 视频 API:一把 key、美元计费、只为你渲染的秒数付费,无需为每家厂商单独注册。

如果 Seedance 对某段片段不合适,同一个端点也能触及目录里的其余模型。阿里的 Wan 最短从 2 秒起步,而 Seedance 的下限是 4 秒;Seedance 2.0 与 Wan 对比 讲了这笔取舍。确切的请求和响应字段,包括每一个可选参数,都在 ofox 视频 API 参考文档 里。

FAQ

Seedance 2.0 API 怎么调?POST https://api.ofox.io/v1/videos 发一个 Bearer ofox key,加一个包含 modelpromptdurationresolutionaspect_ratio 的 JSON body。它返回 202 和一个 polling_url。每 1-2 秒轮询一次 GET /v1/videos/{id},直到 status 变成 completed,再从 unsigned_urls[0] 读出片段。

为什么我读 output_url 时视频 URL 是空的? 因为根本没有 output_url 字段。片段在 unsigned_urls 里(一个数组,所以用 unsigned_urls[0]),或者在 mirror_urls 里。读 resp["output_url"] 每次都返回 None

Seedance 2.0 的结果 URL 能有效多久? unsigned_urls 在完成后约 24 小时过期。mirror_urls 是持久的,但每个签名链接都带自己的 TTL。状态一变成 completed 就把文件下载下来。

Seedance 2.0 API 要多少钱? 按输出秒数、按分辨率计费,不是固定费率。旗舰文生视频是 480p $0.07/s、720p $0.16/s、1080p $0.34/s、4K $1.37/s。一段 8 秒 1080p 片段是 $2.72。

Seedance 2.0 能从一张图片生成视频吗? 能。传 frame_images 做图生视频,或传 input_references 做参考引导生成。模式由字段推断;不带图像就是文生视频。

Seedance 2.0 最便宜的模型是哪个? bytedance/seedance-2.0-mini,480p $0.04/s、720p $0.08/s。它封顶 720p,-fast 也一样。只有旗舰能到 1080p 和 4K。

本次核实查阅的来源