视频生成完整指南
本指南介绍如何使用 宁享Token 的视频生成 API 从零完成一次视频生成,涵盖模型选择、素材准备、任务创建、状态查询、结果获取全流程。
总体流程
1. 选择模型 → 根据需求选择合适的视频模型
2. 准备素材(可选) → 上传参考图、首尾帧、音频等素材
3. 创建任务 → 调用 POST /v1/video/generations
4. 查询状态 → 轮询 GET /v1/video/generations/{task_id}
5. 获取结果 → 从 status=completed 的任务中取 metadata.url 下载视频第 1 步:选择模型
根据需求选择合适的视频模型:
| 模型 | 厂商 | 文生视频 | 图生视频 | 首尾帧 | 音频驱动 | 最大时长 |
|---|---|---|---|---|---|---|
doubao-seedance-2-0 | 字节火山 | ✅ | ✅ | ✅ | ✅ | 10 秒 |
kling-3.0 | 快手可灵 | ✅ | ✅ | ✅ | ❌ | 10 秒 |
kling-3.0-turbo | 快手可灵 | ✅ | ✅ | ❌ | ❌ | 5 秒 |
happyhorse-1.1-t2v | 阿里云 | ✅ | ❌ | ✅ | ✅ | 15 秒 |
wan2.7-t2v(已下架/暂未开放) | 阿里云 | ✅ | ❌ | ✅ | ✅ | 15 秒 |
kling-2.5-turbo | 快手可灵 | ✅ | ✅ | ❌ | ❌ | 5 秒 |
详见 视频模型清单。
第 2 步:准备素材(可选)
如果需要图生视频或首尾帧控制,需先准备参考素材。宁享Token 支持以下素材输入方式:
方式一:URL 引用
直接在请求中使用公开可访问的图片 URL:
json
{
"model": "doubao-seedance-2-0",
"prompt": "让这张图片动起来",
"image": {
"url": "https://example.com/input.jpg"
}
}方式二:素材库上传
通过素材管理 API 上传素材,获取素材 ID 后在视频生成任务中引用:
bash
# 1. 上传素材
curl -X POST /api/assets \
-H "Authorization: Bearer $TOKEN" \
-F "file=@/path/to/image.jpg" \
-F "asset_type=image"
# 响应:
# { "id": "asset_xxx", "url": "https://..." }详见 素材管理 API。
第 3 步:创建任务
文生视频
bash
curl -X POST /v1/video/generations \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-3.0",
"prompt": "夕阳下的城市天际线,延时摄影风格,镜头从远处推近",
"duration": 5,
"resolution": "1080p"
}'响应:
json
{
"id": "task_abc123",
"object": "video",
"status": "queued",
"model": "kling-3.0",
"created_at": 1735660800
}图生视频(Seedance 示例)
bash
curl -X POST /v1/video/generations \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seedance-2-0",
"prompt": "镜头缓慢拉近,人物微笑",
"image": {
"url": "https://example.com/character.jpg"
},
"duration": 5,
"resolution": "1080p"
}'首尾帧控制(Sora 示例)
bash
curl -X POST /v1/video/generations \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-3.0",
"prompt": "从白天过渡到黑夜的城市俯瞰",
"first_frame": {
"url": "https://example.com/day.jpg"
},
"last_frame": {
"url": "https://example.com/night.jpg"
},
"duration": 10,
"resolution": "1080p"
}'音频驱动(Seedance 示例)
bash
curl -X POST /v1/video/generations \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seedance-2-0",
"prompt": "数字人说话",
"image": {
"url": "https://example.com/avatar.jpg"
},
"audio": {
"url": "https://example.com/speech.mp3"
},
"duration": 5
}'第 4 步:查询状态
视频生成是异步任务,需轮询任务状态:
bash
curl /v1/video/generations/task_abc123 \
-H "Authorization: Bearer $TOKEN"任务状态流转:
| status | 含义 |
|---|---|
queued | 任务排队中 |
in_progress | 生成中 |
completed | 生成成功 |
failed | 生成失败 |
cancelled | 已取消 |
轮询示例(Python)
python
import time
import requests
API_BASE = "/v1"
TOKEN = "<YOUR_API_KEY>"
TASK_ID = "task_abc123"
headers = {"Authorization": f"Bearer {TOKEN}"}
while True:
resp = requests.get(f"{API_BASE}/videos/generations/{TASK_ID}", headers=headers)
data = resp.json()
status = data["status"]
print(f"状态: {status}")
if status == "completed":
print("视频 URL:", data["metadata"]["url"])
break
elif status == "failed":
print("生成失败:", data.get("error", "未知错误"))
break
time.sleep(5) # 每 5 秒轮询一次轮询示例(Node.js)
javascript
const API_BASE = "/v1";
const TOKEN = process.env.TOKEN;
const TASK_ID = "task_abc123";
const headers = { Authorization: `Bearer ${TOKEN}` };
async function poll() {
while (true) {
const resp = await fetch(`${API_BASE}/videos/generations/${TASK_ID}`, { headers });
const data = await resp.json();
console.log(`状态: ${data.status}`);
if (data.status === "completed") {
console.log("视频 URL:", data.metadata.url);
break;
} else if (data.status === "failed") {
console.log("生成失败:", data.error);
break;
}
await new Promise((r) => setTimeout(r, 5000));
}
}
poll();第 5 步:获取结果
任务成功后,从 metadata.url 下载视频:
python
import requests
video_url = "https://..." # 从任务结果获取
resp = requests.get(video_url)
with open("output.mp4", "wb") as f:
f.write(resp.content)成功响应示例:
json
{
"id": "task_abc123",
"object": "video",
"status": "completed",
"model": "kling-3.0",
"created_at": 1735660800,
"completed_at": 1735660860,
"metadata": {
"url": "https://...",
"duration": 5,
"resolution": "1080p",
"format": "mp4"
},
"usage": {
"completion_tokens": 108900,
"total_tokens": 108900
}
}完整流程示例(Python)
python
import time
import requests
API_BASE = "/v1"
TOKEN = "<YOUR_API_KEY>"
headers = {"Authorization": f"Bearer {TOKEN}"}
# 1. 创建任务
resp = requests.post(
f"{API_BASE}/videos/generations",
headers=headers,
json={
"model": "doubao-seedance-2-0",
"prompt": "夕阳下的城市天际线,延时摄影风格",
"image": {"url": "https://example.com/scene.jpg"},
"duration": 5,
"resolution": "1080p",
},
)
task = resp.json()
task_id = task["id"]
print(f"任务已创建: {task_id}")
# 2. 轮询状态
while True:
resp = requests.get(f"{API_BASE}/videos/generations/{task_id}", headers=headers)
data = resp.json()
status = data["status"]
print(f"状态: {status}")
if status == "completed":
# 3. 下载视频
video_url = data["metadata"]["url"]
video_resp = requests.get(video_url)
with open("output.mp4", "wb") as f:
f.write(video_resp.content)
print(f"视频已下载: output.mp4")
break
elif status == "failed":
print(f"失败: {data.get('error')}")
break
time.sleep(5)最佳实践
轮询频率
- 建议 5~10 秒轮询一次
- 避免过于频繁,以免触发速率限制
- 可使用指数退避:首次 5 秒,每次失败后增加 2 秒
任务超时
- 不同模型生成时间不同,通常 30~180 秒
- 建议客户端设置 5 分钟超时
- 任务是否计费以厂商官方返回的计费信息为准
错误处理
| 错误 | 排查 |
|---|---|
| 400 图片格式不支持 | 转换为 JPG / PNG |
| 400 图片尺寸过大 | 压缩至 2MB 以内 |
| 400 duration 超限 | 检查模型支持的最大时长 |
| 401 Key 无效 | 检查 API Key |
| 429 超出并发限制 | 降低并发或联系客服 |
| 500 生成失败 | 重试;是否计费以厂商官方返回的计费信息为准 |
计费
- 视频生成按模型分别采用按次 / 按秒档 / 按 token 计费(可灵系按秒档、Seedance 系按 token),以定价总表为准
- 价格随模型、时长、分辨率不同,详见 定价总表
- 计费以厂商官方返回的计费信息为准(见 错误码 · 任务失败会扣费吗)
- 所有费用以 CNY 结算
