文件
影片生成
使用 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 並將其託管於 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_url | string | 圖片轉影片使用的單張來源圖片。接受 URL 或 data: URI。 |
image_urls | string[] | 多張來源圖片(Veo)。優先於 image_url。 |
image_mode | string | Veo 可使用「frame」(預設,第一格/最後一格)或「reference」(風格參考圖)。 |
duration | int | 按秒計費模型的片段長度(秒),省略時為 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_ratio | string | 例如「16:9」、「9:16」、「1:1」。 |
resolution | string | 模型提供不同等級時使用,例如「720p」、「1080p」。 |
input | object | 緊急替代方案 — 請參閱下方的 Raw input。 |
原始輸入的替代方式
在按秒計費的模型上,input 會原樣傳送至上游,取代我們的轉接器原本會建立的輸入。Veo 模型會忽略它。
決定價格的欄位是例外:resolution 一律會以該模型的其中一個級距傳送(未提供此欄位或其值不是該模型的級距時,傳送預設級距),duration 必須是該模型範圍內的整數秒數(其他任何值都會遭到拒絕,並傳回 400;未提供此欄位時傳送 5)。設定了 input 時,不會讀取請求本身的 resolution 和 duration。
影片模型
| 識別碼(slug) | 提供者 | 備註 |
|---|---|---|
veo-3 | Veo 3.1 Fast — 比 Quality 更快、更便宜,支援原生音訊。 | |
veo-3-quality | Veo 3.1 Quality — 最高保真度。 | |
veo-3-lite | Veo 3.1 Lite — 適合預覽的經濟等級。 | |
seedance-2-5 | ByteDance | Seedance 2.5 — 最長 30 秒的影片片段、多模態參考素材、按秒計費。 |
seedance-2 | ByteDance | Seedance 2 — 多鏡頭一致性、最高 1080p、按秒計費。 |
seedance-2-fast | ByteDance | Seedance 2 Fast — 經濟等級、最高 720p、按秒計費。 |
seedance-2-mini | ByteDance | Seedance 2.0 Mini — 最便宜的等級,僅支援 480p/720p,適合草稿與大量生成。 |
wan-2-7 | Alibaba | Wan 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 拒絕該 multipart 請求。
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"])回應格式
| 欄位 | 類型 | 備註 |
|---|---|---|
id | string | 以 vid_ 為前綴的任務 ID。上游變更不會影響此 ID。 |
object | string | "video". |
status | string | queued | in_progress | completed | failed。 |
model | string | 你提交的模型 slug。 |
created_at | int | 我們接受提交時的 Unix 秒數。 |
completed_at | int | null | 進入終止狀態時的 Unix 秒數——待處理時為 null。 |
expires_at | int | 提交後滿 30 天時的 Unix 秒數:至少在此之前都可以輪詢該任務。其結果 URL 不會過期。 |
progress | int | 0–100。目前在任務結束前會回報 0,結束時則回報 100。 |
output | object | null | 完成時為 {url, urls[], duration_ |
error | object | null | 失敗時為 {code, message}。 |
標頭與慣例
Idempotency-Key(選填,最多 128 個字元)— 在同一帳戶中使用相同金鑰重複提交時,會傳回原有任務,不會建立重複任務。適用於重試迴圈。POST /v1/videos在首次提交時會傳回 202 Accepted;使用冪等金鑰重播先前結果時,則傳回 200 OK。GET /v1/videos/{id}僅限任務擁有者存取:若查詢屬於其他帳戶的任務,會傳回 404——我們絕不會確認其他人的任務 ID 是否存在。- 建議的輪詢間隔:5 秒,並使用指數退避,最長增至 30 秒。依模型和解析度而定,任務通常會在 30 秒至 5 分鐘內完成。
如何選擇
| 同步 /v1/ | 非同步 /v1/videos | |
|---|---|---|
| 最適合 | 一次性指令碼、Notebook | 正式環境、行動裝置、長時間執行的工作 |
| 網路 | 連線最多保持開啟 9 分鐘 | 幾秒內提交;按你的時間輪詢 |
| 失敗復原 | 失去回應 = 失去任務 | 在 expires_at 到期前,隨時重新查詢該 ID |
| 並行數 | 每次呼叫佔用一個伺服器工作程序 | 提交後立即釋放連線 |
| 回應格式 | OpenAI /images/ | OpenAI /videos 格式 |
回應與儲存
回應採用 OpenAI 標準格式 — data[].url。URL 是永久的 files.kunavo.com 連結:Kunavo 會將每個結果封存至自己的 CDN,因此不同於原始上游 URL,這些連結永不過期。每段影片也會顯示在 /app/assets。