官方 SDK 快速上手
官方 SDK 封装了完整流程(创建 → 轮询 → 下载),自动生成幂等键并提供类型化错误;Node SDK 零依赖,Python SDK 仅依赖 httpx。目前以 GitHub 仓库形式提供,npm / PyPI 正式发布将另行公告。
Node
npm install github:openaiav/sdk-node # npm release to be announced
import { OpenAiav } from '@openaiav/sdk'
const client = new OpenAiav({ apiKey: process.env.OPENAIAV_API_KEY })
const task = await client.generations.createAndWait({
model: 'seedance-2.5-oa', prompt: 'She walks into the sunlight.',
resolution: '480p', aspectRatio: 'adaptive', durationSeconds: 4,
generateAudio: false
})
await client.generations.downloadToFile(task.id, './out.mp4')Python
pip install git+https://github.com/openaiav/sdk-python # PyPI release to be announced
from openaiav import OpenAiav
client = OpenAiav(os.environ["OPENAIAV_API_KEY"])
task = client.generations.create_and_wait({
"model": "seedance-2.5-oa", "prompt": "She walks into the sunlight.",
"resolution": "480p", "aspectRatio": "adaptive", "durationSeconds": 4,
"generateAudio": False,
})
client.generations.download_to_file(task["id"], "./out.mp4")四步接入
- 使用服务端环境变量
OPENAIAV_API_KEY调用 https://api.openaiav.com/v1/models,读取当前模型键、计价与 reference_modes。 - 向 POST /v1/generations 提交 prompt、referenceMode 与 referenceImages;参考图是公网 HTTPS URL,不需要预注册。创建成功为 HTTP 201。
- 保存响应 id,按 poll_after_ms 对同一个 GET /v1/generations/{id} 轮询。processing、result_pending、submission_unknown 都继续等待,不要重新创建。
- 状态变为 succeeded 后调用 GET /v1/generations/{id}/content 下载;完整响应为 HTTP 200,单区间 Range 为 206。
认证与幂等
export OPENAIAV_API_KEY='oav_...'
# One Idempotency-Key per create intent: every run of this script makes a new one.
# Reuse it only when retrying this same create. No uuidgen? IDEMPOTENCY_KEY=$(python3 -c 'import uuid;print(uuid.uuid4())')
IDEMPOTENCY_KEY=$(uuidgen | tr 'A-Z' 'a-z')
echo "Idempotency-Key: $IDEMPOTENCY_KEY (reuse this value only when retrying this same create)"每个请求都带 Authorization: Bearer oav_...。密钥只放在服务端。创建任务需要 generation:create,查询和下载需要 generation:read。每个创建意图生成一个新的 Idempotency-Key(UUID),示例每次运行都会换新键;只在网络结果不确定、重试同一个创建时复用它,同一个键不得配不同请求体。
请求头
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| Authorization | string | 必填 | 所有 /v1 请求均使用 Bearer oav_...;密钥只保存在服务端。 |
| Idempotency-Key | string | 仅创建任务必填 | 每个创建意图生成一个新值(如 UUID),只在重试同一个创建时复用;同值同请求体不会重复生成或重复扣费。 |
| Content-Type | string | 仅 POST 必填 | 创建任务使用 application/json。 |
端点一览
| 方法 | 路径 | 成功 | 权限范围 | 说明 |
|---|---|---|---|---|
| GET | /v1/models | 200 | 任意有效的 API 密钥 | 读取当前可售模型、价格、分辨率、时长与 reference_modes。提交前必须按目录校验能力。 |
| POST | /v1/generation-quotes | 201 | generation:create | 预览当前价格,不锁价;创建任务时重新定价,按创建响应的 reserved_usd 固定扣费,失败全额退款。quoteId 仍可传入,expires_at 仅为刷新提示。 |
| POST | /v1/generations | 201 | generation:create | 创建异步任务;参考图与 referenceMode 在同一个 JSON 请求中提交。 |
| GET | /v1/generations/{id} | 200 | generation:read | 按响应中的 poll_after_ms 查询同一任务,直到终态。 |
| GET | /v1/generations/{id}/content | 200 / 206 | generation:read | 任务成功后下载输出;单区间 Range 请求返回 206。 |
第一步:读取模型能力
不要写死模型能力。只有 reference_modes 列出的模式可以提交;界面也应在提交前隐藏或拦截不兼容组合。最小示例固定演示 seedance-2.5-oa 的 4 秒、480p、无音频请求。
curl --fail-with-body 'https://api.openaiav.com/v1/models' \
--header "Authorization: Bearer $OPENAIAV_API_KEY"最小公网视频示例
完整链路在同一个示例里:创建 → 轮询同一任务 → 下载。 first_frame 使用一张参考图和 adaptive;generateAudio=false 避免请求音频。创建、轮询、下载的成功状态分别是 201、200、200/206;失败响应先读取 HTTP,再读取 error.code。
# Keep OPENAIAV_API_KEY in an environment variable; do not paste secrets into shell history.
# One Idempotency-Key per create intent: every run of this script makes a new one.
# Reuse it only when retrying this same create. No uuidgen? IDEMPOTENCY_KEY=$(python3 -c 'import uuid;print(uuid.uuid4())')
IDEMPOTENCY_KEY=$(uuidgen | tr 'A-Z' 'a-z')
echo "Idempotency-Key: $IDEMPOTENCY_KEY (reuse this value only when retrying this same create)"
# 1. Create — success: HTTP 201. On failure, the response body contains error.code.
# Lost response (timeout or dropped connection)? Re-run this same command in this shell:
# the unchanged $IDEMPOTENCY_KEY returns the original task instead of creating a second one.
curl --fail-with-body --request POST 'https://api.openaiav.com/v1/generations' \
--header "Authorization: Bearer $OPENAIAV_API_KEY" \
--header "Idempotency-Key: $IDEMPOTENCY_KEY" \
--header 'Content-Type: application/json' \
--data '{
"model": "seedance-2.5-oa",
"prompt": "A young woman finishes a letter and walks from a stone cottage into the morning sunlight",
"resolution": "480p",
"aspectRatio": "adaptive",
"durationSeconds": 4,
"referenceMode": "first_frame",
"referenceImages": [
"https://developers.openaiav.com/samples/seedance-letter-reference.webp"
],
"generateAudio": false,
"outputFormat": "mp4"
}'
# 2. Save the returned id as TASK_ID. Poll the same id — success: HTTP 200.
curl --fail-with-body 'https://api.openaiav.com/v1/generations/TASK_ID' \
--header "Authorization: Bearer $OPENAIAV_API_KEY"
# Repeat step 2 after poll_after_ms until status is succeeded or failed.
# Never recreate a task whose status is submission_unknown.
# 3. After succeeded, download — success: HTTP 200 (or 206 with Range).
curl --fail-with-body --location 'https://api.openaiav.com/v1/generations/TASK_ID/content' \
--header "Authorization: Bearer $OPENAIAV_API_KEY" \
--output 'result.mp4'请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| model | string | 必填 | 取自 GET /v1/models 的 model;最小视频示例使用 seedance-2.5-oa。 |
| prompt | string | 必填 | 1–4000 字符。全能参考可按数组顺序用 @Image1、@Image2 指代图片。 |
| resolution | string | 可选 | 必须属于所选模型的 resolutions;最小视频示例使用 480p。 |
| aspectRatio | string | 可选 | 必须属于所选模型的 aspect_ratios;所选模型的首帧能力要求自适应画幅时使用 adaptive。图片模型如果列出了 image_size_options,resolution 与 aspectRatio 要作为一组从中选取:不是每个分辨率都有全部画幅。 |
| durationSeconds | integer | 可选 | 视频时长用 durationSeconds 指定,须为目录 duration_seconds 区间内的整数秒数;省略时使用模型最小时长。最小示例使用 4 秒。 |
| referenceMode | first_frame | omni_reference | 使用视频参考图时必填 | 只在目录 reference_modes 明确列出的 Seedance 视频模型上使用。一次请求只能选择一个模式。 |
| referenceImages | string[] | 与 referenceMode 同时填写 | 公网 HTTPS 图片 URL。first_frame 必须且只能 1 张;omni_reference 上限读取 reference_images_max。 |
| inputImages | string[] | 可选 | 图生图的输入图片(参考图),仅用于图片模型。每项是公网 HTTPS 图片 URL,或 data:image/png;base64,…、data:image/jpeg;base64,…、data:image/webp;base64,… 形式的 data URL。各模型的上限见 GET /v1/models:input_images_max、input_image_max_bytes(每张,URL 与 data URL 都算)和 input_image_mime_types。参考图可能提高扣费。不要与视频参考模式混用。 |
| generateAudio | boolean | 可选 | 支持音频的视频模型省略时默认 true。最经济示例显式传 false;当前目录没有单列音频附加价,计费始终以 GET /v1/models 为准。 |
| outputFormat | mp4 | mov | 可选 | 只能选择目录 output_formats 中的值;最小示例使用 mp4。 |
参考素材模式
first_frame
first_frame:参考图成为起始画面并决定构图。必须且只能提交 1 张 referenceImages;aspectRatio 取自所选模型的 aspect_ratios,目录含 adaptive 时锁定为 adaptive(输出跟随参考图画幅)。
first_last_frame:提交恰好 2 张 referenceImages,按数组顺序分别是首帧与尾帧,中间画面由模型补全。两张图不要求同尺寸。帧模式与 omni_reference 互斥。
{
"model": "seedance-2.5-oa",
"prompt": "A young woman finishes a letter and walks from a stone cottage into the morning sunlight",
"resolution": "480p",
"aspectRatio": "adaptive",
"durationSeconds": 4,
"referenceMode": "first_frame",
"referenceImages": [
"https://developers.openaiav.com/samples/seedance-letter-reference.webp"
],
"generateAudio": false,
"outputFormat": "mp4"
}omni_reference
omni_reference:参考素材用于锁定主体、风格与场景的一致性,不要求成为首帧。除 referenceImages 外,支持的模型还可传 referenceVideos 与 referenceAudios;各类上限见下表,目录未声明的类型提交即 400。提示词按同类型内的数组顺序引用 @Image1、@Video1、@Audio1。
{
"model": "seedance-2.5-oa",
"prompt": "Keep the identity and outfit from @Image1; a young woman walks from a stone cottage into the morning sunlight",
"resolution": "480p",
"aspectRatio": "16:9",
"durationSeconds": 4,
"referenceMode": "omni_reference",
"referenceImages": [
"https://developers.openaiav.com/samples/seedance-letter-reference.webp"
],
"generateAudio": false,
"outputFormat": "mp4"
}真实兼容范围
接入方式对所有视频模型是同一套:同一个端点、同一组字段,换模型只改 model。差异全部由目录声明——下表就是目录本身,逐个模型列出它支持哪些参考模式、各类素材收几个。目录没声明的能力,提交时会被明确拒绝,不会静默忽略。
首帧细则与尾帧接力
首帧细则:first_frame 与 omni_reference 互斥,同一请求只能选其一;omni 下可用提示词间接引导某张参考图作起始画面,但需要严格首帧一致时,请使用 first_frame 模式提交那张图。Seedance 2.5 的首帧任务画幅固定 adaptive(输出跟随首帧)。尾帧接力:创建时传 returnLastFrame: true,成功后任务额外返回 last_frame_url(与视频同宽高的无水印 PNG,保留 24 小时)——把这个 URL 直接作为下一个请求 first_frame 的 referenceImages,即可串联多镜头连续叙事,无需任何预注册步骤。
参考视频计价
- 能实测出时长的参考视频按固定价格计费,可先预览这个金额;测不出时长时拒绝预览,不扣费。
- 调用
POST /v1/generation-quotes预览当前价格。服务端会测量 URL 视频;创建任务时重新测量并定价,实际金额以创建响应的reserved_usd为准。quoteId可继续传入,但不锁价;expires_at只提示刷新预览。 - 模型目录规定单条、总时长、数量和最低计费秒数;Seedance 2.0 系列每条参考视频为 2–15 秒,其他适用模型为 2–30 秒。实测超出范围返回 422
REFERENCE_DURATION_OUT_OF_RANGE,不扣费。 - 只支持 MP4/MOV 公网 HTTPS 直链。已知文件大小超过 200 MiB 时返回
REFERENCE_VIDEO_TOO_LARGE;未报告大小仍可报价。非公网地址返回REFERENCE_URL_NOT_PUBLIC,探测繁忙时返回 429REFERENCE_PROBE_BUSY。控制台上传上限为 32 MiB。 - 每个任务都在创建时按报价扣除
reserved_usd,成功时就按这个金额,失败时全额退回。预览中的price_usd等于在预览那一刻创建所需扣除的金额;输出视频长度仍须明确指定,不能使用 -1。 - 公网视频 URL 在预览和创建时各探测一次,随后作为直链供生成服务读取,无需平台存储或素材注册。请保持链接内容稳定。上传文件走独立注册路径。真人脸素材仍受模型限制。
图片模型计价
- 图片模型按张计价,价格随
resolution和aspectRatio变化,见image_pricing.rates。gpt-image-*与nano-banana-*模型的列表价按短提示词、不带参考图计算。 - 带参考图或提示词较长时,这些模型的扣费会更高。创建任务前,用同样的请求体调用
POST /v1/generation-quotes,返回的price_usd就是这次请求按当前价格的扣费金额。任务失败全额退款。
轮询与下载
succeeded 与 failed 才是终态。submission_unknown 表示受理结果确认中,result_pending 是结果收尾中:保留原任务 ID,继续轮询,绝不能重放创建请求。成功后优先使用鉴权下载路径 /content,不要依赖任何非 Open AIav 地址。产物保留 24 小时(详情返回 output_expires_at 倒计时;过期后下载返回 410 OUTPUT_EXPIRED,请及时转存)。
| 状态 | 终态 | 处理方式 |
|---|---|---|
| processing | 否 | 已受理;按 poll_after_ms 继续查询。 |
| result_pending | 否 | 结果正在收尾;保留任务 ID 并继续轮询同一任务,勿重新创建。 |
| submission_unknown | 否 | 受理结果确认中;不要重放创建请求,继续保留并查询原任务 ID。 |
| succeeded | 是 | 成功;使用 /content 下载输出。 |
| failed | 是 | 确定失败,已全额退款;读取 error_code。 |
旧端点迁移
/v1/assets、/v1/assets/content、/v1/assets/{id}、/v1/asset-groups 与 /v1/asset-groups/{id} 已退役;使用有效密钥及相应旧 scope 调用时返回 HTTP 410 / ENDPOINT_RETIRED。新接入不得调用这些路径;把 referenceMode 与 referenceImages 放进同一次生成请求。错误码对照
完整对照:HTTP 状态、错误码、含义、建议处理方式和 SDK 错误类。本表与 SDK 的错误映射使用同一数据源;遇到未知的新错误码,SDK 会按 HTTP 状态分类处理。
| HTTP | 错误码 | 含义 | 建议处理方式 | SDK |
|---|---|---|---|---|
| 401 | UNAUTHENTICATED | 缺少或无法识别 API 密钥。 | 带上 Authorization: Bearer oav_… 请求头;密钥只放服务端。 | AuthenticationError |
| 401 | INVALID_API_KEY | 密钥无效或已撤销。 | 在控制台确认密钥状态;必要时轮换生成新密钥。 | AuthenticationError |
| 403 | INSUFFICIENT_SCOPE | 密钥缺少本操作所需的权限(scope)。 | 创建任务需 generation:create,查询与下载需 generation:read。 | PermissionError |
| 429 | RATE_LIMITED | 请求超出该密钥的速率限制。 | 按 Retry-After / retryAfterSeconds 退避重试;SDK 自动处理。 | RateLimitError |
| 400 | IDEMPOTENCY_KEY_REQUIRED | 创建任务必须携带 Idempotency-Key。 | 为每次新请求生成唯一键;网络重试复用同一键。SDK 自动生成。 | InvalidRequestError |
| 409 | IDEMPOTENCY_KEY_CONFLICT | 同一个幂等键被用于不同的请求体。 | 不同参数请换新键;同参重试保持键与请求体逐字一致。 | InvalidRequestError |
| 400 | MODEL_NOT_FOUND | 未知模型 ID。 | 以 GET /v1/models 返回的 model 为准(如 seedance-2.5-oa)。 | InvalidRequestError |
| 503 | MODEL_NOT_AVAILABLE | 该模型暂时无法调用。 | 本次未扣费。查看该模型在 GET /v1/models 中的 status,稍后再试。 | ServerError |
| 400 | INVALID_PROMPT | 提示词为空或超长。 | 提示词 1–4000 字符。 | InvalidRequestError |
| 400 | INVALID_DURATION | durationSeconds 不在模型允许区间。 | 请指定视频长度:填写目录 duration_seconds 区间内的整数秒数。 | InvalidRequestError |
| 400 | INVALID_RESOLUTION | 分辨率不被该模型支持。 | 取目录 resolutions 中的取值。 | InvalidRequestError |
| 400 | INVALID_ASPECT_RATIO | 画幅不被该模型支持。 | 取目录 aspect_ratios 中的取值;first_frame 场景常锁 adaptive。 | InvalidRequestError |
| 400 | INVALID_REFERENCE_IMAGES | referenceImages 需为公网 HTTPS URL 数组。 | 逐项提供任务期间可读取的 https:// 图片链接。 | InvalidRequestError |
| 400 | INVALID_REFERENCE_IMAGE | 某一项参考图不是合法 URL。 | 错误信息带下标(referenceImages[i]);逐项检查该链接。 | InvalidRequestError |
| 400 | REFERENCE_IMAGE_URL_NOT_HTTPS | 参考图链接不是公网 HTTPS。 | 不支持 http/内网/data URL;请上传到可公网访问的存储。 | InvalidRequestError |
| 400 | REFERENCE_MODE_REQUIRES_IMAGES | 声明了 referenceMode 却没有参考图。 | referenceMode 与 referenceImages 必须同时出现。 | InvalidRequestError |
| 400 | REFERENCE_MODE_NOT_SUPPORTED | 该模型不支持所选参考模式。 | 以目录 reference_modes 为准选择 first_frame / omni_reference。 | InvalidRequestError |
| 400 | FIRST_FRAME_REQUIRES_ONE_IMAGE | first_frame 必须且只能一张参考图。 | 只提交 1 张;多图请改用 omni_reference。 | InvalidRequestError |
| 400 | TOO_MANY_REFERENCES | 参考图数量超过目录上限。 | 上限见目录 reference_images_max。 | InvalidRequestError |
| 400 | INVALID_INPUT_IMAGES | inputImages 需为数组。 | 逐项为 HTTPS URL 或 data:image/* base64。 | InvalidRequestError |
| 400 | INVALID_INPUT_IMAGE | 某一项输入图片格式不合法。 | 逐项需为 HTTPS URL 或 data:image/* base64;错误信息带下标。 | InvalidRequestError |
| 400 | INPUT_IMAGE_URL_NOT_HTTPS | 输入图片链接不是 HTTPS。 | 改用 https:// 链接,或 data:image/png;base64,… 这类 data URL。 | InvalidRequestError |
| 400 | INPUT_IMAGE_TOO_LARGE | 内嵌图片超过 10 MiB。 | 压缩到 10 MiB 以内再发送。列出 input_image_max_bytes 的模型对 HTTPS 链接同样限制大小:超限时任务以 REFERENCE_INPUT_INVALID 失败并全额退款。 | InvalidRequestError |
| 400 | IMAGE_INPUT_NOT_SUPPORTED | 该模型不支持图片输入。 | 仅目录声明 input_images_max>0 的图片模型可用 inputImages。 | InvalidRequestError |
| 400 | TOO_MANY_INPUT_IMAGES | 输入图片数量超上限。 | 上限见目录 input_images_max。 | InvalidRequestError |
| 422 | REFERENCE_DURATION_OUT_OF_RANGE | 实测的参考视频时长超出模型限制。 | 检查目录中的单条、总时长和数量上限后重新预览;本次未扣费。 | InvalidRequestError |
| 422 | REFERENCE_DURATION_UNVERIFIED | 参考视频时长无法实测。 | 使用普通 MP4/MOV,建议 faststart;URL 主机需支持 Range 请求。 | InvalidRequestError |
| 422 | REFERENCE_URL_NOT_PUBLIC | 参考视频 URL 不是公网 HTTPS 地址。 | 使用无需登录的公网 HTTPS 直链,端口为 443。 | InvalidRequestError |
| 422 | CONTENT_TYPE_MISMATCH | 参考视频 URL 返回的内容不是所需的视频格式。 | 确认链接直接返回 MP4/MOV 字节,而非网页或图片。 | InvalidRequestError |
| 422 | REFERENCE_VIDEO_TOO_LARGE | 参考视频超过文件大小上限。 | 公网 URL 上限为 200 MiB,控制台上传上限为 32 MiB;压缩或裁剪后重新预览。 | InvalidRequestError |
| 429 | REFERENCE_PROBE_BUSY | 同时实测的参考视频过多。 | 按 retry_after_seconds 稍后重试;本次未扣费。 | RateLimitError |
| 400 | INSUFFICIENT_BALANCE | 余额不足以支付本次任务。 | 到控制台「钱包」充值或兑换后重试。 | InvalidRequestError |
| 400 | LEGACY_ASSET_REFERENCE_RETIRED | 素材 ID 引用已退役。 | 在同一次请求中使用 referenceMode + referenceImages(公网 HTTPS)。 | InvalidRequestError |
| 404 | NOT_FOUND | 任务不存在,或属于其他账户。 | 确认任务 ID 与密钥属于同一账户。 | InvalidRequestError |
| 409 | OUTPUT_NOT_READY | 输出尚未就绪。 | 继续按 poll_after_ms 轮询任务至终态。 | InvalidRequestError |
| 410 | OUTPUT_EXPIRED | 输出的下载期限(成功后 24 小时)已过。 | 请及时保存输出;过期后需重新生成。可用详情里的 output_expires_at 显示倒计时。 | OutputExpiredError |
图片任务失败码
图片任务以 status=failed 结束时,读取 error_code 并对照下表。失败的任务全额退款。SDK 会抛出带同一错误码的 GenerationFailedError。
| 错误码 | 含义 |
|---|---|
| CONTENT_POLICY_REJECTED | 内容未通过审核,请调整内容后重新提交。 |
| REFERENCE_INPUT_INVALID | 素材不符合要求,请检查格式、大小及模型支持的参数。 |
| REFERENCE_SOURCE_UNREACHABLE | 素材链接无法读取,请检查链接有效期或重新上传。 |
| REFERENCE_SERVICE_UNAVAILABLE | 素材处理服务暂不可用,请携带任务编号联系支持;无需因此反复换图。 |
| GENERATION_INPUT_INVALID | 生成参数不符合模型要求,请检查输入。 |
| GENERATION_RATE_LIMITED | 生成服务暂时限流,请稍后再试。 |
| GENERATION_REJECTED | 生成请求被拒绝,请携带任务编号联系支持核实原因。 |
| GENERATION_SERVICE_UNAVAILABLE | 生成服务暂不可用,请稍后再试。 |
| GENERATION_FAILED | 任务未能完成,请携带任务编号联系支持。 |
仅在控制台返回的错误码
| HTTP | 错误码 | 含义 | 建议处理方式 |
|---|---|---|---|
| 400 | REFERENCE_UPLOAD_NOT_FOUND | 本地上传引用不存在、已过期或不属于当前账户。 | 在在线测试中重新上传后再运行(上传短时有效)。 |
| 429 | UPLOAD_QUOTA_EXCEEDED | 未使用的上传数量达到上限。 | 先运行使用这些上传的任务,或等待它们过期后重试。 |
| 429 | WEBHOOK_ENDPOINT_LIMIT | Webhook 端点数量达到上限。 | 删除或停用不再使用的端点。 |
| 400 | INVALID_WEBHOOK_URL | 回调 URL 不是可公网访问的 HTTPS 地址。 | 使用公网 HTTPS 地址;内网或回环地址会被拒绝。 |