跳转到主要内容
POST
/
v1
/
videos
图生视频:基于参考图生成视频任务
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.

右侧的交互式 Playground 支持直接在线调试。请在 Authorization 中填入你的 API Key(格式:Bearer sk-xxx),上传一张参考图、输入 prompt、选择 model / size / seconds 后一键发送即可。
场景说明:本页用于「基于参考图生成视频」——上传一张图片作为视频的起始帧/视觉锚点,让静态画面”动起来”。如果不需要参考图,请使用 文生视频接口(同一端点,JSON 请求体)。
⚠️ 参考图分辨率必须与 size 完全一致
  • 上传图片的像素尺寸必须与请求的 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 交给后端代理处理,避免大文件直接在浏览器下载 */}

参数说明速查

参数类型必填默认说明
modelstringsora-2(720p 标准)或 sora-2-pro(720p / 1024p / 1080p 多档)
promptstring视频描述提示词,建议描述”如何让画面动起来”(镜头运动、物体动作、光线变化)
secondsstring"4"视频时长,字符串枚举"4" / "8" / "12"
sizestring720x1280输出分辨率,必须与 input_reference 图片像素完全一致
input_referencefile参考图文件,image/jpeg / image/png / image/webp像素必须等于 size
详细的参数约束、可选值、示例请查看右侧 Playground 中的字段说明。input_reference 字段必须通过 multipart 文件上传,不接受 URL 或 base64。

参考图准备建议

1

确定目标分辨率

根据用途先选 size:竖屏 720x1280、横屏 1280x720、Pro 1080p 横屏 1920x1080 等。
2

本地裁切到精确像素

用 Pillow / ffmpeg 把图片裁切到目标尺寸:
from PIL import Image
img = Image.open("source.jpg")
img = img.resize((1280, 720), Image.LANCZOS)  # 或先 crop 再 resize 保留比例
img.save("reference.png")
或 ffmpeg 一行:
ffmpeg -i source.jpg -vf "scale=1280:720" reference.png
3

选合适的图片格式

优先 PNG(无损,适合插画 / 截图),照片类用 JPEG 节省体积,需要透明通道用 WebP。
4

prompt 聚焦「动作」而不是「画面」

参考图已经定了画面,prompt 应该重点描述如何让它动起来:镜头推拉、物体运动、光线变化、人物表情等。例:"Camera slowly pushes in, leaves gently swaying, sunlight flickering through branches"

响应格式

响应结构与 文生视频 完全相同:提交返回 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"
}
⚠️ 常见 400 错误
  • Inpaint image must match the requested width and height —— 参考图像素与 size 不一致,最常见。客户端做好上传前的尺寸校验
  • Invalid file format —— 上传的不是 jpeg / png / webp,或文件损坏
  • Missing required parameter: input_reference —— multipart 字段名拼错(必须是 input_reference,不是 imagereference
  • seconds must be one of "4", "8", "12" —— 传了数字 4 而非字符串 "4"
图生视频与文生视频单价相同(按 seconds 计费),并不会因为多上传了一张参考图额外收费。详见 概览页定价表

授权

Authorization
string
header
必填

在 API易控制台获取的 API Key(必须配置 Sora2官转 分组 + 按量计费)

请求体

multipart/form-data
model
enum<string>
默认值:sora-2
必填

模型 ID。sora-2 仅支持 720p;sora-2-pro 支持 720p / 1024p / 1080p

可用选项:
sora-2,
sora-2-pro
prompt
string
必填

视频生成提示词。重点描述如何让画面动起来:镜头运动、物体动作、光线变化

示例:

"Animate this scene: gentle waves lapping, leaves swaying, cinematic camera push-in"

input_reference
file
必填

参考图文件,作为视频的起始帧/视觉锚点。

  • 接受格式:image/jpeg / image/png / image/webp
  • 像素必须等于 size,否则报错 Inpaint image must match the requested width and height
  • 仅支持 1 个文件,字段名固定 input_reference
seconds
enum<string>
默认值:4

视频时长,字符串枚举"4" / "8" / "12"

可用选项:
4,
8,
12
size
enum<string>
默认值:720x1280

输出分辨率,必须与 input_reference 图片像素完全一致

  • sora-2(仅 720p):720x1280 / 1280x720
  • sora-2-pro 额外:1024x1792 / 1792x1024 / 1080x1920 / 1920x1080
可用选项:
720x1280,
1280x720,
1024x1792,
1792x1024,
1080x1920,
1920x1080

响应

任务已提交,返回 video_id 与 queued 状态

id
string

任务 ID,用于后续轮询和下载

示例:

"video_abc123def456"

object
string

对象类型,固定 video

示例:

"video"

model
string

本次任务使用的模型 ID

示例:

"sora-2"

status
enum<string>

任务状态:

  • queued —— 已提交,排队等待
  • in_progress —— 正在生成
  • completed —— 完成,可下载(/v1/videos/{id}/content
  • failed —— 失败(不计费),可重试
可用选项:
queued,
in_progress,
completed,
failed
示例:

"queued"

progress
integer

生成进度百分比(0–100),不严格线性

示例:

0

created_at
integer

任务创建 Unix 时间戳(秒)

示例:

1712697600

completed_at
integer

任务完成 Unix 时间戳(秒),仅 completed 状态返回

示例:

1712697900

size
string

实际输出分辨率(与请求的 size 一致)

示例:

"1280x720"

seconds
string

实际生成时长(与请求的 seconds 一致)

示例:

"8"

quality
string

画质档位(standard 对应 sora-2,high 对应 sora-2-pro)

示例:

"standard"