Pense Video API 接入文档
使用 MX Canvas 账号中的积分调用视频生成能力。模型、价格、分辨率、时长和可见性均以后台实时配置为准。
Base URLhttps://api.pense.cn/v1
快速开始
1. 充值积分
登录 MX Canvas,在软件账号中充值积分。API 调用和软件生成共用同一积分余额。
2. 创建密钥
进入“个人信息 → API 接入”,创建并立即保存以
pense_sk_ 开头的密钥。3. 获取模型
调用
GET /models,使用返回的完整模型 ID、时长和分辨率。4. 提交并查询
提交视频任务获得任务 ID,再定时调用任务查询接口直到成功或失败。
身份认证
所有 /v1 接口都必须在请求头中携带 API Key:
Authorization: Bearer pense_sk_xxxxxxxxxxxxxxxxx
完整密钥只在创建时展示一次。不要放进前端网页、公开仓库或客户端日志;泄露后请立即在 MX Canvas 中禁用。
模型列表
GET/models
返回当前向用户开放并且已经设置价格的视频模型。务必使用返回的完整 id。
与软件后台实时同步:后台视频模型管理中“向用户展示”的模型和分辨率,才会开放给 API 用户。隐藏模型不会出现在本列表中,即使手工提交隐藏模型 ID,服务端也会拒绝生成。
curl https://api.pense.cn/v1/models \ -H "Authorization: Bearer pense_sk_xxx"
{
"object": "list",
"data": [{
"id": "release/seedance-2.0",
"object": "model",
"name": "Seedance 2.0",
"billing_mode": "per_generation",
"credit_cost": 5.5,
"resolution_prices": {},
"config": {
"video_generation": {
"fixed_fields": {
"duration": {"values": ["4", "5", "6"]},
"resolution": {"values": ["480p", "720p"]}
}
}
}
}]
}
账户余额
GET/account/balance
curl https://api.pense.cn/v1/account/balance \ -H "Authorization: Bearer pense_sk_xxx"
{
"user_id": "用户ID",
"credits": 120.5,
"personal_credits": 80.5,
"team_credits": 40
}
credits 是当前总可用积分。团队成员调用时,可按现有团队规则使用团长共享积分。
生成视频
POST/videos/generations
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | string | 是 | /models 返回的完整 ID,例如 release/seedance-2.0 |
prompt | string | 是 | 视频提示词,最长 4000 个字符 |
duration | number | 是 | 时长秒数,必须使用该模型支持的值 |
ratio | string | 否 | 画面比例,例如 16:9、9:16、1:1 |
resolution | string | 是 | 例如 480p、720p、1080p |
references | array | 否 | 图生视频或多模态参考素材 |
extensions | object | 否 | 模型扩展参数,以模型接口返回能力为准 |
curl https://api.pense.cn/v1/videos/generations \
-H "Authorization: Bearer pense_sk_xxx" \
-H "Content-Type: application/json" \
-d '{
"model": "release/seedance-2.0",
"prompt": "海边日出,镜头缓慢向前推进,电影感",
"duration": 5,
"ratio": "16:9",
"resolution": "720p"
}'
{
"id": "task_xxxxxxxxx",
"object": "video.task",
"status": "accepted",
"model": "release/seedance-2.0",
"credit_cost": 5.5,
"credits": 115
}
图生视频与参考素材
在 references 中传入可公开访问的 HTTPS 地址,或合法的 Base64 Data URL:
{
"model": "aistartlab/模型ID",
"prompt": "让人物自然转身并看向镜头",
"duration": 5,
"ratio": "9:16",
"resolution": "720p",
"references": [{
"url": "https://example.com/reference.jpg",
"kind": "image",
"name": "reference.jpg",
"mime": "image/jpeg"
}]
}
不同上游模型支持的素材数量和类型不同。建议优先读取
/models 的模型配置,并控制素材文件大小。穗禾首尾帧
当 /models 返回的穗禾模型配置中包含 config.video_generation.reference_modes,且其中有 first_last_frames 时,可以使用首尾帧。调用时把前两张图片放入 references,并传入 extensions.function_mode=first_last_frames。服务端会把第一张图片转为穗禾的 first_frame,第二张图片转为 end_frame。
{
"model": "shapi/穗禾模型ID",
"prompt": "从首帧自然运动到尾帧,镜头平滑推进",
"duration": 5,
"ratio": "16:9",
"resolution": "720p",
"extensions": {
"function_mode": "first_last_frames"
},
"references": [
{
"url": "https://example.com/start.jpg",
"kind": "image",
"name": "start.jpg",
"mime": "image/jpeg"
},
{
"url": "https://example.com/end.jpg",
"kind": "image",
"name": "end.jpg",
"mime": "image/jpeg"
}
]
}
查询任务
GET/videos/tasks/{task_id}
curl https://api.pense.cn/v1/videos/tasks/task_xxxxxxxxx \ -H "Authorization: Bearer pense_sk_xxx"
{
"id": "task_xxxxxxxxx",
"object": "video.task",
"status": "succeeded",
"model": "release/seedance-2.0",
"result": {
"items": [{
"kind": "video",
"delivery_status": "ready",
"download_url": "https://..."
}]
},
"credits": 115,
"refunded": false
}
常见状态:accepted、queued、processing、succeeded、failed。建议每 5 秒查询一次。
计费与退款
任务提交前由服务器计算并预扣积分。提交失败会立即退款;任务最终失败时会自动退款,成功任务不退款。
- 按次计费:每次任务扣除后台设置的固定积分。
- 按秒计费:每秒价格 × 用户选择时长,不进行整数四舍五入。
- 不同分辨率可使用不同的每秒价格。
- 没有设置价格或被后台隐藏的模型、分辨率无法调用。
- 团队成员调用会记录实际调用用户,并按团队共享积分规则扣费。
状态码与错误
| HTTP | 含义 | 处理建议 |
|---|---|---|
| 200 | 请求成功 | 读取返回的 JSON 数据 |
| 400 | 参数、模型、价格或余额问题 | 读取响应中的 detail 并修正请求 |
| 401 | API Key 缺失、错误或已禁用 | 检查 Authorization 请求头 |
| 403 | 无权访问该任务 | 任务只能由创建它的账号查询 |
| 404 | 任务或资源不存在 | 确认任务 ID 完整且正确 |
| 422 | 请求体格式不正确 | 检查字段类型和必填字段 |
| 429 | 请求过于频繁 | 降低频率,默认每个 Key 每分钟最多 60 次 |
| 502/504 | 上游异常或超时 | 稍后重试;失败任务按规则自动退款 |
{
"detail": "错误原因"
}代码示例
Python
import time
import requests
API_KEY = "pense_sk_xxx"
BASE_URL = "https://api.pense.cn/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}
task = requests.post(
f"{BASE_URL}/videos/generations",
headers={**headers, "Content-Type": "application/json"},
json={
"model": "release/seedance-2.0",
"prompt": "海边日出,电影感",
"duration": 5,
"ratio": "16:9",
"resolution": "720p",
},
timeout=180,
).json()
while True:
result = requests.get(
f"{BASE_URL}/videos/tasks/{task['id']}",
headers=headers,
timeout=60,
).json()
if result.get("status") in {"succeeded", "failed"}:
print(result)
break
time.sleep(5)
JavaScript
const apiKey = "pense_sk_xxx";
const baseUrl = "https://api.pense.cn/v1";
const response = await fetch(`${baseUrl}/videos/generations`, {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "release/seedance-2.0",
prompt: "海边日出,电影感",
duration: 5,
ratio: "16:9",
resolution: "720p"
})
});
const task = await response.json();
console.log(task);