BitCloud 视频生成 API 接入文档
目录
1. 快速开始
先调用 GET /v1/models,将下例中的 YOUR_VIDEO_MODEL_ID 替换为当前 API Key 实际可用的完整模型 ID;不要使用未出现在模型列表中的旧名称。
bash# 提交一个视频生成任务
curl -X POST "https://edge.bitcloud.com.cn/v1/videos" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "YOUR_VIDEO_MODEL_ID",
"prompt": "夕阳下的海滩,海浪轻轻拍打,海鸥飞翔",
"seconds": "5"
}'
# 响应
{
"id": "task_abc123",
"task_id": "task_abc123",
"object": "video",
"model": "YOUR_VIDEO_MODEL_ID",
"status": "queued",
"progress": 0,
"created_at": 1781510000
}bash# 轮询查询任务状态
curl -X GET "https://edge.bitcloud.com.cn/v1/videos/task_abc123" \
-H "Authorization: Bearer YOUR_API_KEY"2. 接口列表
| 方法 | 端点 | 说明 |
|---|---|---|
POST | /v1/videos | 提交视频生成任务 |
POST | /v1/video/generations | 提交视频生成任务(请求字段兼容;响应为任务中继信封) |
GET | /v1/videos/{video_id} | 查询任务状态 |
GET | /v1/video/generations/{task_id} | 查询任务状态(兼容别名) |
GET | /v1/videos/{video_id}/content | 获取/下载视频 |
POST | /v1/videos/{video_id}/cancel | 取消任务 |
两个提交端点使用相同的请求结构。新接入推荐使用 /v1/videos,其提交、查询和内容下载接口均采用本文定义的标准视频响应;/v1/video/generations 为任务中继兼容端点,响应使用 code、message 和 data 信封,不应按 /v1/videos 的响应格式解析。
推荐使用 application/json。兼容表单请求不支持把 content 数组原样编码为表单字段;需要传入图片、视频或音频时,请使用 JSON 中的 HTTPS URL。
3. 提交视频生成任务
POST /v1/videos
创建一个新的视频生成任务。支持文生视频、图生视频和视频参考输入。model 决定可用能力;如果所选模型不支持某个显式字段或输入角色,接口会在创建任务前返回 400,不会静默忽略该字段。
请求体
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | string | ✅ | 模型名,见 支持模型 |
prompt | string | ✅ | 视频描述文本 |
content | object[] | ❌ | 统一多媒体输入,支持 image_url / video_url / audio_url 和角色 |
image | string | ❌ | 参考图 URL(图生视频) |
images | string[] | ❌ | 多张参考图 URL |
duration | int | ❌ | 视频时长(秒) |
seconds | string | ❌ | 视频时长(秒),默认 5 |
size | string | ❌ | 分辨率:480p / 720p / 1080p,默认 720p |
ratio | string | ❌ | 画面比例,例如 16:9 / 9:16 / 1:1 |
resolution | string | ❌ | 统一分辨率字段:480p / 720p / 1080p |
style | string | ❌ | 风格,仅在所选模型支持时可用 |
generate_audio | bool | ❌ | 是否生成同步音频 |
seed | int | ❌ | 随机种子 |
width / height | int | ❌ | 明确尺寸,仅在所选模型支持时可用 |
n | int | ❌ | 生成数量;是否支持及上限由模型决定 |
metadata | object | ❌ | 向后兼容参数;只接受本文列出的字段 |
prompt 是唯一的文本语义来源;如果 content 中包含 text item,其内容必须与 prompt 一致。使用 content 时不要再同时传递 image、images、input_reference 或 metadata 中的旧版媒体字段。
示例
文生视频(5 秒,默认 720p):
json{
"model": "YOUR_VIDEO_MODEL_ID",
"prompt": "一只猫咪在樱花树下追蝴蝶,阳光透过花瓣洒落",
"seconds": "5"
}文生视频(10 秒,1080p,16:9):
json{
"model": "YOUR_VIDEO_MODEL_ID",
"prompt": "航拍城市夜景,车辆灯光形成流光",
"duration": 10,
"resolution": "1080p",
"ratio": "16:9",
"seed": 42
}图生视频(单张参考图,5 秒):
json{
"model": "YOUR_VIDEO_MODEL_ID",
"prompt": "让画面中的花朵缓缓绽放,镜头缓慢推进",
"image": "https://example.com/flower.jpg",
"seconds": "5"
}视频参考输入:
json{
"model": "YOUR_VIDEO_MODEL_ID",
"prompt": "保持主体动作,改成电影级夜景",
"duration": 5,
"resolution": "1080p",
"content": [
{
"type": "video_url",
"role": "reference_video",
"video_url": {"url": "https://example.com/input.mp4"}
}
]
}输入视频不必先上传到本服务;只要 HTTPS URL 可被服务读取即可。统一素材库创建的资源使用 asset://ast_...。请只使用素材库接口返回的 URI,不要自行构造或传递其他素材标识。素材管理接口见 素材库与真人认证 API 接入文档。
响应 (200)
json{
"id": "task_DY6gPtt72sJGgzlCTZkbuuNdqtN460O2",
"task_id": "task_DY6gPtt72sJGgzlCTZkbuuNdqtN460O2",
"object": "video",
"model": "YOUR_VIDEO_MODEL_ID",
"status": "queued",
"progress": 0,
"created_at": 1781510000
}| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 任务唯一标识 |
task_id | string | 同 id,用于后续查询 |
object | string | 固定为 "video" |
model | string | 使用的模型 |
status | string | 任务状态:queued / in_progress / completed / failed |
progress | int | 进度 0-100 |
created_at | int | 创建时间戳(Unix 秒) |
4. 查询任务状态
GET /v1/videos/{video_id}
查询视频生成任务的当前进度和结果。
路径参数
| 参数 | 类型 | 说明 |
|---|---|---|
video_id | string | 提交任务时返回的 task_id |
响应示例
处理中:
json{
"id": "task_DY6gPtt72sJGgzlCTZkbuuNdqtN460O2",
"task_id": "task_DY6gPtt72sJGgzlCTZkbuuNdqtN460O2",
"object": "video",
"model": "YOUR_VIDEO_MODEL_ID",
"status": "in_progress",
"progress": 50,
"created_at": 1781510000
}已完成:
json{
"id": "task_DY6gPtt72sJGgzlCTZkbuuNdqtN460O2",
"task_id": "task_DY6gPtt72sJGgzlCTZkbuuNdqtN460O2",
"object": "video",
"model": "YOUR_VIDEO_MODEL_ID",
"status": "completed",
"progress": 100,
"created_at": 1781510000,
"completed_at": 1781510120,
"metadata": {
"url": "https://edge.bitcloud.com.cn/v1/videos/task_DY6gPtt72sJGgzlCTZkbuuNdqtN460O2/content"
}
}任务状态说明
| 状态 | 进度 | 说明 |
|---|---|---|
queued | 0% | 已提交,排队等待 |
in_progress | 0-99% | 正在生成中 |
completed | 100% | 生成成功,metadata.url 可获取视频 |
failed | 100% | 生成失败,error.message 查看原因 |
5. 获取视频内容
GET /v1/videos/{video_id}/content
获取/下载生成的视频文件。该地址始终由 BitCloud 代理返回视频内容,不会返回第三方文件地址。
使用方式
bash# curl 下载
curl "https://edge.bitcloud.com.cn/v1/videos/task_abc123/content" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o output.mp4注意: 仅在任务状态为 completed 时可用。该端点要求 API Key;浏览器地址栏不能自动附带 Bearer Token,请由服务端转发下载,或使用能添加请求头的客户端。6. 取消任务
POST /v1/videos/{video_id}/cancel
取消一个进行中的视频生成任务。仅支持取消能力已开放的模型;取消成功后,已预扣的费用全额退还。
限制
- 不支持取消的任务返回
501 video_cancel_not_supported - 正在生成中的任务(
in_progress)可能无法取消 - 已完成的任务无法取消
响应 (200)
json{
"id": "task_abc123",
"status": "cancelled"
}7. 支持模型
请使用账户中已启用的公开模型 ID。模型的可用时长、分辨率、画面比例、输入类型及计费,以模型广场或账户控制台显示为准;请勿依赖第三方名称、路由规则或内部实现。
8. 计费说明
视频模型可能按秒或按次计费。实际价格由所选模型、账户分组和请求规格共同确定,最终以模型广场和账户账单为准。费用在任务提交时预扣;未成功提交或生成失败时会按结算规则退回。
9. 参数参考
统一 content 角色
type | role | 含义 |
|---|---|---|
image_url | reference_image | 普通参考图 |
image_url | first_frame | 首帧 |
image_url | last_frame | 尾帧 |
video_url | reference_video | 参考/输入视频 |
audio_url | reference_audio | 参考音频 |
不同模型支持的角色不同。显式提供但不支持的角色会返回 unsupported_video_input,不会静默删除。
reference_image 可选传 subject_type,取值为 person、animal 或 object。仅在所选模型支持主体参考时使用;不支持时返回明确的 400。
metadata 向后兼容参数
新接入优先使用顶层 ratio、resolution、generate_audio、seed 和 content。现有客户端仍可使用下列 metadata 别名;示例值不代表每个模型的默认值或可用性:
| 参数 | 类型 | 示例值 | 说明 |
|---|---|---|---|
resolution | string | 720p | 分辨率:480p / 720p / 1080p |
ratio | string | - | 宽高比:16:9 / 4:3 / 1:1 / 9:16 |
duration | int | 5 | 视频时长(秒) |
seed | int | -1 | 随机种子,相同 seed 产生相似结果 |
watermark | bool | false | 是否包含水印 |
generate_audio | bool | true | 是否生成同步音频 |
camera_fixed | bool | - | 固定摄像头视角 |
draft | bool | false | 样片模式(快速预览) |
service_tier | string | online | 服务等级 |
input_mode | string | 自动检测 | 手动指定输入模式 |
metadata 不是任意透传对象。只支持本文列出的兼容字段;未知字段返回 unsupported_video_parameter。
完整请求示例
json{
"model": "YOUR_VIDEO_MODEL_ID",
"prompt": "一个未来城市的全景航拍,赛博朋克风格",
"seconds": "10",
"size": "1080p",
"metadata": {
"ratio": "16:9",
"seed": 12345,
"watermark": false,
"generate_audio": true,
"resolution": "1080p",
"duration": 10
}
}10. 错误处理
错误响应格式
json{
"code": "invalid_request",
"message": "模型服务调用失败",
"data": null
}常见错误码
| 错误码 | HTTP | 说明 | 处理建议 |
|---|---|---|---|
model_price_error | 400 | 当前模型暂不可用 | 联系支持人员 |
invalid_request | 400 | 请求参数有误 | 检查必填字段和参数格式 |
invalid_video_parameter | 400 | 统一视频字段类型错误 | 按参数表修正字段类型 |
unsupported_video_parameter | 400 | 所选模型不支持该参数 | 删除参数或改用支持它的模型 |
unsupported_video_input | 400 | 不支持内容类型、角色或 URL 协议 | 改用 HTTPS URL 或受支持角色 |
unsupported_asset_reference | 400 | 所选模型无法使用该素材 | 使用素材库返回的 asset://ast_...,或使用 HTTPS URL |
unsupported_resolution | 400 | 所选模型不支持该分辨率 | 使用模型支持的分辨率 |
unsupported_ratio | 400 | 所选模型不支持该画面比例 | 使用模型支持的比例 |
unsupported_size | 400 | 所选模型不支持该兼容尺寸 | 改用 resolution、ratio 或模型支持的尺寸 |
insufficient_user_quota | 403 | 额度不足 | 充值或切换模型 |
fail_to_fetch_task | 500 | 视频服务暂时不可用 | 稍后重试 |
build_request_failed | 500 | 请求构建失败 | 检查 metadata 参数类型 |
计费保障
- 提交失败:全额退款,不产生费用
- 任务失败:预扣费自动退回
- 差额结算:任务完成时自动调整实际费用
附录:完整流程示例
pythonimport requests
import time
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://edge.bitcloud.com.cn/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
# 1. 提交任务
resp = requests.post(f"{BASE_URL}/videos", json={
"model": "YOUR_VIDEO_MODEL_ID",
"prompt": "海浪拍打礁石,夕阳余晖洒在海面上",
"seconds": "10",
"size": "1080p",
"metadata": {"ratio": "16:9", "seed": 42}
}, headers=HEADERS)
task = resp.json()
task_id = task["task_id"]
print(f"任务已提交: {task_id}")
# 2. 轮询等待
while True:
resp = requests.get(f"{BASE_URL}/videos/{task_id}", headers=HEADERS)
task = resp.json()
print(f"状态: {task['status']} 进度: {task['progress']}%")
if task["status"] == "completed":
video_url = task["metadata"]["url"]
print(f"视频生成完成: {video_url}")
# 3. 下载视频
video = requests.get(
f"{BASE_URL}/videos/{task_id}/content",
headers=HEADERS
)
with open("output.mp4", "wb") as f:
f.write(video.content)
print("视频已下载: output.mp4")
break
elif task["status"] == "failed":
print(f"任务失败: {task.get('error', {}).get('message')}")
break
time.sleep(5)