Appearance
Huifa Seedance 视频生成 API 调用指南
面向 Huifa 平台调用方。本文档说明如何调用 seedance 系列视频生成模型。 调用方使用 OpenAI 风格的视频协议。
基本信息
| 项 | 值 |
|---|---|
| 服务域名 | https://huifa.one-connect.cn |
| 鉴权 | Authorization: Bearer <Huifa 令牌 sk-xxx>(在站点「令牌」页面创建) |
| 协议风格 | OpenAI 视频 API(异步任务:创建 → 轮询) |
| 支持模型 | doubao-seedance-2-0-260128 |
令牌
sk-xxx是你在 Huifa 站点创建的平台令牌。
调用流程
视频生成是异步任务:先创建任务拿到 task_id,再轮询查询直到 status 变为 completed。
POST /v1/video/generations → 返回 task_id (status=queued)
↓ 轮询
GET /v1/video/generations/{id} → status=in_progress ... → completed (metadata.url)1. 创建视频任务
请求
bash
curl https://huifa.one-connect.cn/v1/video/generations \
-X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-你的Huifa令牌" \
-d '{
"model": "doubao-seedance-2-0-260128",
"prompt": "第一人称视角果茶宣传广告,seedance牌「苹苹安安」苹果果茶限定款;全程第一视角构图,背景音乐轻快卡点,女声口播「鲜切现摇」「来一口鲜爽」。",
"seconds": "11",
"metadata": {
"ratio": "16:9",
"generate_audio": true,
"watermark": false,
"content": [
{
"type": "image_url",
"image_url": { "url": "https://你的图床/pic1.jpg" },
"role": "reference_image"
},
{
"type": "image_url",
"image_url": { "url": "https://你的图床/pic2.jpg" },
"role": "reference_image"
},
{
"type": "video_url",
"video_url": { "url": "https://你的图床/video1.mp4" },
"role": "reference_video"
},
{
"type": "audio_url",
"audio_url": { "url": "https://你的图床/audio1.mp3" },
"role": "reference_audio"
}
]
}
}'请求字段
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | string | 是 | 模型名,见上方支持列表 |
prompt | string | 是 | 主提示词,自动作为文本内容注入 |
seconds | string | 否 | 视频时长(秒),对应上游 duration |
metadata | object | 否 | 上游特有参数入口,见下 |
metadata 字段
| 字段 | 类型 | 说明 |
|---|---|---|
ratio | string | 宽高比:16:9 / 9:16 / 1:1 / 4:3 / 3:4 |
generate_audio | bool | 是否生成音频(背景音 + 口播) |
watermark | bool | 是否加水印 |
content | array | 参考素材数组,见下 |
content 数组元素(参考图 / 视频 / 音频)
| 字段 | 说明 |
|---|---|
type | image_url / video_url / audio_url / text |
image_url.url / video_url.url / audio_url.url | 素材公网地址(必须上游可访问,不能是本地文件) |
role | reference_image / reference_video / reference_audio |
⚠️ 必填项提醒:上游要求
ratio、generate_audio、watermark必须传(放在metadata里)。若遗漏,会收到错误调试执行失败: 插件缺少必要输入参数。即使不需要音频/水印,也要显式传"generate_audio": false、"watermark": false。
响应
json
{
"id": "task-xxxxxxxx",
"task_id": "task-xxxxxxxx",
"object": "video",
"model": "doubao-seedance-2-0-260128",
"status": "queued",
"created_at": 1751180000
}记下 task_id 用于轮询。
2. 轮询查询结果
请求
bash
curl https://huifa.one-connect.cn/v1/video/generations/task-xxxxxxxx \
-H "Authorization: Bearer sk-你的Huifa令牌"进行中
json
{
"task_id": "task-xxxxxxxx",
"status": "IN_PROGRESS",
"progress": "50%"
}已完成(实测样例,字段已省略部分)
json
{
"task_id": "task-xxxxxxxx",
"status": "SUCCESS",
"progress": "100%",
"result_url": "https://ark-acg-cn-beijing.tos-cn-beijing.volces.com/....mp4?X-Tos-...",
"finish_time": 1782789150
}生成的视频地址在顶层
result_url字段。它是火山对象存储的签名链接,有效期 24 小时,过期需重新查询任务获取新链接,或提前转存。注意:返回 JSON 中
result_url里的&是&的 JSON 转义,程序解析后会自动还原;若手动复制到浏览器,需把&替换成&。
失败
json
{
"task_id": "task-xxxxxxxx",
"status": "FAILURE",
"fail_reason": "失败原因"
}status 取值
| status | 含义 |
|---|---|
QUEUED | 排队中 |
IN_PROGRESS | 生成中 |
SUCCESS | 完成,视频地址在 result_url |
FAILURE | 失败,原因在 fail_reason |
建议轮询间隔 5~10 秒,直到 SUCCESS 或 FAILURE。
若改用 OpenAI 兼容入口
GET /v1/videos/{task_id}(见第 3 节),返回结构略有不同:status 为小写(completed/failed),视频地址在metadata.url。两个入口取其一即可。
3. OpenAI 官方兼容入口(可选)
如果你的客户端基于 OpenAI 官方 videos API,可改用以下入口,请求/响应结构一致:
bash
# 创建
curl https://huifa.one-connect.cn/v1/videos \
-X POST -H "Authorization: Bearer sk-你的Huifa令牌" \
-H "Content-Type: application/json" \
-d '{ "model": "doubao-seedance-2-0-260128", "prompt": "...", "seconds": "11" }'
# 查询
curl https://huifa.one-connect.cn/v1/videos/task-xxxxxxxx \
-H "Authorization: Bearer sk-你的Huifa令牌"4. 豆包(火山 Ark)原生入口(可选,推荐已有豆包代码的用户)
如果你已经有调用火山引擎 seedance 的代码或 SDK(火山官方 content 数组格式),不想改造成 Huifa 的 prompt/seconds 风格,可以直接用这个入口——请求体与火山官方完全一致,只需把 base_url 指向 https://huifa.one-connect.cn/doubao、把 key 换成 Huifa 令牌即可。
端点路径与火山官方一致(
/api/v3/contents/generations/tasks),仅多了/doubao前缀。仅支持doubao-seedance-*系列模型。
bash
# 创建(火山原生 content 数组格式)
curl https://huifa.one-connect.cn/doubao/api/v3/contents/generations/tasks \
-X POST -H "Authorization: Bearer sk-你的Huifa令牌" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seedance-2-0-260128",
"content": [
{ "type": "text", "text": "一只猫在跳舞" },
{ "type": "image_url", "image_url": { "url": "https://你的图床/pic1.jpg" }, "role": "reference_image" }
],
"ratio": "16:9",
"duration": 11,
"generate_audio": true,
"watermark": false
}'
# 查询(task_id 走 URL 路径,同火山官方)
curl https://huifa.one-connect.cn/doubao/api/v3/contents/generations/tasks/task-xxxxxxxx \
-H "Authorization: Bearer sk-你的Huifa令牌"请求体:与火山官方 content_generation.tasks.create 的 body 完全一致(model + content[] + ratio/duration/resolution/generate_audio/watermark/seed/camera_fixed 等扁平参数)。提示词放在 content 数组的 type:"text" 项里,时长用 duration(整数)。
⚠️ 与前两个入口不同点:响应仍是 Huifa 的任务格式(不是火山原生响应)。创建返回
{id, task_id, status:"queued", ...};查询返回{status, result_url, ...},视频地址在顶层result_url。也就是说"请求体保持豆包原生、响应按 Huifa 格式解析"。
generate_audio/watermark未显式传时,网关会自动补false(上游必填),但建议你显式传入。
5. 完整轮询示例
Python
python
import time
import requests
BASE_URL = "https://huifa.one-connect.cn"
API_KEY = "sk-你的Huifa令牌"
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
def create_video_task() -> str:
"""创建视频任务,返回 task_id。"""
payload = {
"model": "doubao-seedance-2-0-260128",
"prompt": "第一人称视角果茶宣传广告,seedance牌「苹苹安安」苹果果茶限定款。",
"seconds": "11",
"metadata": {
"ratio": "16:9",
"generate_audio": True,
"watermark": False,
"content": [
{"type": "image_url", "image_url": {"url": "https://你的图床/pic1.jpg"}, "role": "reference_image"},
{"type": "video_url", "video_url": {"url": "https://你的图床/video1.mp4"}, "role": "reference_video"},
],
},
}
resp = requests.post(f"{BASE_URL}/v1/video/generations", headers=HEADERS, json=payload, timeout=30)
resp.raise_for_status()
return resp.json()["task_id"]
def poll_video_task(task_id: str, interval: int = 8, max_wait: int = 600) -> dict:
"""轮询任务直到完成或失败。interval 秒/次,max_wait 秒超时。"""
deadline = time.time() + max_wait
while time.time() < deadline:
resp = requests.get(f"{BASE_URL}/v1/video/generations/{task_id}", headers=HEADERS, timeout=30)
resp.raise_for_status()
data = resp.json()
status = data.get("status")
print(f"status={status} progress={data.get('progress', '0%')}")
if status == "SUCCESS":
return data
if status == "FAILURE":
raise RuntimeError(f"任务失败: {data.get('fail_reason', '未知原因')}")
time.sleep(interval)
raise TimeoutError(f"任务 {task_id} 超过 {max_wait}s 未完成")
if __name__ == "__main__":
task_id = create_video_task()
print(f"任务已创建: {task_id}")
result = poll_video_task(task_id)
print("视频地址:", result.get("result_url"))Node.js
javascript
const BASE_URL = 'https://huifa.one-connect.cn'
const API_KEY = 'sk-你的Huifa令牌'
const HEADERS = {
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
}
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
async function createVideoTask() {
const payload = {
model: 'doubao-seedance-2-0-260128',
prompt: '第一人称视角果茶宣传广告,seedance牌「苹苹安安」苹果果茶限定款。',
seconds: '11',
metadata: {
ratio: '16:9',
generate_audio: true,
watermark: false,
content: [
{ type: 'image_url', image_url: { url: 'https://你的图床/pic1.jpg' }, role: 'reference_image' },
{ type: 'video_url', video_url: { url: 'https://你的图床/video1.mp4' }, role: 'reference_video' },
],
},
}
const resp = await fetch(`${BASE_URL}/v1/video/generations`, {
method: 'POST',
headers: HEADERS,
body: JSON.stringify(payload),
})
if (!resp.ok) throw new Error(`创建失败: ${resp.status} ${await resp.text()}`)
return (await resp.json()).task_id
}
async function pollVideoTask(taskId, { interval = 8000, maxWait = 600000 } = {}) {
const deadline = Date.now() + maxWait
while (Date.now() < deadline) {
const resp = await fetch(`${BASE_URL}/v1/video/generations/${taskId}`, { headers: HEADERS })
if (!resp.ok) throw new Error(`查询失败: ${resp.status} ${await resp.text()}`)
const data = await resp.json()
console.log(`status=${data.status} progress=${data.progress ?? '0%'}`)
if (data.status === 'SUCCESS') return data
if (data.status === 'FAILURE') throw new Error(`任务失败: ${data.fail_reason ?? '未知原因'}`)
await sleep(interval)
}
throw new Error(`任务 ${taskId} 超过 ${maxWait}ms 未完成`)
}
;(async () => {
const taskId = await createVideoTask()
console.log(`任务已创建: ${taskId}`)
const result = await pollVideoTask(taskId)
console.log('视频地址:', result.result_url)
})()常见问题
Q: 参考素材能传本地文件吗? 不能。url 必须是上游可公网访问的地址(如对象存储 / 图床)。
Q: 计费怎么算? 按生成视频的 token 量计费(分辨率 × 帧率 × 时长相关)。
