文档

文档

视频生成

使用 Google Veo 3.1 系列将文本或图像转换为视频。提供两种 API 形式:一种是一次性同步端点,会阻塞等待视频片段就绪;另一种是用于生产工作负载的提交并轮询异步端点组合。

端点:POST /v1/video/generations(同步,先介绍),以及 POST /v1/videos + GET /v1/videos/{id}(异步,推荐用于生产环境)。生成时间视模型和时长而定,从 30 秒到数分钟不等——使用同步端点时,请将客户端超时设置得足够长(600s 是安全值)。

文本生成视频

传入 prompt 并选择模型。aspect_ratio 可选。

import requests

resp = requests.post(
    "https://api.kunavo.com/v1/video/generations",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={
        "model": "veo-3",
        "prompt": "a cinematic dolly-in on a red origami crane unfolding, soft light",
        "aspect_ratio": "16:9",
    },
    timeout=600,  # video generation can take minutes
)
print(resp.json()["data"][0]["url"])

duration(秒)用于在按秒计费的模型(Seedance 系列模型和 Wan 2.7)上设置片段时长。Veo 模型会忽略它;每个 Veo 片段都是 8 秒,按视频计费。

# The models billed per second take a clip length: here 5 seconds of
# Seedance 2. Leave "duration" out and these models make a 5-second clip.
resp = requests.post(
    "https://api.kunavo.com/v1/video/generations",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={
        "model": "seedance-2",
        "prompt": "a paper crane unfolds into a flock of birds over a city at dawn",
        "duration": 5,
        "aspect_ratio": "16:9",
    },
    timeout=600,
)
print(resp.json()["data"][0]["url"])

图像生成视频

添加 image_url,Veo 就会以它为基础生成动画——默认情况下,静态图像会成为视频的第一帧。

# Image-to-video: animate a still image. The source image can be an
# https URL, or inline base64 — Kunavo hosts it for the model automatically.
resp = requests.post(
    "https://api.kunavo.com/v1/video/generations",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={
        "model": "veo-3",
        "prompt": "the crane gently lifts off the desk",
        "image_url": "https://your-cdn.com/source.png",
    },
    timeout=600,
)
print(resp.json()["data"][0]["url"])
image_url 接受 https:// URL 或内联 data: base64 URI。运行模型前,Kunavo 会自动解码 base64 并将其托管到 Kunavo CDN。

首帧、尾帧和参考图

image_mode 控制 Veo 如何使用图像。传入 image_urls(数组)可发送多张图像。

  • frame(默认)— 一张图像作为首帧;两张图像分别作为首帧和尾帧,Veo 会生成两帧之间的过渡。
  • reference — 最多三张图像可用作风格和主体参考。它们会引导生成效果,但不会作为视频帧出现。
# First + last frame: pass two images and Veo fills in the motion.
resp = requests.post(
    "https://api.kunavo.com/v1/video/generations",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={
        "model": "veo-3",
        "prompt": "a smooth transition between the two poses",
        "image_urls": [
            "https://your-cdn.com/first.png",
            "https://your-cdn.com/last.png",
        ],
        "image_mode": "frame",
    },
    timeout=600,
)

上传源帧

如果只有本地文件,请通过 POST /v1/files 上传一次,并重复使用返回的永久 URL。

# No public URL? Upload the still first, then animate it.
with open("frame.png", "rb") as f:
    up = requests.post(
        "https://api.kunavo.com/v1/files",
        headers={"Authorization": f"Bearer {API_KEY}"},
        files={"file": f},
    ).json()

resp = requests.post(
    "https://api.kunavo.com/v1/video/generations",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={
        "model": "veo-3",
        "prompt": "slow push-in, volumetric light",
        "image_url": up["url"],
    },
    timeout=600,
)

参数

参数类型备注
model字符串(必填)来自 /v1/models 的视频模型标识。
prompt字符串(必填)镜头的文本描述。
image_urlstring用于图生视频的单张源图像。URL 或 data: URI。
image_urlsstring[]多个源图像(Veo)。优先级高于 image_url。
image_modestringVeo:"frame"(默认 — 首帧/尾帧)或 "reference"(风格参考图)。
durationint按秒计费模型的片段时长,单位为秒,省略时为 5:Seedance 2、Seedance 2 Fast 和 Seedance 2.0 Mini 支持 4–15,Seedance 2.5 支持 4–30,Wan 2.7 支持 2–15。超出模型范围的时长会被拒绝,并返回 400。Veo 会忽略该参数:每个 Veo 片段都是 8 秒。
aspect_ratiostring例如 "16:9"、"9:16"、"1:1"。
resolutionstring模型提供多个档位时使用,例如 "720p"、"1080p"。
inputobject备用方案 — 见下文的 Raw input。

原始输入直通选项

在按秒计费的模型上,input 会按原样发送至上游,替代我们的适配器原本会构建的输入。Veo 模型会忽略它。

决定价格的字段是例外:resolution 始终会以该模型的某个档位发送(未提供该字段或其值不是该模型的档位时,发送默认档位),duration 必须是该模型范围内的整数秒数(其他任何值都会被拒绝,并返回 400;未提供该字段时发送 5)。设置了 input 时,不会读取请求自身的 resolution 和 duration。

视频模型

标识符(slug)提供商备注
veo-3GoogleVeo 3.1 Fast — 比 Quality 更快、更便宜,原生支持音频。
veo-3-qualityGoogleVeo 3.1 Quality — 最高保真度。
veo-3-liteGoogleVeo 3.1 Lite — 面向预览的经济档。
seedance-2-5ByteDanceSeedance 2.5 — 支持最长 30 秒的视频片段和多模态参考,按秒计费。
seedance-2ByteDanceSeedance 2 — 支持多镜头一致性,最高 1080p,按秒计费。
seedance-2-fastByteDanceSeedance 2 Fast — 经济档,最高 720p,按秒计费。
seedance-2-miniByteDanceSeedance 2.0 Mini — 最低价档,仅支持 480p/720p,适用于草稿和批量生成。
wan-2-7AlibabaWan 2.7 — 电影质感的文本生成视频,按秒计费。

请始终查看 /models,以获取实时模型列表和各模型定价。

延迟和超时

  • Kunavo 最多轮询上游任务 540 秒,之后会返回 504。
  • 快速档(Veo 3.1 Fast / Lite):通常为 30–90 秒。
  • 高质量档和较长时长:2–5 分钟。
  • 将 HTTP 客户端超时设置为至少 600s。
  • 如果网络不稳定或使用移动客户端,请优先使用异步 API——提交请求会在数秒内返回,然后你可以轮询获取结果。

异步 API(提交 + 轮询)

端点:POST /v1/videos + GET /v1/videos/{id}。它们返回的任务对象使用 OpenAI 视频对象的字段名称和状态值,并额外包含一个存放视频片段 URL 的 output 字段。请求体为包含上述参数的 JSON。

上面的同步端点会保持 HTTP 连接打开,最长可达九分钟——适合一次性脚本,但在移动网络上不可靠,也会降低服务器效率。异步端点组合会立即返回一个 vid_* ID;你可以轮询 GET /v1/videos/{id},直到 status 变为 completed 或 failed。模型相同、价格相同,归档的 URL 也相同。

import requests, time

# 1. Submit — returns immediately with a task id. No long-lived connection.
submit = requests.post(
    "https://api.kunavo.com/v1/videos",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        # Optional: retrying with the same key inside ~24h returns the
        # original task rather than submitting again.
        "Idempotency-Key": "my-task-uuid",
    },
    json={
        "model": "veo-3",
        "prompt": "a cinematic dolly-in on a red origami crane",
        "aspect_ratio": "16:9",
    },
    timeout=60,
).json()

task_id = submit["id"]              # "vid_abc..."
status  = submit["status"]          # "queued"

# 2. Poll until terminal. Recommended cadence: 5s, backing off to 30s.
while status not in ("completed", "failed"):
    time.sleep(5)
    r = requests.get(
        f"https://api.kunavo.com/v1/videos/{task_id}",
        headers={"Authorization": f"Bearer {API_KEY}"},
        timeout=30,
    ).json()
    status = r["status"]

if status == "failed":
    raise RuntimeError(r["error"]["message"])
print(r["output"]["url"])

使用 OpenAI SDK 发送该请求体时,请使用 client.post,并按下文所示使用 client.get 轮询。SDK 自带的 client.videos.create 在这里无法使用:它只接受 Sora 的参数,并会以 multipart 表单的形式发送这些参数(Python SDK 自版本 2.27.0 起),而此端点会以 400 错误拒绝这种请求。

import time
from openai import OpenAI

client = OpenAI(api_key=API_KEY, base_url="https://api.kunavo.com/v1")

# The same JSON body, sent with the client's own post().
task = client.post(
    "/videos",
    body={
        "model": "veo-3",
        "prompt": "a cinematic dolly-in on a red origami crane",
        "aspect_ratio": "16:9",
    },
    # object hands back the JSON as parsed. Passing dict instead raises
    # after the task has been created.
    cast_to=object,
    options={"headers": {"Idempotency-Key": "my-task-uuid"}},
)

while task["status"] not in ("completed", "failed"):
    time.sleep(5)
    task = client.get(f"/videos/{task['id']}", cast_to=object)

if task["status"] == "failed":
    raise RuntimeError(task["error"]["message"])
print(task["output"]["url"])

响应格式

字段类型备注
idstring以 vid_ 为前缀的任务 ID。在上游发生更改时保持稳定。
objectstring"video".
statusstringqueued | in_progress | completed | failed。
modelstring提交时指定的模型 slug。
created_atint我们接受提交请求时的 Unix 秒数。
completed_atint | null进入终态时的 Unix 秒数 ——任务待处理时为 null。
expires_atint提交后满 30 天时的 Unix 秒数:至少在此之前都可以轮询该任务。其结果 URL 不会过期。
progressint0–100。任务结束前当前报告值为 0,结束后为 100。
outputobject | null完成时返回 {url, urls[], duration_seconds, resolution}。duration_seconds 是向模型请求的片段时长,Veo 为 null;resolution 是片段的分辨率档位,没有记录时为 null。
errorobject | null失败时返回 {code, message}。

请求头与约定

  • Idempotency-Key(可选,最多 128 个字符)— 在同一账户下使用相同的密钥提交两次,会返回原任务而不会创建重复任务。适用于重试循环。
  • 全新提交时,POST /v1/videos 返回 202 Accepted;幂等键命中并重放先前结果时,返回 200 OK。
  • GET /v1/videos/{id} 按所有者进行范围限定:查询属于其他账户的任务会返回 404——我们绝不会确认其他用户的任务 ID 是否存在。
  • 建议的轮询间隔:5 s,并采用指数退避,最长间隔为 30 s。任务通常会在 30 s – 5 min 内完成,具体取决于模型和分辨率。

何时使用哪种方式

同步 /v1/video/generations异步 /v1/videos
适用场景一次性脚本、笔记本适用于生产环境、移动端和长时间运行的任务
网络连接最长保持 9 分钟几秒内提交;按你的时间安排轮询
故障恢复丢失响应 = 丢失任务expires_at 到期前随时重新查询该 ID
并发数每次调用占用一个服务器工作进程提交后立即释放连接
响应格式OpenAI /images/generations 格式OpenAI /videos 格式

响应与存储

响应采用 OpenAI 的标准格式 — data[].url。URL 是一个永久的 files.kunavo.com 链接:Kunavo 会将每个结果归档到自己的 CDN,因此与原始上游 URL 不同,它永不过期。每个视频片段也会显示在 /app/assets 中。

接下来