POST /v1/videos 生成视频。该端点需要通过 Authorization: Bearer 发送 API
密钥。详见认证。请求体为 JSON。
视频的生成需要时间,因此该端点从不等待结果。它总是返回 202 和一个任务。你可以通过轮询任务或接收 Webhook 事件来取回结果。即使你用相同的 Idempotency-Key 再次发送请求,且任务已经完成,也是如此。
创建视频
章节标题“创建视频”发送模型和提示词。示例使用 sakuranbo/cherry-1.0-pro。
curl -X POST "https://api.sakuranbo.ai/v1/videos" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $SAKURANBO_API_KEY" \ -d '{ "model": "sakuranbo/cherry-1.0-pro", "prompt": "Aerial shot gliding over a misty mountain lake at sunrise, gentle wind and birdsong", "duration": 5, "resolution": "1080p", "aspect_ratio": "16:9"}'const response = await fetch("https://api.sakuranbo.ai/v1/videos", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${process.env.SAKURANBO_API_KEY}`, }, body: JSON.stringify({ "model": "sakuranbo/cherry-1.0-pro", "prompt": "Aerial shot gliding over a misty mountain lake at sunrise, gentle wind and birdsong", "duration": 5, "resolution": "1080p", "aspect_ratio": "16:9" }),});const data = await response.json();console.log(data);import os
import requests
response = requests.post( "https://api.sakuranbo.ai/v1/videos", headers={ "Authorization": f"Bearer {os.environ['SAKURANBO_API_KEY']}", }, json={ "model": "sakuranbo/cherry-1.0-pro", "prompt": "Aerial shot gliding over a misty mountain lake at sunrise, gentle wind and birdsong", "duration": 5, "resolution": "1080p", "aspect_ratio": "16:9", },)print(response.json())以下是示例模型的输入参数:
| 名称 | 类型 | 必填 | 默认值 | 约束 | 说明 |
|---|---|---|---|---|---|
prompt | string | 是 | 最多 20,000 个字符 | 场景、动作和音频的描述。 | |
first_frame | url | 否 | 用作首帧的图像(图生视频)。 | ||
last_frame | url | 否 | 用作尾帧的图像,需与 first_frame 一起使用。 | ||
reference_images | url[] | 否 | 最多 10 项 | 最多 10 张参考图,不能与关键帧同时使用。 | |
duration | integer | 否 | 5 | 2 至 30 | 视频时长(秒),按秒计费。 |
resolution | enum | 否 | 1080p | 可选值:1080p, 2k, 4k | 输出分辨率,决定每秒价格。 |
aspect_ratio | enum | 否 | adaptive | 可选值:adaptive, 16:9, 9:16, 1:1, 4:3, 3:4 | 输出视频的宽高比。 |
audio | boolean | 否 | true | 生成音轨。有无音频价格相同。 |
请求体包含以下字段:
| 名称 | 类型 | 必填 | 默认值 | 约束 |
|---|---|---|---|---|
model | string | 是 | 1 至 128 个字符 | |
prompt | string | 是 | ||
first_frame | string | 否 | ||
last_frame | string | 否 | ||
reference_images | string[] | 否 | ||
duration | number | 否 | ||
resolution | string | 否 | ||
aspect_ratio | string | 否 | ||
audio | boolean | 否 |
不在表中的参数或超出范围的值会返回 400 和 invalid_request。error.param 给出参数名称,error.details.allowed、error.details.minimum 或 error.details.maximum 给出有效的取值。
选择输入
章节标题“选择输入”你发送的字段决定视频的生成方式:
- 只发送
prompt,根据文本生成视频。 - 发送
first_frame,让视频从一张图像开始。你还可以发送last_frame,让视频以一张图像结束。last_frame需要同时有first_frame。 - 发送
reference_images,生成以这些图像为参考的视频。顺序很重要,因为提示词可以指代第一张图像或第二张图像。reference_images不能与first_frame或last_frame同时使用。
图像是公开的 https URL,或者是 PNG、JPEG、WebP 或 GIF 图像的 data:image/...;base64, URI。data URI 的大小限制比 URL 更小,因此较大的图像请以公开 URL 发送。服务器在创建任务之前会获取每个 URL 来进行检查。它不会跟随重定向,并会拒绝包含凭据、IP 地址或内部主机名的 URL。无法使用的图像会返回 400 和 invalid_request。error.param 给出字段名称。对于 URL,error.details.reason 会说明问题所在。对于过大的 data URI,error.details.max_bytes 为大小上限。
响应
章节标题“响应”202 响应是任务,另外多了两个字段:polling_url 和 eta_seconds。它的 object 为 video。
| 名称 | 类型 |
|---|---|
id | string |
object | string |
model | string |
status | string |
progress | integer | null |
created_at | string |
completed_at | string | null |
expires_at | string | null |
error | object | null |
outputs | object[] |
usage | object | null |
cost | object | null |
polling_url | string |
eta_seconds | integer | null |
progress 和 eta_seconds 是根据已用时间得出的估计值。不要把它们当作截止时间或计费依据。Location 响应头和 polling_url 都指向该视频。
等待结果
章节标题“等待结果”请每隔几秒轮询一次 GET /v1/videos/{id},直到 status 变为 completed、failed、cancelled 或 expired。polling_url 就是这个请求的 URL。失败的任务仍会返回 200,原因在 error 中。各状态详见任务。
curl "https://api.sakuranbo.ai/v1/videos/job_0123456789abcdef0123456789abcdef" \ -H "Authorization: Bearer $SAKURANBO_API_KEY"const response = await fetch("https://api.sakuranbo.ai/v1/videos/job_0123456789abcdef0123456789abcdef", { headers: { Authorization: `Bearer ${process.env.SAKURANBO_API_KEY}`, },});const data = await response.json();console.log(data);import os
import requests
response = requests.get( "https://api.sakuranbo.ai/v1/videos/job_0123456789abcdef0123456789abcdef", headers={ "Authorization": f"Bearer {os.environ['SAKURANBO_API_KEY']}", },)print(response.json())如需避免轮询,请注册一个 Webhook 端点,接收 job.succeeded、job.failed 和 job.cancelled 事件。详见 Webhook。
没有在时限内完成的任务会变为 expired。它不会计费。
模型提供方繁忙不会表现为 POST /v1/videos 的 HTTP 状态码,而是稍后出现在任务的 error 字段中,错误代码为 rate_limited 或 concurrency_limited。请稍等片刻后重新创建视频。
模型提供方也可能因内容拒绝提示词或参考图像。这同样不会表现为 HTTP 状态码,任务会以错误代码 content_policy_violation 失败,不会扣费。
下载文件
章节标题“下载文件”已完成的任务在 outputs 中有一项。它的 url 是带签名的 URL,不需要 API 密钥,并且在 expires_at 之前有效,即任务完成后 7 天。在此之前,任何拿到该 URL 的人都可以下载文件,因此请把 URL 当作机密。expires_at 之后文件会被删除,请保存你需要的视频。
你也可以带上 API 密钥调用 GET /v1/videos/{id}/content。它会以重定向响应指向签名 URL,因此你的客户端必须跟随重定向。如果任务没有文件,它会返回 404,error.details.status 为任务的状态。任务仍在运行、已失败、已取消或已过期,以及文件已被删除时,都会出现这种情况。
列出和取消视频
章节标题“列出和取消视频”GET /v1/videos 列出你的视频,最新的在前,使用与任务列表相同的 limit、cursor 和
status 参数。使用 POST /v1/videos/{id}/cancel
可以取消排队中或运行中的视频。两者都遵循任务端点的规则。详见任务。
安全地重试
章节标题“安全地重试”发送 Idempotency-Key 请求头,值由你自己选择。如果之后又收到幂等键相同、内容也相同的请求,你会得到同一个任务,并且只会被扣费一次。相同的幂等键搭配不同的请求会返回 409 和 idempotency_conflict。幂等键只会被记住一段有限的时间,具体时长见 API 参考。
计费
章节标题“计费”请求被接受时,Sakuranbo AI 会从你的余额中预留预估的价格。预估根据 duration 和 resolution 得出。任务完成时,会按所请求的 duration 和该 resolution 的每秒价格扣费,这正是之前预留的金额。被取消或已过期的任务不会计费。失败的任务通常也不会计费,其预留会回到你的余额。
在极少数情况下,Sakuranbo AI 无法确认请求是否已到达模型提供方。此时任务会以 upstream_error 失败,其预留金额会保持预留,直到 Sakuranbo AI 确认该请求是否计费。如果它一直保持预留,请联系支持团队并提供任务 ID。
价格请查看模型目录和定价页面,也可以在运行请求之前用 POST /v1/estimate 计算价格。详见费用预估 API。
错误
章节标题“错误”| 代码 | HTTP 状态码 | 类型 | 说明 |
|---|---|---|---|
invalid_request | 400 | invalid_request_error | 请求格式有误或取值超出范围。如果有效取值已知,会列在 details.allowed 中。 |
unauthorized | 401 | authentication_error | API 密钥缺失、格式有误、未知、已被吊销或已过期。响应不会说明属于哪一种情况。 |
balance_insufficient | 402 | insufficient_balance | 可用余额低于该请求需要预留的金额。error.details.limit_source 为 balance。 |
key_limit_exceeded | 402 | insufficient_balance | 该请求会使 API 密钥超出其支出上限。error.details.limit_source 为 key,error.details.resets_at 说明计数器何时重新开始。 |
account_suspended | 403 | permission_error | 账户已被停用,图像、视频和对话请求会被拒绝。请联系支持团队。余额、充值、API 密钥和任务仍可使用。 |
model_not_found | 404 | not_found_error | 目录中不存在该模型 ID。对于不是文本模型的模型,对话端点也会返回此代码。 |
idempotency_conflict | 409 | conflict_error | 该 Idempotency-Key 已被用于另一个内容不同的请求。 |
payload_too_large | 413 | invalid_request_error | 请求体超过了允许的大小。error.details.max_bytes 为大小上限。 |
upstream_unavailable | 503 | overloaded_error | 上游提供方暂时容量不足,请稍后重试。 |
对于 429 或 503 响应,请等待 Retry-After 响应头给出的秒数再重试。402 响应带有 error.details.limit_source,其值为 balance 或 key。详见余额与 API 密钥限额。完整的错误代码列表请参阅错误。
所有价格均以 USD 计价,标价已包含我们的加价。