主题
视频分组 API 教程
视频分组提供异步视频生成接口,支持 Seedance、Wan 和 MiniMax 等模型。完整流程为:查询模型 → 创建任务 → 保存任务 ID → 查询状态 → 下载视频。
服务根地址为 https://www.poke2api.com。视频任务使用 /v1/videos 系列接口;Chat Completions 和 Responses 不用于创建视频。
一、准备 API Key
- 登录 Poke API 控制台,进入 API 密钥。
- 创建或编辑 API Key,绑定 视频分组,确认账户有可用余额和分组权限。
- 将密钥读入环境变量
POKE_API_KEY,具体命令见 API 脚本接入:隐藏读取 API Key。
本页示例将请求固定到当前视频分组(ID 为 98),创建、查询和下载均携带 X-Sub2API-Group-ID: 98。该分组必须已绑定到当前 API Key;请求头本身不授予分组权限。只有一个绑定分组时,也可在所有请求中省略此请求头。
任务归属
查询和下载必须使用创建任务时的同一把 API Key,并选择同一个视频分组。换成同一用户的另一把 Key,也无法访问原任务。任务处理期间请保留这把 Key 的分组绑定。
二、可用模型
使用以下公开模型名称填写 model,网关会自动完成账号映射,无需填写上游模型名或上游服务地址。
可用模型以当前 Key 的 /v1/models 为准,支持的参数以模型描述为准。
| 模型名称 | 说明 |
|---|---|
seedance-2.0 | 支持 480p、720p、1080p |
seedance-2.5 | 支持 480p、720p、1080p |
wan-3.0-720p | 仅提供 720p |
wan-3.0-1080p | 仅提供 1080p |
minimax-h3 | MiniMax 视频模型,参数以模型描述为准 |
seedance-2.0-720p | 仅提供 720p |
seedance-2.5-720p | 720p 线路 |
seedance-2.0-route-1 | Seedance 2.0 线路 1 |
seedance-2.5-route-1 | Seedance 2.5 线路 1,当前模型描述要求 30 秒 |
seedance-2.0-fast-route-4 | Seedance 2.0 Fast 线路 4 |
seedance-2.0-fast-route-5 | Seedance 2.0 Fast 线路 5 |
seedance-2.0-route-8 | Seedance 2.0 线路 8 |
route-* 是不同服务线路的区分标识;各线路支持的时长和素材数量可能不同,不能只替换模型名并假定所有参数兼容。
三、查询可用模型
bash
curl --fail-with-body --silent --show-error \
https://www.poke2api.com/v1/models \
-H "Authorization: Bearer ${POKE_API_KEY}" \
-H 'X-Sub2API-Group-ID: 98'读取响应 data 数组中的 id 和 description。例如使用 seedance-2.0,并查看它的模型描述。描述用于说明模型能力,不是请求字段。
若目标模型不在列表中,先检查 Key 的分组绑定和模型权限。旧上游名称仍保留兼容,新接入统一使用目录中的正式名称。
四、创建视频任务
text
POST https://www.poke2api.com/v1/videos以下示例使用 seedance-2.0,生成 5 秒、720p、16:9 的视频。JSON 中的 seconds 使用整数。
bash
curl --fail-with-body --silent --show-error \
https://www.poke2api.com/v1/videos \
-H "Authorization: Bearer ${POKE_API_KEY}" \
-H 'X-Sub2API-Group-ID: 98' \
-H 'Content-Type: application/json' \
--data '{
"model": "seedance-2.0",
"prompt": "海面日出,镜头缓慢向前移动,写实风格,画面平稳",
"seconds": 5,
"resolution": "720p",
"aspect_ratio": "16:9"
}' > video-task.jsonpowershell
if (-not $env:POKE_API_KEY) { throw '请先设置 POKE_API_KEY。' }
$videoHeaders = @{
Authorization = "Bearer $env:POKE_API_KEY"
'X-Sub2API-Group-ID' = '98'
}
$videoBody = @{
model = 'seedance-2.0'
prompt = '海面日出,镜头缓慢向前移动,写实风格,画面平稳'
seconds = 5
resolution = '720p'
aspect_ratio = '16:9'
} | ConvertTo-Json
$task = Invoke-RestMethod `
-Uri 'https://www.poke2api.com/v1/videos' `
-Method Post `
-Headers $videoHeaders `
-ContentType 'application/json; charset=utf-8' `
-Body ([Text.Encoding]::UTF8.GetBytes($videoBody))
$task | ConvertTo-Json -Depth 10 | Set-Content video-task.json -Encoding utf8
$task.id创建响应包含 id、status 等字段。立即保存服务返回的 id,后续用它查询和下载;不要根据示例自行拼接任务 ID。
POST /v1/videos 不是幂等接口。如果收到响应前超时或断线,请先检查任务和用量记录,不要自动重复提交,以免创建多个任务。
如果错误 code 为 video_task_persistence_failed,上游可能已受理任务。请保存错误响应中的 error.task_id 并联系支持,不要再次创建同一任务。
常用参数
| 字段 | 必填 | 说明 |
|---|---|---|
model | 是 | 当前视频分组目录中的公开模型名 |
prompt | 是 | 非空的视频描述或生成指令 |
seconds | 按模型要求 | 视频时长,正整数;建议显式填写 |
resolution | 分档模型必填 | 如 480p、720p、1080p,必须有对应模型规格 |
aspect_ratio | 否 | 如 16:9、9:16、1:1,以模型能力为准 |
references | 否 | 图片、视频等参考素材数组,格式见下一节 |
generate_audio | 否 | JSON 布尔值,仅对支持音频生成的模型使用 |
推荐明确填写 seconds 和 resolution。duration 是时长兼容字段,与 seconds 同时出现时必须一致。分辨率不支持或对应规格未开放时会报错,不会自动降级为其他规格。
五、参考素材与文本表单
支持参考素材的模型可以提交公网 HTTPS URL。例如:
json
{
"model": "seedance-2.0",
"prompt": "沿参考图中的海岸线缓慢推进,保持建筑外观一致",
"seconds": 5,
"resolution": "720p",
"aspect_ratio": "16:9",
"references": [
{
"type": "image",
"role": "reference",
"source": "https://example.com/coast.png"
}
]
}将示例 URL 替换为实际可访问的素材地址。支持首尾帧的模型可以使用 role: "first_frame"、role: "last_frame";参考视频、音频以及 reference_images 等扩展字段是否可用,取决于所选模型。
素材 URL 必须能由服务端直接访问,不能填写本地文件路径,也不能依赖浏览器登录状态。当前视频接口不接受 multipart 二进制文件上传,不要照搬图片编辑接口的 -F 'image=@...' 用法。
需要兼容文本表单的客户端可使用以下格式;curl 会自动生成 multipart boundary:
bash
curl --fail-with-body --silent --show-error \
https://www.poke2api.com/v1/videos \
-H "Authorization: Bearer ${POKE_API_KEY}" \
-H 'X-Sub2API-Group-ID: 98' \
-F 'model=seedance-2.0' \
-F 'prompt=海面日出,镜头缓慢向前移动' \
-F 'seconds=5' \
-F 'resolution=720p' \
-F 'aspect_ratio=16:9' \
-F 'references=[]'表单中的数组字段使用 JSON 数组字符串。size=1280x720 只用于换算画面比例,不能替代 resolution=720p。新接入优先使用 JSON 和上表中的标准字段。
六、查询任务状态
从创建响应读取任务 id,设为 VIDEO_TASK_ID 后查询:
bash
VIDEO_TASK_ID='<创建响应中的 id>'
curl --fail-with-body --silent --show-error \
"https://www.poke2api.com/v1/videos/${VIDEO_TASK_ID}" \
-H "Authorization: Bearer ${POKE_API_KEY}" \
-H 'X-Sub2API-Group-ID: 98'status | 含义 | 处理方式 |
|---|---|---|
queued | 排队中 | 等待后继续查询 |
in_progress | 生成中 | 等待后继续查询 |
completed | 已完成 | 停止轮询并下载 |
failed | 已失败 | 停止轮询,读取 error.message 或 message |
unknown | 暂无法识别 | 降低查询频率,持续出现时联系支持 |
建议每 3~5 秒查询一次,并设置总等待时间。达到客户端等待上限不代表服务端取消任务,应保存任务 ID,稍后继续查询。progress 等扩展字段以实际返回为准。
七、下载视频
任务 status 为 completed 后,使用同一个任务 ID 下载:
bash
curl --fail --silent --show-error --location \
"https://www.poke2api.com/v1/videos/${VIDEO_TASK_ID}/content" \
-H "Authorization: Bearer ${POKE_API_KEY}" \
-H 'X-Sub2API-Group-ID: 98' \
--output result.mp4成功响应是视频文件,不是 JSON。应检查 HTTP 状态码、Content-Type 和文件大小,完成后及时保存到自己的存储中。下载中断时重试同一任务的 /content,无需重新生成。
用 HEAD /v1/videos/{id}/content 可以检查视频是否可用。下载支持转发 Range,但是否返回分段内容取决于视频源:只有 206 才能按范围追加,返回 200 时应覆盖旧文件,避免拼接出损坏的视频。
八、Node.js 完整示例
需要 Node.js 18 或更高版本,无需额外依赖。先设置 POKE_API_KEY,将代码作为 .mjs 脚本运行。首次运行创建任务并保存 ID;已有任务时设置 POKE_VIDEO_TASK_ID 即可继续查询下载,不会再次创建。
javascript
import { createWriteStream } from 'node:fs'
import { writeFile } from 'node:fs/promises'
import { Readable } from 'node:stream'
import { pipeline } from 'node:stream/promises'
const baseUrl = 'https://www.poke2api.com'
const apiKey = process.env.POKE_API_KEY
if (!apiKey) throw new Error('请先设置 POKE_API_KEY')
const headers = {
Authorization: `Bearer ${apiKey}`,
'X-Sub2API-Group-ID': '98',
}
async function requireSuccess(response) {
if (response.ok) return
const text = await response.text()
let message = text
try {
const data = JSON.parse(text)
message = [
data.error?.code || data.code,
data.error?.message || data.message || text,
data.error?.task_id ? `任务 ID:${data.error.task_id}` : null,
].filter(Boolean).join(' | ')
} catch {}
throw new Error(`HTTP ${response.status}: ${message}`)
}
async function requestJson(path, body) {
const response = await fetch(baseUrl + path, {
method: body ? 'POST' : 'GET',
headers: body ? { ...headers, 'Content-Type': 'application/json' } : headers,
body: body ? JSON.stringify(body) : undefined,
signal: AbortSignal.timeout(60_000),
})
await requireSuccess(response)
return response.json()
}
let taskId = process.env.POKE_VIDEO_TASK_ID
if (!taskId) {
const task = await requestJson('/v1/videos', {
model: 'seedance-2.0',
prompt: '海面日出,镜头缓慢向前移动,写实风格,画面平稳',
seconds: 5,
resolution: '720p',
aspect_ratio: '16:9',
})
if (!task.id) throw new Error('创建响应没有任务 ID,请检查用量记录,勿自动重试')
taskId = task.id
console.log(`任务 ID:${taskId}`)
await writeFile('video-task.json', JSON.stringify(task, null, 2), { mode: 0o600 })
}
const taskPath = `/v1/videos/${encodeURIComponent(taskId)}`
const deadline = Date.now() + 30 * 60_000
while (true) {
if (Date.now() >= deadline) {
throw new Error(`等待超时。保留任务 ${taskId},下次设置 POKE_VIDEO_TASK_ID 继续查询`)
}
const current = await requestJson(taskPath)
if (current.status === 'completed') break
if (current.status === 'failed') {
throw new Error(current.error?.message || current.message || `任务失败:${taskId}`)
}
console.log(`任务 ${taskId}:${current.status || 'unknown'}`)
await new Promise(resolve => setTimeout(resolve, current.status === 'unknown' ? 10_000 : 4_000))
}
const video = await fetch(baseUrl + taskPath + '/content', {
headers,
signal: AbortSignal.timeout(300_000),
})
await requireSuccess(video)
if (!video.body) throw new Error('视频响应体为空')
await pipeline(Readable.fromWeb(video.body), createWriteStream('result.mp4'))
console.log('视频已保存为 result.mp4')脚本执行失败时仍应保留 video-task.json。创建请求没有自动重试;查询或下载失败后,用已有 ID 恢复任务,而不是重新执行创建流程。
九、常见错误
| 状态或现象 | 排查方式 |
|---|---|
400 参数错误 | 核对模型名、时长、分辨率和素材字段;先使用本文的 JSON 基础请求 |
| 分辨率或规格不可用 | 使用该模型已提供的规格;如 Wan 720p 线路不能请求 1080p |
401 | 检查 Key 是否有效,Authorization 是否为 Bearer <API Key> |
403 | 检查视频分组权限、Key 绑定、余额和额度;固定分组 98 时必须已绑定它 |
404 任务不存在 | 确认任务 ID,并使用创建时的同一把 Key 和同一分组;任务也可能已过期 |
410 | 视频内容已不可用;完成后应及时下载保存 |
413 | 请求体超过限制;二进制文件不受支持,会被拒绝,应改为公网素材 URL |
429 | 频率、并发或额度受限,等待后再查询或提交 |
502、503、504 | 上游或可用线路暂时异常;已有任务先保留 ID,避免重复创建 |
生成失败但 HTTP 为 200 | 查询接口正常不代表任务成功,必须检查 status 和任务错误字段 |
错误信息优先读取 error.message,其次读取顶层 message;程序分支应结合 HTTP 状态码和错误 code,不要只匹配错误文本。
