customer-api.md,一键投喂给 Claude Code / Codex,
即可直接调用视频生成 API,无需手动对照文档写代码。
视频生成 API 使用说明(凭证用户版)
本文档面向持有视频凭证(卡密 XXXX-XXXX-XXXX 或 dbk_ 开头的 API Key)的开发者。
用 HTTP 接口提交视频生成任务、查询进度、下载成片,与网页端 https://alliex.space/user 走的是同一套后端。
下文所有「输入 / 输出示例」均来自真实 API 实测(2026-08-14,图转视频·多角色 @参考图)。
- 服务地址:
https://alliex.space - 数据格式:JSON(参考图上传用
multipart/form-data) - 认证:
Authorization: Bearer <凭证>,卡密与 API Key 用法完全相同
没有凭证?找管理员(微信号:xin_1696891425开通即可。凭证即「次数」,每次成功出片扣 1 次。
1. 快速开始(curl 三步)
BASE=https://alliex.space
CRED=XXXX-XXXX-XXXX # 换成你的卡密或 dbk_ API Key
# ① 提交文转视频任务
curl -s $BASE/api/video \
-H "Authorization: Bearer $CRED" -H "Content-Type: application/json" \
-d '{"prompt":"一只小猫追蝴蝶,阳光下的草地","ratio":"9:16","duration":10,"mode":"t2v"}'
# ② 用返回的 job id 查状态(等待 status=done)
curl -s $BASE/api/video/<job_id> -H "Authorization: Bearer $CRED"
# ③ 查出片(命中该会话素材),再下载
curl -s -X POST $BASE/api/video/<job_id>/query -H "Authorization: Bearer $CRED"
curl -s -o out.mp4 "$BASE/api/assets/media/job/<job_id>?item=0&filename=out.mp4" \
-H "Authorization: Bearer $CRED"
# ④ 随时查剩余次数
curl -s $BASE/api/card/info -H "Authorization: Bearer $CRED"提交后立即返回任务(status=queued),后台自动受理并生成,最终 done 或 error。
期间用 GET /api/video/{id} 轮询,不用重复提交。
2. 额度说明(冻结制)
额度 = 凭证还能生成几次视频;生成图片按张计费(0.02 额度 / 张),所以额度可以有两位小数。
| 概念 | 说明 |
|---|---|
quota | 总额度里的整数视频次数(管理员分配;保留给旧客户端读取) |
quota_display | 总额度(含小数零头,如 8.5)——展示请用它 |
used | 已成功出片的次数 + 已生成图片折算的额度(可能有小数) |
reserved | 冻结中(已提交、尚未出片的额度) |
remaining | 剩余可提交额度 = quota_display − used − reserved |
- 提交任务时按
count先冻结额度;任务成功出片 → 扣 1 次;失败 / 取消 → 自动退回。 - 冻结中的额度不可再提交(避免重复占用)。
- 额度不足 →
403,提示「剩余 X 次,本次需 N 次」。 remaining < 1时提交不了视频(不足一次),但仍可能够生成图片。
真实输出(实测:提交 1 个任务后查询):
{
"ok": true,
"code": "dbk_11cb9459",
"quota": 5,
"quota_display": 5,
"used": 0,
"reserved": 1,
"remaining": 4,
"status": "active",
"created": 1786691041,
"last_used": null,
"kind": "api"
}code是脱敏前缀(只显示前 10 位);reserved: 1表示刚提交的 1 个任务正在冻结;出片成功后会变成used: 1、reserved: 0。
只有整数额度时quota_display与quota相同(都是整数);管理员设过小数额度时两者才不同(如quota: 8而quota_display: 8.5)。
常见误解:提交后刷新网页 / 断开请求,任务依然在服务端继续生成,额度照常冻结,不会「白嫖」——退款只会因任务最终失败而触发。
3. 接口总览
| 接口 | 说明 |
|---|---|
POST /api/video | 提交视频生成 |
GET /api/video/{id} | 查任务状态(仅自己的任务) |
POST /api/video/{id}/query | 手动查出片(仅自己的任务) |
GET /api/jobs | 自己的任务列表 |
GET /api/card/info | 查本凭证额度 |
POST /api/upload / POST /api/upload-zip | 上传参考图(.zip 批量) |
GET /api/refs / DELETE /api/refs | 参考图列表 / 清空(仅自己的图) |
GET /api/preview | 参考图预览缩略图 |
GET /api/assets/media/job/{job_id} | 按任务 ID 播放 / 下载素材 |
POST /api/assets/pack/job/{job_id} | 按任务 ID 打包素材 ZIP |
POST /api/jobs/{id}/restore | 任务「重新生成」:回档该任务的提示词与参考图 |
POST /api/jobs/{id}/hide / POST /api/jobs/hide-all | 软删除任务卡片(从列表隐藏,任务本体保留) |
GET /api/archives / POST /api/archives | 存档库:列出 / 保存配置(按凭证隔离) |
POST /api/archives/{id}/restore | 回档存档(提示词 + 参考图原样恢复) |
DELETE /api/archives/{id} / DELETE /api/archives | 删除单个 / 清除全部存档 |
所有素材下载都走「按任务 ID」代理,上游源地址不暴露给客户端。
4. POST /api/video —— 提交视频生成
请求体(JSON)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
prompt | string | ✅ | 提示词。超过 5000 字会被拒绝(除非 nolimit: true) |
mode | string | 二选一:t2v 文转视频(不带参考图)/ r2v 图转视频(必须带 images);不传或传其它值 → 按是否带图自动判断 | |
model | string | 视频模型标识,当前固定 doubao-seedance-2-5-260628(默认);不传即用当前模型,传其它值一律忽略。响应不返回 model 字段 | |
images | array | 图转视频 | [{"store_uri":"…","name":"a.png","account":0}],由 /api/upload 获得 |
ratio | string | 画面比例:16:9 / 21:9 / 9:16 / 4:3 / 1:1,默认 9:16 | |
duration | int | 3–30 秒,默认 5 | |
count | int | 一次提交 N 个独立任务(各开新会话),1–10,默认 1,按此数冻结额度 | |
nolimit | bool | true 跳过 5000 字上限校验 | |
two_step | bool | 两段式(先图后指令)暂未开放:传 true 也会被忽略,按一步式处理 |
示例一:文转视频(t2v)
请求体(JSON):
{
"prompt": "夕阳下的海边,海浪拍打礁石",
"ratio": "9:16",
"duration": 10,
"mode": "t2v",
"count": 2
}示例二:图转视频(r2v,多角色 @参考图 引用)—— 本次真实实测
先上传 5 张参考图(见第 7 节),拿到各自的 store_uri 后,请求体:
{
"prompt": "30秒音乐跳舞视频,16:9,先是个人solo,出场顺序为第一 @参考图4【D】 、第二 @参考图3【C】 、第三 @参考图1【A】 ,然后 @参考图2【B】 @参考图5【E】 同时出场。最后 @参考图1【A】 和 @参考图2【B】 分别牵着 @参考图4【D】 和 @参考图3【C】 的手一起跳起来",
"ratio": "16:9",
"duration": 30,
"mode": "r2v",
"count": 1,
"images": [
{ "store_uri": "tos-cn-i-a9rns2rl98/053569abe5ca4db5b410121c9ad40b44.png", "name": "A.png", "account": 0 },
{ "store_uri": "tos-cn-i-a9rns2rl98/cd38141b2a0044e1a47b621cc1a7a0e1.png", "name": "B.png", "account": 0 },
{ "store_uri": "tos-cn-i-a9rns2rl98/067674a008234440a46b3b97198e8f3c.png", "name": "C.png", "account": 0 },
{ "store_uri": "tos-cn-i-a9rns2rl98/17a12e2112824eddbf02994254d2ec8c.png", "name": "D.png", "account": 0 },
{ "store_uri": "tos-cn-i-a9rns2rl98/5f775b8a6d0e4ef28ea50ae6037b9f76.png", "name": "E.png", "account": 0 }
]
}提示词里的@参考图1【A】…@参考图5【E】与images数组一一对应(第 1 张 = A,第 5 张 = E)。多角色场景把每张图的「角色编号 + 文件名」写进提示词即可。
响应(真实实测)
{
"jobs": [
{
"id": "8ef298d3abab",
"status": "queued",
"prompt": "30秒音乐跳舞视频,16:9,先是个人solo,出场顺序为第一 @参考图4【D】 、第二 @参考图3【C】 、第三 @参考图1【A】 ,然后 @参考图2【B】 @参考图5【E】 同时出场。最后 @参考图1【A】 和 @参考图2【B】 分别牵着 @参考图4【D】 和 @参考图3【C】 的手一起跳起来",
"ratio": "16:9",
"duration": 30,
"mode": "r2v",
"image_uris": [
"tos-cn-i-a9rns2rl98/eca87887a4e4487b9816b9213607f83f.png",
"tos-cn-i-a9rns2rl98/4078242fe44a418ebf5504f7f4938482.png",
"tos-cn-i-a9rns2rl98/e7d4f9ae0e2f481486dc3eff1eb8aada.png",
"tos-cn-i-a9rns2rl98/0a4cacf8f77c4fd98bee7e2414b8f6d4.png",
"tos-cn-i-a9rns2rl98/2c79e935999d472ea582e1c9a80dc34e.png"
],
"image_names": ["A.png", "B.png", "C.png", "D.png", "E.png"],
"image_name": null,
"created": 1786691107,
"done_at": null,
"progress": "",
"error": null,
"detail": "任务已排队",
"attempts": 0
}
]
}注意:任务里的image_uris是服务端把参考图重绑到实际出片账号后的新 TOS URI,与第 7 节上传响应返回的store_uri不一定相同——这是正常的,客户端不要用上传时的store_uri去比对任务里的image_uris。任务里只透出白名单字段(无model/conversation_id/url等内部字段)。
常见错误
{ "error": "prompt 不能为空" } // 400
{ "error": "server_busy" } // 409 服务器额度繁忙,稍后重试
{ "error": "卡密剩余额度不足(剩余 X 次,本次需 N 次)" } // 403
{ "error": "凭证无效" } // 401错误码速查(繁忙 / 账号类失败)
服务器繁忙、账号不可用这类失败,error 与 detail 字段返回机器可读错误码(无中文文案),便于程序判断后处理:
| 错误码 | 含义 | 建议处理 |
|---|---|---|
server_busy | 服务器额度繁忙(所有账号都在生成或今日额度用完) | 稍后重试 |
account_busy | 指定账号正在生成视频 | 稍后重试 |
account_quota_exhausted | 指定账号今日额度已用完 | 换账号或明日再试 |
group_busy | 所选小组暂无可用账号 | 稍后重试 / 换组 |
no_account | 服务器无可用账号 | 联系管理员 |
其余失败(额度不足、版权、参数错误、超时等)error / detail 仍为中文说明。
5. GET /api/video/{id} —— 查任务状态
curl -s $BASE/api/video/<job_id> -H "Authorization: Bearer $CRED"任务状态机:
queued → accepting → generating → done | error| 状态 | 含义 |
|---|---|
queued | 已受理,排队中 |
accepting | 正在提交到生成服务 |
generating | 生成中(通常需要几分钟) |
done | 已出片 |
error | 失败(见 error 字段说明,额度已退回) |
真实输出一:生成中(generating)
{
"id": "8ef298d3abab",
"status": "generating",
"prompt": "30秒音乐跳舞视频,16:9,先是个人solo,出场顺序为第一 @参考图4【D】 、第二 @参考图3【C】 、第三 @参考图1【A】 ,然后 @参考图2【B】 @参考图5【E】 同时出场。最后 @参考图1【A】 和 @参考图2【B】 分别牵着 @参考图4【D】 和 @参考图3【C】 的手一起跳起来",
"ratio": "16:9",
"duration": 30,
"mode": "r2v",
"image_uris": [ "…(同上,5 个)…" ],
"image_names": ["A.png", "B.png", "C.png", "D.png", "E.png"],
"image_name": null,
"created": 1786691107,
"done_at": null,
"progress": "视频正在生成中,耐心等待",
"error": null,
"detail": "已受理,正在生成视频",
"attempts": 1
}真实输出二:已出片(done,本次实测用时 7 分 35 秒)
{
"id": "8ef298d3abab",
"status": "done",
"prompt": "30秒音乐跳舞视频,16:9,先是个人solo,出场顺序为第一 @参考图4【D】 、第二 @参考图3【C】 、第三 @参考图1【A】 ,然后 @参考图2【B】 @参考图5【E】 同时出场。最后 @参考图1【A】 和 @参考图2【B】 分别牵着 @参考图4【D】 和 @参考图3【C】 的手一起跳起来",
"ratio": "16:9",
"duration": 30,
"mode": "r2v",
"image_uris": [ "…(同上,5 个)…" ],
"image_names": ["A.png", "B.png", "C.png", "D.png", "E.png"],
"image_name": null,
"created": 1786691107,
"done_at": 1786691562,
"progress": "视频成功生成,本次用时:7分钟35秒,点击右下角查询按钮获取视频",
"error": null,
"detail": "视频已生成",
"attempts": 1
}detail为当前阶段状态说明(如生成中显示「已受理,正在生成视频」),仅作展示;判断任务请以status为准,不要解析detail文案。
出片后任务列表GET /api/jobs返回同样的字段结构(jobs数组包裹)。
6. POST /api/video/{id}/query —— 查出片 + 下载
任务进入 generating 一段时间后即可主动查出片,命中后自动置 done:
curl -s -X POST $BASE/api/video/<job_id>/query -H "Authorization: Bearer $CRED"未出片时:
{ "ok": false, "error": "暂未查询到该任务视频,请耐心等待或者重新提交" }命中后(真实实测:本次任务出片 1 个 1280×720 视频):
{
"ok": true,
"video_items": [
{
"type": "video",
"name": "video.mp4",
"node_id": "52603089981680386",
"key": "v0269cg10004d9vburi7dldfo4tpdu40",
"message_id": "52601107523635458",
"conversation_id": "38437745109779458",
"duration": 30.042,
"create_time": 1786691502,
"ai_skill_status": 0,
"width": 1280,
"height": 720,
"account_index": 32,
"has_src": true,
"has_cover": true,
"ext": ".mp4"
}
],
"total": 1,
"items": [ "…(与 video_items 同结构)…" ]
}items数组下标与后续素材代理的item参数一一对应。has_src标记该素材可下载,ext是扩展名。node_id/key/message_id/conversation_id/create_time/ai_skill_status/account_index为服务端内部标识,客户端不需要使用,下载 / 打包只认items下标。
下载素材
# 下载第 0 个素材(带文件名 → 浏览器/工具会存成文件)
curl -s -o out.mp4 "$BASE/api/assets/media/job/<job_id>?item=0&filename=out.mp4" \
-H "Authorization: Bearer $CRED"
# 取封面(kind=cover;无封面回退素材本体)
curl -s -o cover.jpg "$BASE/api/assets/media/job/<job_id>?item=0&kind=cover&filename=cover.jpg" \
-H "Authorization: Bearer $CRED"
# 打包素材为一个 ZIP(items 可加多项,本次实测只打 1 个视频)
curl -s -X POST $BASE/api/assets/pack/job/<job_id> \
-H "Authorization: Bearer $CRED" -H "Content-Type: application/json" \
-d '{"items":[{"index":0,"type":"video"}]}' -o all.zip真实输出(本次实测,返回 200 + ZIP 流):
HTTP 200;ZIP 内文件:8ef298d3abab_video_1.mp4(36513771 字节,视频按 STORED 存储)
下载单素材 out.mp4:36513771 字节,合法 MP4(30 秒 1280×720)7. 图转视频:先传参考图
# 单张
curl -s -F "file=@ref.png" $BASE/api/upload -H "Authorization: Bearer $CRED"
# 批量 .zip(压缩包内多张图片)
curl -s -F "file=@refs.zip" $BASE/api/upload-zip -H "Authorization: Bearer $CRED"返回(响应不含 ok 字段,成功以 store_uri 存在为准)。真实实测(A.png,1596779 字节):
{
"store_uri": "tos-cn-i-a9rns2rl98/053569abe5ca4db5b410121c9ad40b44.png",
"name": "A.png",
"size": 1596779,
"account_index": 0
}把 store_uri、account_index 填进 /api/video 的 images:
curl -s $BASE/api/video \
-H "Authorization: Bearer $CRED" -H "Content-Type: application/json" \
-d '{"prompt":"让画面中的人物跳起舞来","mode":"r2v","images":[{"store_uri":"tos-cn-i-a9rns2rl98/053569abe5ca4db5b410121c9ad40b44.png","name":"a.png","account":0}]}'- 单张 ≤30MB;请求体整体 ≤64MB;最多 30 张。
- 参考图按凭证隔离,只自己可见;
GET /api/refs可查、DELETE /api/refs可清空。
8. Python 客户端
仓库内 api_client.py 同时提供命令行与库两种用法。
命令行(提交并自动等待出片,快速测试)
python api_client.py --base https://alliex.space --api-key XXXX-XXXX-XXXX \
--prompt "一只小猫追蝴蝶" --ratio 9:16 --duration 10 --mode t2v命令行提交后会自动等待出片。注意凭证用户拿不到直链,下载成片请用下面的库模式(query()+download_asset())。
库模式(推荐,可逐步控制)
import asyncio
from api_client import VideoGenAPI
async def main():
api = VideoGenAPI(base_url="https://alliex.space", api_key="XXXX-XXXX-XXXX")
# 提交文转视频,拿到任务
jobs = await api.submit("一只小猫追蝴蝶", ratio="9:16", duration=10, mode="t2v")
job_id = jobs[0]["id"]
# 轮询直到出片 / 失败(默认最多等 35 分钟)
job = await api.wait_for_done(job_id)
if job.get("status") != "done":
print("任务失败:", job.get("error"))
return
# 查出片并下载第 0 个素材
await api.query(job_id)
await api.download_asset(job_id, item=0, out_path="out.mp4")
asyncio.run(main())网络环境 TLS 被重置时:用 curl_cffi 模拟浏览器指纹
个别网络链路(海外访问 / 运营商 / 企业防火墙)会对「非浏览器 TLS 指纹」的连接做重置,普通 curl / httpx 可能报 Recv failure: Connection was reset / SSL: UNEXPECTED_EOF_WHILE_READING。服务端接受标准 TLS 1.2/1.3、不挑客户端(curl、openssl、浏览器均验证通过),上述现象是链路中间设备的指纹干扰,可用 curl_cffi 模拟 Chrome 指纹绕过:
from curl_cffi import requests
from curl_cffi import CurlMime
s = requests.Session(impersonate="chrome") # 模拟 Chrome TLS 指纹
BASE = "https://alliex.space"
H = {"Authorization": "Bearer XXXX-XXXX-XXXX"}
# 提交文转视频(json= 用法同 requests)
r = s.post(f"{BASE}/api/video", headers=H,
json={"prompt": "一只小猫追蝴蝶", "ratio": "9:16", "duration": 10, "mode": "t2v"})
# 上传参考图:curl_cffi 的 multipart 必须传 CurlMime() 对象,不能用普通 dict / files=
mime = CurlMime(s)
mime.addpart(name="file", filename="ref.png", local_path="ref.png", content_type="image/png")
r = s.post(f"{BASE}/api/upload", headers=H, multipart=mime)
data = r.json()
store_uri = data.get("store_uri") # 成功以 store_uri 存在为准(响应无 ok 字段)注意:/api/upload、/api/upload-zip的响应不含ok字段,请以返回的store_uri是否存在判断成功。
9. 常见问题
| 问题 | 说明 |
|---|---|
| 提交后额度被冻结,任务失败了会退回吗 | 会。失败 / 取消 / 服务中断都会自动退回冻结额度 |
一直显示 generating | 生成通常需几分钟;超 35 分钟会自动判失败并退回额度,刷新(Ctrl+F5)看最新状态 |
| 怎么拿成片 | POST /api/video/{id}/query 查出片后,用素材代理下载(第 6 节) |
| 任务列表在哪 | GET /api/jobs(只返回自己凭证创建的任务) |
| 想重新用某次的提示词 / 参考图 | POST /api/jobs/{id}/restore 回档到表单,或存档库 POST /api/archives 手动存一份 |
| 凭证被禁用 / 吊销 | 新提交返回 401;服务端会取消该凭证所有在途任务并退回冻结额度 |
count 能多大 | 1–10(网页端按钮组最多 4,API 可到 10,按实际次数冻结额度) |
为什么任务里 image_uris 跟上传时返回的 store_uri 不一样 | 服务端把参考图重绑到实际出片账号,URI 会变;只用于展示,不影响出片 |
curl / httpx 连不上,报 SSL 被重置 / UNEXPECTED_EOF_WHILE_READING | 服务端不限制客户端类型;多为网络链路对非浏览器 TLS 指纹的干扰。用 curl_cffi 的 impersonate="chrome" 即可(完整示例见第 8 节) |
上传接口没有 ok 字段 | 正常——上传成功以返回的 store_uri 是否存在判断,不要用 data.get("ok") 判断 |