curl --request POST \
--url https://api.apiyi.com/v1/videos \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form model=sora-2 \
--form 'prompt=Animate this scene: gentle waves lapping, leaves swaying, cinematic camera push-in' \
--form input_reference='@example-file'{
"id": "video_abc123def456",
"object": "video",
"model": "sora-2",
"status": "queued",
"progress": 0,
"created_at": 1712697600,
"completed_at": 1712697900,
"size": "1280x720",
"seconds": "8",
"quality": "standard"
}图生视频 API 参考
Sora 2 图生视频 API 参考与在线调试 — multipart 上传 input_reference 参考图,让静态画面动起来。
curl --request POST \
--url https://api.apiyi.com/v1/videos \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: multipart/form-data' \
--form model=sora-2 \
--form 'prompt=Animate this scene: gentle waves lapping, leaves swaying, cinematic camera push-in' \
--form input_reference='@example-file'{
"id": "video_abc123def456",
"object": "video",
"model": "sora-2",
"status": "queued",
"progress": 0,
"created_at": 1712697600,
"completed_at": 1712697900,
"size": "1280x720",
"seconds": "8",
"quality": "standard"
}Documentation Index
Fetch the complete documentation index at: https://docs.apiyi.com/llms.txt
Use this file to discover all available pages before exploring further.
Bearer sk-xxx),上传一张参考图、输入 prompt、选择 model / size / seconds 后一键发送即可。- 上传图片的像素尺寸必须与请求的
size字段完全一致(如size=1280x720则图片必须是 1280×720) - 不一致会返回 400:
Inpaint image must match the requested width and height - 建议先用 ffmpeg / Pillow 在本地裁切到目标尺寸再上传
- Content-Type 必须是
multipart/form-data(不是 JSON) - 仅支持 1 个文件,字段名固定
input_reference - 接受格式:
image/jpeg/image/png/image/webp
代码示例
Python(OpenAI SDK 直连)
from openai import OpenAI
import time
client = OpenAI(
api_key="sk-your-api-key",
base_url="https://api.apiyi.com/v1"
)
# 第 1 步:提交(OpenAI SDK 用 input_reference 参数自动走 multipart)
with open("./reference.png", "rb") as f:
video = client.videos.create(
model="sora-2",
prompt="Animate this scene: gentle waves lapping against the shore, leaves swaying in the breeze",
seconds="8",
size="1280x720",
input_reference=f
)
print(f"Video ID: {video.id}, status: {video.status}")
# 第 2 步:轮询
while True:
video = client.videos.retrieve(video.id)
print(f"Status: {video.status}, progress: {getattr(video, 'progress', 0)}%")
if video.status == "completed":
break
if video.status == "failed":
raise RuntimeError(f"Generation failed: {video}")
time.sleep(15)
# 第 3 步:下载
client.videos.download_content(video.id).write_to_file("output.mp4")
print("Saved: output.mp4")
Python(原生 requests + multipart)
import requests
import time
API_KEY = "sk-your-api-key"
BASE_URL = "https://api.apiyi.com/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
# 第 1 步:multipart 上传(注意:image 分辨率必须等于 size)
with open("./reference.png", "rb") as f:
resp = requests.post(
f"{BASE_URL}/videos",
headers=HEADERS, # 不要手动加 Content-Type,requests 会自动处理 multipart 边界
data={
"model": "sora-2",
"prompt": "Animate this scene with cinematic camera push-in, soft golden hour lighting",
"seconds": "8",
"size": "1280x720"
},
files={
"input_reference": ("reference.png", f, "image/png")
},
timeout=60 # multipart 上传大图可能慢,超时建议 60 秒
).json()
video_id = resp["id"]
print(f"Video ID: {video_id}, status: {resp['status']}")
# 第 2 步:轮询
deadline = time.time() + 900
while time.time() < deadline:
status_resp = requests.get(f"{BASE_URL}/videos/{video_id}", headers=HEADERS).json()
print(f"Status: {status_resp['status']}, progress: {status_resp.get('progress', 0)}%")
if status_resp["status"] == "completed":
break
if status_resp["status"] == "failed":
raise RuntimeError(f"Generation failed: {status_resp}")
time.sleep(15)
# 第 3 步:下载
with requests.get(f"{BASE_URL}/videos/{video_id}/content", headers=HEADERS, stream=True) as r:
r.raise_for_status()
with open("output.mp4", "wb") as f:
for chunk in r.iter_content(chunk_size=8192):
f.write(chunk)
print("Saved: output.mp4")
cURL
{/* 第 1 步:multipart 上传 + 提交任务 */}
curl -X POST "https://api.apiyi.com/v1/videos" \
-H "Authorization: Bearer sk-your-api-key" \
-F "model=sora-2" \
-F "prompt=Animate this scene: gentle waves lapping, leaves swaying, cinematic" \
-F "seconds=8" \
-F "size=1280x720" \
-F "input_reference=@./reference.png;type=image/png"
{/* 第 2 步:轮询 */}
curl -X GET "https://api.apiyi.com/v1/videos/video_abc123" \
-H "Authorization: Bearer sk-your-api-key"
{/* 第 3 步:下载 */}
curl -X GET "https://api.apiyi.com/v1/videos/video_abc123/content" \
-H "Authorization: Bearer sk-your-api-key" \
-o output.mp4
Node.js(原生 fetch + FormData)
import fs from 'node:fs';
import { fileFromPath } from 'formdata-node/file-from-path';
import { FormData } from 'formdata-node';
const API_KEY = 'sk-your-api-key';
const BASE_URL = 'https://api.apiyi.com/v1';
// 第 1 步:multipart 上传
const form = new FormData();
form.set('model', 'sora-2');
form.set('prompt', 'Animate this scene with cinematic camera push-in, soft lighting');
form.set('seconds', '8');
form.set('size', '1280x720');
form.set('input_reference', await fileFromPath('./reference.png'));
const submitResp = await fetch(`${BASE_URL}/videos`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${API_KEY}` }, // 不要手动加 Content-Type
body: form
});
const { id: videoId } = await submitResp.json();
console.log(`Video ID: ${videoId}`);
// 第 2 步:轮询
let status = 'queued';
while (status !== 'completed' && status !== 'failed') {
await new Promise(r => setTimeout(r, 15000));
const data = await (await fetch(`${BASE_URL}/videos/${videoId}`, {
headers: { 'Authorization': `Bearer ${API_KEY}` }
})).json();
status = data.status;
console.log(`Status: ${status}, progress: ${data.progress ?? 0}%`);
}
if (status === 'failed') throw new Error('Generation failed');
// 第 3 步:下载
const contentResp = await fetch(`${BASE_URL}/videos/${videoId}/content`, {
headers: { 'Authorization': `Bearer ${API_KEY}` }
});
fs.writeFileSync('output.mp4', Buffer.from(await contentResp.arrayBuffer()));
console.log('Saved: output.mp4');
浏览器 JavaScript
{/* 仅作演示,生产请走后端代理避免 Key 泄露 */}
const fileInput = document.getElementById('refImage'); // <input type="file" />
const file = fileInput.files[0];
const form = new FormData();
form.append('model', 'sora-2');
form.append('prompt', 'Animate this scene, gentle motion');
form.append('seconds', '4');
form.append('size', '1280x720');
form.append('input_reference', file);
const submitResp = await fetch('https://api.apiyi.com/v1/videos', {
method: 'POST',
headers: { 'Authorization': 'Bearer sk-your-api-key' },
body: form
});
const { id } = await submitResp.json();
console.log('Video ID:', id);
{/* 轮询完成后,建议把视频 URL 交给后端代理处理,避免大文件直接在浏览器下载 */}
参数说明速查
| 参数 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
model | string | 是 | — | sora-2(720p 标准)或 sora-2-pro(720p / 1024p / 1080p 多档) |
prompt | string | 是 | — | 视频描述提示词,建议描述”如何让画面动起来”(镜头运动、物体动作、光线变化) |
seconds | string | 否 | "4" | 视频时长,字符串枚举:"4" / "8" / "12" |
size | string | 否 | 720x1280 | 输出分辨率,必须与 input_reference 图片像素完全一致 |
input_reference | file | 是 | — | 参考图文件,image/jpeg / image/png / image/webp,像素必须等于 size |
input_reference 字段必须通过 multipart 文件上传,不接受 URL 或 base64。参考图准备建议
本地裁切到精确像素
from PIL import Image
img = Image.open("source.jpg")
img = img.resize((1280, 720), Image.LANCZOS) # 或先 crop 再 resize 保留比例
img.save("reference.png")
ffmpeg -i source.jpg -vf "scale=1280:720" reference.png
响应格式
响应结构与 文生视频 完全相同:提交返回id + status: "queued",轮询返回进度,完成后通过 /v1/videos/{id}/content 下载 MP4。
{
"id": "video_abc123def456",
"object": "video",
"model": "sora-2",
"status": "queued",
"progress": 0,
"created_at": 1712697600,
"size": "1280x720",
"seconds": "8",
"quality": "standard"
}
Inpaint image must match the requested width and height—— 参考图像素与size不一致,最常见。客户端做好上传前的尺寸校验Invalid file format—— 上传的不是 jpeg / png / webp,或文件损坏Missing required parameter: input_reference—— multipart 字段名拼错(必须是input_reference,不是image或reference)seconds must be one of "4", "8", "12"—— 传了数字4而非字符串"4"
seconds 计费),并不会因为多上传了一张参考图额外收费。详见 概览页定价表。授权
在 API易控制台获取的 API Key(必须配置 Sora2官转 分组 + 按量计费)
请求体
模型 ID。sora-2 仅支持 720p;sora-2-pro 支持 720p / 1024p / 1080p
sora-2, sora-2-pro 视频生成提示词。重点描述如何让画面动起来:镜头运动、物体动作、光线变化
"Animate this scene: gentle waves lapping, leaves swaying, cinematic camera push-in"
参考图文件,作为视频的起始帧/视觉锚点。
- 接受格式:
image/jpeg/image/png/image/webp - 像素必须等于
size,否则报错Inpaint image must match the requested width and height - 仅支持 1 个文件,字段名固定
input_reference
视频时长,字符串枚举:"4" / "8" / "12"
4, 8, 12 输出分辨率,必须与 input_reference 图片像素完全一致:
sora-2(仅 720p):720x1280/1280x720sora-2-pro额外:1024x1792/1792x1024/1080x1920/1920x1080
720x1280, 1280x720, 1024x1792, 1792x1024, 1080x1920, 1920x1080 响应
任务已提交,返回 video_id 与 queued 状态
任务 ID,用于后续轮询和下载
"video_abc123def456"
对象类型,固定 video
"video"
本次任务使用的模型 ID
"sora-2"
任务状态:
queued—— 已提交,排队等待in_progress—— 正在生成completed—— 完成,可下载(/v1/videos/{id}/content)failed—— 失败(不计费),可重试
queued, in_progress, completed, failed "queued"
生成进度百分比(0–100),不严格线性
0
任务创建 Unix 时间戳(秒)
1712697600
任务完成 Unix 时间戳(秒),仅 completed 状态返回
1712697900
实际输出分辨率(与请求的 size 一致)
"1280x720"
实际生成时长(与请求的 seconds 一致)
"8"
画质档位(standard 对应 sora-2,high 对应 sora-2-pro)
"standard"
此页面对您有帮助吗?