视频生成 API 接入文档

版本 v1.1 | 更新日期 2026-09-27 | 网关:https://www.20saminos.cn

目录


1. 概述

本网关提供 Seedance / MiniMax 系列视频生成能力,接口兼容 OpenAI Chat Completions 协议——任何支持该协议的 SDK 或客户端都可以直接调用。

项目 值
网关地址 https://www.20saminos.cn
提交端点 POST /v1/chat/completions
调用方式 两段式:先提交任务拿 TASK_ID,再轮询状态取视频地址
数据格式 JSON,Content-Type: application/json

调用链路:

1
调用方 → 本网关(鉴权 · 计费 · 限流)→ 协议适配层 → 视频模型上游

2. 鉴权

所有请求需在请求头携带平台令牌:

1
Authorization: Bearer sk-xxxxxxxxxxxxxxxx

注意:令牌在平台后台「令牌管理」创建,创建时分组必须选择 default,否则请求会返回「无可用渠道」。


3. 可用模型

模型 ID 时长(秒) 分辨率 画面比例 说明
seedance-2.0 5 / 15 720p 9:16、1:1、3:4、4:3、16:9 综合质量最好
seedance-2.5 14 / 30 720p 同上 长视频,最长 30 秒
minimaxh3 4 ~ 15(整数) 2K 同上 支持参考视频/音频,任意时长同价

分辨率由模型固定,不需要也不能覆盖(传入会被忽略)。


4. 提交任务

4.1 请求

1
2
3
POST /v1/chat/completions
Authorization: Bearer sk-xxx
Content-Type: application/json
1
2
3
4
5
6
7
8
9
10
{
"model": "seedance-2.0",
"messages": [
{ "role": "user", "content": "一只小狗在草地上奔跑,镜头缓慢推进,阳光自然,画面稳定" }
],
"duration": 5,
"ratio": "9:16",
"mode": "text-to-video",
"request_id": "order_20260927_001"
}

4.2 参数说明

参数 必填 类型 说明
model ✅ string 见第 3 节模型表
messages ✅ array 提示词写在最后一条 user 消息的 content 里,长度 1–10000 字符
duration int 秒数,取值受模型限制;不传则用默认值(2.0 → 5、2.5 → 14、minimaxh3 → 15)
ratio string 画面比例,默认 9:16
mode string text-to-video(默认)、reference(参考图生视频)、first-frame(首帧生视频)
images array 参考图/首帧图 URL 数组,最多 9 张,详见 4.4
request_id string 幂等键,建议传唯一订单号。同一 request_id 重复提交不会重复扣费

兜底写法:如果客户端不方便传顶层参数,可以写在提示词末尾,例如
...影调偏暖 [duration=5 ratio=16:9]

4.3 响应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"id": "chatcmpl-c8e39d2d90f045bc95a7",
"object": "chat.completion",
"created": 1790473750,
"model": "koko",
"choices": [
{
"index": 0,
"finish_reason": "stop",
"message": {
"role": "assistant",
"content": "TASK_ID: ee9e3705d6dd4693a50ebb8602a863ba\nSTATUS: queued\nPOINTS: 8\nBALANCE: 1064"
}
}
]
}

content 中是若干行 键: 值,按行解析即可:

字段 含义
TASK_ID 任务编号,务必保存,查询和取片都用它
STATUS 提交后的即时状态,通常为 queued 或 running
POINTS 本次扣除的积分
BALANCE 账户剩余积分

4.4 参考图与首帧图

除了纯文生视频,还支持上传图片作为参考或首帧:

参数 说明
images 图片 URL 数组,1–9 张
mode first-frame:首帧生视频(取 images 第 1 张)
reference:参考图生视频
不传且带 images 时默认按 reference 处理

图片要求(重要)

上游服务器会主动去下载你提供的图片,因此必须满足:

检查项 要求
协议 必须 HTTPS,http 不支持
可达性 公网可直连,不能是内网地址、不能需要登录/Cookie/Basic Auth
防盗链 不能有 Referer 校验,否则上游会拿到 403
Content-Type 必须是 image/*(见下方常见坑)
格式 JPG / PNG / WebP
大小 单张 ≤ 50 MB
数量 最多 9 张

⚠️ 最常见的坑:只看状态码 200 是不够的。
很多反向代理站点对不存在的路径会返回 200 + text/html(前端首页),看起来”能访问”,但上游拿到的是网页不是图片,会直接报错。必须确认 Content-Type 是 image/*。

自检命令:

1
curl -sI "https://your-cdn.com/first.png" | grep -iE 'HTTP|content-type|content-length'
返回 判定
200 + content-type: image/png ✅ 可用
200 + content-type: text/html ❌ 拿到的是网页
403 / 404 / 超时 ❌ 上游拿不到

示例:首帧生视频

1
2
3
4
5
6
7
8
9
10
11
{
"model": "seedance-2.0",
"messages": [
{ "role": "user", "content": "冰淇淋变成一个跳舞的粑粑" }
],
"duration": 5,
"ratio": "9:16",
"mode": "first-frame",
"images": ["https://img.example.com/first.png"],
"request_id": "ff_test_001"
}

示例:参考图生视频

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"model": "seedance-2.0",
"messages": [
{ "role": "user", "content": "画面中的猫咪缓缓睁开眼睛,镜头轻微推近" }
],
"duration": 5,
"ratio": "1:1",
"mode": "reference",
"images": [
"https://img.example.com/cat.png",
"https://img.example.com/style.png"
]
}

最佳实践

  1. 比例对齐:ratio 要与图片比例一致(竖图用 9:16,横图用 16:9),否则首帧会被裁切或拉伸。
  2. prompt 描述动作和镜头运动,不要重复描述静态画面——首帧已经决定了画面起点。
  3. 图片放独立静态站点或对象存储(公共读),不要放在有登录态、防盗链或反向代理兜底成 HTML 的站点上。
  4. 图片处理失败会自动退还积分,不用担心扣费。

5. 查询任务状态

沿用同一个端点,把 model 换成带 -status 后缀的模型(该模型不计费),消息体中放入 TASK_ID:

1
2
3
4
5
6
{
"model": "seedance-2.0-status",
"messages": [
{ "role": "user", "content": "TASK_ID: ee9e3705d6dd4693a50ebb8602a863ba" }
]
}

响应:

1
2
3
4
5
6
7
8
9
{
"choices": [
{
"message": {
"content": "TASK_ID: ee9e3705d6dd4693a50ebb8602a863ba\nSTATUS: completed\nVIDEO_URL: https://example.com/video.mp4\nFAILURE_REASON: "
}
}
]
}

状态说明

STATUS 含义 处理方式
queued 已扣费,等待提交上游 继续轮询
running 生成中 继续轮询
completed 生成完成 读取 VIDEO_URL
failed 生成失败,积分已自动退回 查看 FAILURE_REASON

轮询建议:提交后每隔 5–10 秒查询一次,直到 completed 或 failed。多数任务在 1–5 分钟内完成,请勿高频轮询。

⚠️ 关于 VIDEO_URL

返回的 VIDEO_URL 是带签名的临时下载链接,有有效期。过期后再次访问会返回:

1
2
3
4
5
6
{
"error": {
"code": "INVALID_DOWNLOAD_SIGNATURE",
"message": "视频下载链接无效或已过期,请重新查询任务状态获取新链接"
}
}

处理方式:

  • 不要直接把该链接交付终端用户长期使用;
  • 拿到后请立即下载并转存到自己的对象存储/CDN;
  • 如果链接已失效,重新调用本接口查询任务即可获取新链接(任务本身不会失效)。

6. 完整示例

6.1 cURL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# ① 提交任务
curl -s https://www.20saminos.cn/v1/chat/completions \
-H "Authorization: Bearer sk-xxx" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.0",
"messages": [{"role": "user", "content": "一只小狗在草地上奔跑,镜头缓慢推进"}],
"duration": 5,
"ratio": "9:16",
"request_id": "order_001"
}'

# ② 查询状态(把 TASK_ID 换成上一步返回的值)
curl -s https://www.20saminos.cn/v1/chat/completions \
-H "Authorization: Bearer sk-xxx" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.0-status",
"messages": [{"role": "user", "content": "TASK_ID: ee9e3705d6dd4693a50ebb8602a863ba"}]
}'

6.2 首帧生视频(cURL)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cat > /tmp/first.json <<'EOF'
{
"model": "seedance-2.0",
"messages": [{"role": "user", "content": "冰淇淋变成一个跳舞的粑粑"}],
"duration": 5,
"ratio": "9:16",
"mode": "first-frame",
"images": ["https://img.example.com/first.png"],
"request_id": "ff_test_002"
}
EOF

curl -s https://www.20saminos.cn/v1/chat/completions \
-H "Authorization: Bearer sk-xxx" \
-H "Content-Type: application/json" -d @/tmp/first.json

6.3 Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import re
import time
import uuid
import requests

BASE = "https://www.20saminos.cn/v1/chat/completions"
TOKEN = "sk-xxx"
HEAD = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}


def submit(prompt, model="seedance-2.0", duration=5, ratio="9:16",
mode="text-to-video", images=None):
"""提交任务,返回 TASK_ID"""
body = {
"model": model,
"messages": [{"role": "user", "content": prompt}],
"duration": duration,
"ratio": ratio,
"mode": mode,
"request_id": uuid.uuid4().hex,
}
if images:
body["images"] = images
resp = requests.post(BASE, json=body, headers=HEAD, timeout=60)
text = resp.json()["choices"][0]["message"]["content"]
return re.search(r"TASK_ID:\s*(\S+)", text).group(1)


def wait(task_id, model="seedance-2.0", interval=8, timeout=900):
"""轮询直到完成,返回视频地址"""
t0 = time.time()
while time.time() - t0 < timeout:
resp = requests.post(BASE, headers=HEAD, timeout=30, json={
"model": f"{model}-status",
"messages": [{"role": "user", "content": f"TASK_ID: {task_id}"}],
})
text = resp.json()["choices"][0]["message"]["content"]
status = re.search(r"STATUS:\s*(\S+)", text).group(1)
if status == "completed":
return re.search(r"VIDEO_URL:\s*(\S+)", text).group(1)
if status == "failed":
raise RuntimeError(re.search(r"FAILURE_REASON:\s*(.*)", text).group(1))
time.sleep(interval)
raise TimeoutError("生成超时")


if __name__ == "__main__":
# 文生视频
task = submit("一只小狗在草地上奔跑,镜头缓慢推进")
print("视频地址:", wait(task))

# 首帧生视频
task = submit("冰淇淋变成一个跳舞的粑粑",
mode="first-frame",
images=["https://img.example.com/first.png"])
print("视频地址:", wait(task))

7. 错误码

错误响应为 OpenAI 风格:

1
2
3
4
5
6
7
{
"error": {
"message": "seedance-2.0 只支持 [5, 15],收到 8",
"type": "koko_error",
"code": "INVALID_DURATION"
}
}
HTTP code 说明
400 invalid_request 请求体结构问题(如缺少 messages)
400 MODEL_NOT_SUPPORTED 模型 ID 不在支持列表
400 INVALID_PROMPT 提示词为空或超过 10000 字符
400 INVALID_DURATION 时长不符合该模型规格
400 INVALID_RATIO 画面比例不支持
400 INVALID_MODE mode 取值不支持
400 INVALID_REFERENCE_MEDIA 参考素材不是公网 HTTPS URL
400 INVALID_REFERENCE_IMAGES 参考图字段、数量或格式不符合要求
400 REFERENCE_UPLOAD_FAILED 参考图下载/处理失败,积分已自动退回
401 INVALID_API_KEY 令牌无效或已停用
402 INSUFFICIENT_POINTS 积分不足,未扣费
404 TASK_NOT_FOUND 任务不存在或不属于当前账号
429 RATE_LIMITED 超过每分钟 120 次请求
502 UPSTREAM_ERROR 上游提交/查询失败;若 message 含「参考图处理失败」,通常是图片地址返回的不是图片
503 MODEL_MAINTENANCE 模型维护中,未扣积分
504 UPSTREAM_TIMEOUT 上游超时,积分已退回
4xx 无可用渠道 令牌分组与模型不匹配

8. 计费

  • 按次计费,与 token 数、视频文件大小、参考图数量无关。
  • 扣费发生在提交成功时;提交失败、参数校验失败、参考图处理失败、模型维护、任务最终失败都会自动退回。
  • 同一 request_id 最多成功扣费一次。
模型 积分/次 折合人民币
seedance-2.0 8 约 ¥0.8
seedance-2.5 待确认 —
minimaxh3 待确认 —
*-status(查询) 0 免费

价格以平台后台实时配置为准。


9. 限制与注意事项

  1. 同一提示词不保证结果一致,视频生成具有随机性。
  2. VIDEO_URL 是临时签名链接,会过期,请立即下载转存(详见第 5 节)。
  3. 参考图/首帧图必须是公网 HTTPS 且能被上游直接访问,Content-Type 必须为 image/*,单张 ≤ 50 MB、最多 9 张。内网地址、需鉴权地址、防盗链地址都会导致失败(积分自动退回)。
  4. 参考图比例需与 ratio 一致,否则首帧会被裁切或拉伸。
  5. 单令牌限速 120 次/分钟,批量生成请做好排队与退避重试。
  6. 幂等重试:网络超时时,请使用相同的 request_id 重发,不会重复扣费。
  7. 上游异常格式的视频会被平台自动转为浏览器可播放的 H.264 MP4。

附录 A:服务端实现说明

内部内容,不需要发给接入方。

A.1 功能实现状态

功能 状态 说明
提交任务(文生视频) ✅ 已实现 /v1/chat/completions
查询任务(*-status) ✅ 已实现 消息中识别 TASK_ID
参考图 / 首帧图(images) ✅ 已实现 映射为上游 reference_images
取片代理(/koko/content/{id}) ⬜ 待添加 见 A.3,可解决链接过期问题

A.2 New API 侧配置

  • 渠道类型:高级自定义
  • Base URL:http://172.18.0.1:8787
  • 上游路径:http://172.18.0.1:8787/v1/chat/completions
  • 认证:无认证(key 已移到适配层环境变量)
  • 透传请求体:开启
  • 参数覆盖:留空
  • 渠道模型:seedance-2.0、seedance-2.5、minimaxh3,以及 seedance-2.0-status、seedance-2.5-status、minimaxh3-status
  • 计费:按次固定价;*-status 三个模型价格设为 0,否则每次轮询都会扣一整次视频费用

A.3 取片代理端点(待添加,推荐)

上游的 VIDEO_URL 是临时签名链接,客户侧体验差。加一个代理端点即可提供稳定取片:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from fastapi.responses import StreamingResponse

@app.get("/koko/content/{task_id}")
async def content(task_id: str):
client = httpx.AsyncClient(timeout=300)
req = client.build_request(
"GET", f"{KOKO_BASE}/videos/{task_id}/content",
headers={"Authorization": f"Bearer {KOKO_KEY}"})
r = await client.send(req, stream=True)
if r.status_code not in (200, 206):
await r.aclose(); await client.aclose()
return fail(502, "CONTENT_FAILED", "取视频失败")
return StreamingResponse(
r.aiter_bytes(),
media_type=r.headers.get("content-type", "video/mp4"),
headers={"Content-Disposition": f'inline; filename="{task_id}.mp4"'})

优势:不需要 key、不受签名过期影响、支持大文件流式传输。

两种用法:

用法 说明
后端转存(推荐) 后端调 http://172.18.0.1:8787/koko/content/{task_id} 下载后转存到自己的存储,对外发自己的永久链接
直接对外 需 nginx 反代 + 额外鉴权,否则视频会裸露在公网

A.4 重启与验证

1
2
systemctl restart koko-adapter
journalctl -u koko-adapter -n 20 --no-pager

附录 B:运维备忘

内部内容,不需要发给接入方。

项目 位置 / 命令
适配层代码 /opt/koko-adapter/koko_adapter.py
上游密钥 /etc/koko-adapter.env(权限 600)
重启 systemctl restart koko-adapter
日志 journalctl -u koko-adapter -f
监听地址 172.18.0.1:8787(baota_net 网关,仅容器可访问)
参考图静态站点 img.20saminos.cn(纯静态,图片放站点根目录)
New API 部署 compose 项目 /www/dk_project/dk_app/newapi/newapi_25CJ,容器 newapi_25cj-new-api-1
⚠️ 防火墙 需放行网桥 br-b5debb1b700d 入站,重启或重载防火墙后会失效(Ubuntu:ufw allow from 172.18.0.0/16 to any port 8787 proto tcp,或在宝塔面板加规则)。更稳的做法是把适配层容器化,走容器互访
⚠️ 密钥轮换 sk-hIIr... 与 koko_live_a23c... 曾明文暴露,需在 New API 和 kokoai 后台分别重建

更新日志

版本 日期 变更
v1.0 2026-09-27 初版:概述、鉴权、模型、提交、查询、示例、错误码、计费、限制
v1.1 2026-09-27 新增「4.4 参考图与首帧图」;补充 VIDEO_URL 临时签名链接说明;错误码表新增 4 项参考图相关;新增附录 A.3 取片代理端点