视频生成 API
视频模型(当前上线:doubao-seedance-2.0,豆包 Seedance)走 异步任务,不是对话补全。
请使用下面两个接口,不要把视频模型发给 POST /chat/completions。
前置条件
模型 ID 以 模型广场 与控制台为准。
基本信息
| 项目 | 值 |
|---|---|
| Base URL | https://api.haiyushuke.com/v1 |
| 创建任务 | POST /video/generations |
| 查询任务 | GET /videos/{task_id} |
| Content-Type | application/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
}'请求体
| 字段 | 类型 | 说明 |
|---|---|---|
model | string | 必填。平台模型 ID,例如 doubao-seedance-2.0 |
prompt | string | 必填。镜头 / 画面描述 |
resolution | string | 可选。480p / 720p / 1080p,缺省按 720p 计费档位处理 |
duration | integer | 可选。时长(秒)。体验中心常用 5 或 10;未传时预扣按 5 秒估算 |
ratio | string | 可选。画面比例,原样转发给上游 |
generate_audio | boolean | 可选。是否生成配音 / 音画同步 |
has_video_input | boolean | 可选。请求是否带 视频参考。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_url。usage.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 / 720P | 1080P |
|---|---|---|
| 标准(不含视频入参) | 28 | 31 |
含视频(has_video_input: true) | 46 | 51 |
扣费节奏:
- 创建任务时预扣:按
resolution、duration、has_video_input估算输出 token 并从余额划出。余额不足返回 402 /INSUFFICIENT_BALANCE。 - 创建失败(上游错误等):预扣退回。
- 任务成功:退回预扣,再按查询响应里的
usage.completion_tokens实扣。 - 任务失败 / 取消 / 过期:预扣退回,不按输出结算。
同一任务只结算一次。明细见控制台 财务 → 使用记录。更多见 计费与财务。
错误与 HTTP 状态码
| 状态 | 常见原因 |
|---|---|
| 401 | Key 无效、过期或未带 Authorization: Bearer |
| 402 | 余额不足以完成预扣(INSUFFICIENT_BALANCE) |
| 403 | Key 未开通该模型,或 IP 不在白名单 |
| 404 | model 不存在或未上线(model_not_found) |
| 400 | 缺少 model 等必填字段 |
| 502 | 上游异常 |
视频生成耗时长、费用高于文本对话,请避免在浏览器前端持有 Key,并由后端控制并发与超时。
相关文档
- HTTP API 调用(文本对话)
- API Key 管理
- 计费与财务
- 快速开始
