视频生成 API

视频模型(当前上线:doubao-seedance-2.0,豆包 Seedance)走 异步任务,不是对话补全。

请使用下面两个接口,不要把视频模型发给 POST /chat/completions

前置条件

  1. 控制台  完成 实名认证充值 
  2. 创建 API Key,并在 Key 的 可用模型 中开通 doubao-seedance-2.0
  3. 可先在控制台 体验中心 用同一模型试生成,确认效果后再接入业务

模型 ID 以 模型广场 与控制台为准。

基本信息

项目
Base URLhttps://api.haiyushuke.com/v1
创建任务POST /video/generations
查询任务GET /videos/{task_id}
Content-Typeapplication/json
鉴权Authorization: Bearer <API_KEY>

创建接口会较快返回任务 ID;真正出片通常需要 数十秒到数分钟,需由客户端轮询查询接口。

调用流程

1. POST /video/generations   → 得到 task id(此时已按预估 token 预扣费用)
2. 每隔约 5 秒 GET /videos/{id}
3. status = succeeded        → 读取 content.video_url,按实际输出 token 结算
   status = failed / cancelled / expired → 预扣退回,无成片

创建任务

POST https://api.haiyushuke.com/v1/video/generations

curl https://api.haiyushuke.com/v1/video/generations \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "doubao-seedance-2.0",
    "prompt": "清晨的海边公路,镜头缓慢前推,阳光洒在湿润的柏油路上,电影感,4 秒一个镜头切换",
    "resolution": "720p",
    "duration": 5,
    "generate_audio": true
  }'

请求体

字段类型说明
modelstring必填。平台模型 ID,例如 doubao-seedance-2.0
promptstring必填。镜头 / 画面描述
resolutionstring可选。480p / 720p / 1080p,缺省按 720p 计费档位处理
durationinteger可选。时长(秒)。体验中心常用 5 或 10;未传时预扣按 5 秒估算
ratiostring可选。画面比例,原样转发给上游
generate_audioboolean可选。是否生成配音 / 音画同步
has_video_inputboolean可选。请求是否带 视频参考true 走「含视频」单价档,默认 false(「标准」档)

网关会把 JSON 转发给上游,并写入上游模型名。其它与上游兼容的字段也可随请求体传递;是否生效以上游与该模型实际上线能力为准。

创建成功时返回任务对象(HTTP 2xx),至少包含 id。请保存该 ID 用于后续查询。

{
  "id": "cgt-xxxxxxxx",
  "model": "doubao-seedance-2.0",
  "status": "queued"
}

id 的具体前缀以上游返回为准。若同时返回 upstream_id,查询时优先使用 id

查询任务

GET https://api.haiyushuke.com/v1/videos/{task_id}

curl https://api.haiyushuke.com/v1/videos/cgt-xxxxxxxx \
  -H "Authorization: Bearer YOUR_API_KEY"

建议间隔 5 秒 轮询;单次生成可能持续数分钟。控制台体验中心最多轮询约 7.5 分钟,业务侧请按超时策略自行截断并提示用户。

任务状态

status(大小写不敏感)含义计费
queued / running 等非终态生成中保持预扣
succeeded / success / completed成功退回预扣后,按实际输出 token 扣费
failed / cancelled / canceled / expired / error失败或取消退回预扣,不按输出结算

成功响应(字段示意)

{
  "id": "cgt-xxxxxxxx",
  "model": "doubao-seedance-2.0",
  "status": "succeeded",
  "resolution": "720p",
  "content": {
    "video_url": "https://example.com/output.mp4",
    "last_frame_url": "https://example.com/last-frame.jpg"
  },
  "usage": {
    "completion_tokens": 108900,
    "total_tokens": 108900
  }
}

成片地址优先读 content.video_url,若无则读顶层 video_urlusage.completion_tokens(没有则用 total_tokens)为结算用的 输出视频 token

Python 示例

import os
import time
import requests
 
BASE = os.environ.get("HAIYUSHUKE_BASE_URL", "https://api.haiyushuke.com/v1")
KEY = os.environ["HAIYUSHUKE_API_KEY"]
HEADERS = {
    "Authorization": f"Bearer {KEY}",
    "Content-Type": "application/json",
}
 
created = requests.post(
    f"{BASE}/video/generations",
    headers=HEADERS,
    json={
        "model": "doubao-seedance-2.0",
        "prompt": "城市夜景航拍,霓虹倒映在江面,缓慢环绕",
        "resolution": "720p",
        "duration": 5,
    },
    timeout=180,
)
created.raise_for_status()
task_id = created.json()["id"]
 
terminal_ok = {"succeeded", "success", "completed", "complete"}
terminal_fail = {"failed", "cancelled", "canceled", "expired", "error"}
 
for _ in range(90):
    r = requests.get(f"{BASE}/videos/{task_id}", headers=HEADERS, timeout=60)
    r.raise_for_status()
    task = r.json()
    status = str(task.get("status") or "").lower()
    if status in terminal_ok:
        content = task.get("content") or {}
        print(content.get("video_url") or task.get("video_url"))
        break
    if status in terminal_fail:
        raise RuntimeError(task.get("error") or status)
    time.sleep(5)
else:
    raise TimeoutError("视频生成超时")

Node.js 示例

const BASE = process.env.HAIYUSHUKE_BASE_URL ?? "https://api.haiyushuke.com/v1";
const KEY = process.env.HAIYUSHUKE_API_KEY;
 
async function createAndWait(prompt) {
  const created = await fetch(`${BASE}/video/generations`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "doubao-seedance-2.0",
      prompt,
      resolution: "720p",
      duration: 5,
    }),
  });
  if (!created.ok) throw new Error(await created.text());
  const { id } = await created.json();
 
  const ok = new Set(["succeeded", "success", "completed", "complete"]);
  const fail = new Set(["failed", "cancelled", "canceled", "expired", "error"]);
 
  for (let i = 0; i < 90; i++) {
    const res = await fetch(`${BASE}/videos/${id}`, {
      headers: { Authorization: `Bearer ${KEY}` },
    });
    if (!res.ok) throw new Error(await res.text());
    const task = await res.json();
    const status = String(task.status || "").toLowerCase();
    if (ok.has(status)) {
      return task.content?.video_url || task.video_url;
    }
    if (fail.has(status)) {
      throw new Error(task.error?.message || status);
    }
    await new Promise((r) => setTimeout(r, 5000));
  }
  throw new Error("视频生成超时");
}

官方 OpenAI SDK 的 chat.completions 不能生成视频;OpenAI 原站的 /videos 路径也与本网关的 /video/generations 不一致。请按上文直接调用 HTTP。

计费说明(doubao-seedance-2.0

分辨率档位单价(元 / 1M tokens)× 输出视频 token 计费。单价以控制台模型广场为准,当前公示原价:

档位480P / 720P1080P
标准(不含视频入参)2831
含视频(has_video_input: true4651

扣费节奏:

  1. 创建任务时预扣:按 resolutiondurationhas_video_input 估算输出 token 并从余额划出。余额不足返回 402 / INSUFFICIENT_BALANCE
  2. 创建失败(上游错误等):预扣退回。
  3. 任务成功:退回预扣,再按查询响应里的 usage.completion_tokens 实扣。
  4. 任务失败 / 取消 / 过期:预扣退回,不按输出结算。

同一任务只结算一次。明细见控制台 财务 → 使用记录。更多见 计费与财务

错误与 HTTP 状态码

状态常见原因
401Key 无效、过期或未带 Authorization: Bearer
402余额不足以完成预扣(INSUFFICIENT_BALANCE
403Key 未开通该模型,或 IP 不在白名单
404model 不存在或未上线(model_not_found
400缺少 model 等必填字段
502上游异常

视频生成耗时长、费用高于文本对话,请避免在浏览器前端持有 Key,并由后端控制并发与超时。

相关文档