Sora 2 异步 API 采用标准的异步处理机制,适合需要更精细控制视频生成流程的场景。与同步流式 API 不同,异步 API 将视频生成分为三个独立步骤,让您可以更灵活地管理任务状态和下载时机。
异步 API 特别适合批量处理、后台任务、以及需要长时间等待的场景。如果您需要实时进度反馈,建议使用同步流式 API。
核心特性
独立的任务管理
提交后获得任务 ID,可随时查询状态
完整流程
异步 API 采用三步流程:
第一步:提交请求
POST /v1/videos
↓
返回 video_id
第二步:轮询状态(建议每 30 秒)
GET /v1/videos/{video_id}
↓
submitted → in_progress → completed
第三步:下载视频
GET /v1/videos/{video_id}/content
↓
保存 MP4 文件
典型生成时间:3-5 分钟。建议轮询间隔设置为 30 秒,最长等待时间设置为 10 分钟。
模型定价
| 模型名 | 描述 | 分辨率 | 价格 | 稳定性 |
|---|
sora_video2 | 默认竖屏版本 | 720 × 1280 | $0.12/次 | 高 |
sora_video2-landscape | 横屏版本 | 1280 × 720 | $0.12/次 | 高 |
sora_video2-15s | 竖屏15s 视频 | 720 × 1280 | $0.12/次 | 高 |
sora_video2-landscape-15s | 横屏 15s 视频 | 1280 × 720 | $0.12/次 | 高 |
sora-2-pro | Pro账号版本 | 1024 × 1792,1792 × 1024 | $0.8/次 | 正常可用了! |
- 推荐异步调用,各种错误而不计费;
- 若同步调用,则支持流式输出查看进度;
- 视频存储时效为 1 天,请及时转存或下载;
- sora 2 普通版本的分辨率输出其实为 704 px(而非 720 px),是官方的实际表现;
端点地址
https://api.apiyi.com/v1/videos
第一步:提交视频生成请求
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|
prompt | string | ✅ | 视频生成的文本描述,建议详细描述场景、动作、风格 |
model | string | ✅ | 固定值:sora-2 |
size | string | ✅ | 1280x720(横屏)或 720x1280(竖屏) |
seconds | string | ✅ | 视频时长,可选值:10 或 15 |
input_reference | file | ❌ | 参考图片文件(PNG/JPG/JPEG),可选,用于图生视频 |
文生视频示例
curl -X POST "https://api.apiyi.com/v1/videos" \
-H "Content-Type: multipart/form-data" \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "model=sora-2" \
-F "prompt=一只可爱的金毛犬在公园草地上追逐飞盘,阳光明媚,背景是绿树和蓝天" \
-F "size=1280x720" \
-F "seconds=10"
图生视频示例
支持上传参考图片,生成基于图片的视频。
curl -X POST "https://api.apiyi.com/v1/videos" \
-H "Content-Type: multipart/form-data" \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "model=sora-2" \
-F "prompt=参考配图,使得动物们活跃起来,在场地里绕场一周的追逐" \
-F "size=1280x720" \
-F "seconds=10" \
-F "input_reference=@/path/to/image.png"
响应格式
{
"id": "video_abc123def456",
"status": "submitted",
"progress": 0,
"prompt": "一只可爱的金毛犬在公园草地上追逐飞盘,阳光明媚,背景是绿树和蓝天",
"model": "sora-2",
"size": "1280x720",
"seconds": "10",
"created_at": 1704067200,
"url": null,
"completed_at": null
}
第二步:轮询查询视频状态
提交请求后,需要定期轮询查询视频生成状态。
请求方式
GET /v1/videos/{video_id}
查询示例
curl -X GET "https://api.apiyi.com/v1/videos/video_abc123def456" \
-H "Authorization: Bearer YOUR_API_KEY"
状态说明
| 状态 | 说明 | 下一步操作 |
|---|
submitted | 请求已提交,等待处理 | 继续轮询查询 |
in_progress | 视频生成中 | 继续轮询查询,可查看进度百分比 |
completed | 视频生成完成 | 可以下载视频 |
failed | 视频生成失败 | 检查错误信息,重新提交 |
生成中的响应示例
{
"id": "video_abc123def456",
"status": "in_progress",
"progress": 45,
"prompt": "一只可爱的金毛犬在公园草地上追逐飞盘,阳光明媚,背景是绿树和蓝天",
"model": "sora-2",
"size": "1280x720",
"seconds": "10",
"created_at": 1704067200,
"url": null,
"completed_at": null
}
完成后的响应示例
{
"id": "video_abc123def456",
"status": "completed",
"progress": 100,
"prompt": "一只可爱的金毛犬在公园草地上追逐飞盘,阳光明媚,背景是绿树和蓝天",
"model": "sora-2",
"size": "1280x720",
"seconds": "10",
"created_at": 1704067200,
"url": "https://api.apiyi.com/v1/videos/video_abc123def456/content",
"completed_at": 1704067500
}
第三步:下载生成的视频
视频生成完成后(status 为 completed),可以下载视频文件。
请求方式
GET /v1/videos/{video_id}/content
下载示例
curl -X GET "https://api.apiyi.com/v1/videos/video_abc123def456/content" \
-H "Authorization: Bearer YOUR_API_KEY" \
-o video.mp4
视频文件可能在一段时间后过期,建议生成完成后立即下载并保存到本地。
完整流程示例
以下是完整的三步流程集成示例:
import requests
import time
import os
from datetime import datetime
# API 配置
BASE_URL = "https://api.apiyi.com/v1/videos"
API_KEY = "YOUR_API_KEY"
# 参数配置
IMAGE_PATH = './dog-and-cat.png' # 参考图片路径,设为 None 则为文生视频
PROMPT = '参考配图,使得动物们活跃起来,在场地里绕场一周的追逐'
MODEL = 'sora-2'
SIZE = '1280x720'
SECONDS = '10'
# 轮询配置
POLL_INTERVAL = 30
MAX_WAIT_TIME = 600
def step1_submit_request():
"""第一步:提交视频生成请求"""
print("=" * 60)
print("第一步:提交视频生成请求")
print("=" * 60)
files = {
'prompt': (None, PROMPT),
'model': (None, MODEL),
'size': (None, SIZE),
'seconds': (None, SECONDS)
}
headers = {
'Accept': 'application/json',
'Authorization': API_KEY
}
# 如果有图片,添加到请求中
if IMAGE_PATH and os.path.exists(IMAGE_PATH):
print(f"模式:图片生成视频")
print(f"图片: {IMAGE_PATH}")
with open(IMAGE_PATH, 'rb') as f:
files['input_reference'] = (
os.path.basename(IMAGE_PATH),
f,
'image/png'
)
response = requests.post(BASE_URL, headers=headers, files=files)
else:
print(f"模式:文字生成视频")
response = requests.post(BASE_URL, headers=headers, files=files)
if response.status_code == 200:
result = response.json()
video_id = result.get('id')
print(f"✅ 请求提交成功!")
print(f" 视频ID: {video_id}")
print(f" 状态: {result.get('status')}")
print(f" 预计生成时间: 3-5 分钟")
return video_id
else:
print(f"❌ 请求失败: {response.status_code}")
print(f" 响应: {response.text}")
return None
def step2_poll_status(video_id):
"""第二步:轮询查询视频生成状态"""
print("\n" + "=" * 60)
print("第二步:查询视频生成状态")
print("=" * 60)
headers = {'Authorization': API_KEY}
status_url = f"{BASE_URL}/{video_id}"
start_time = time.time()
while True:
elapsed_time = time.time() - start_time
if elapsed_time > MAX_WAIT_TIME:
print(f"⏱️ 超时:已等待 {MAX_WAIT_TIME} 秒")
return False
response = requests.get(status_url, headers=headers)
if response.status_code == 200:
result = response.json()
status = result.get('status')
progress = result.get('progress', 0)
print(f"\n🔍 查询状态... (已等待 {int(elapsed_time)} 秒)")
print(f" 状态: {status}")
print(f" 进度: {progress}%")
if status == 'completed':
print(f"✅ 视频生成完成!")
print(f" 视频URL: {result.get('url')}")
return True
elif status == 'failed':
print(f"❌ 视频生成失败")
return False
else:
print(f"⏳ 等待 {POLL_INTERVAL} 秒后继续查询...")
time.sleep(POLL_INTERVAL)
else:
print(f"❌ 状态查询失败: {response.status_code}")
time.sleep(POLL_INTERVAL)
def step3_download_video(video_id, output_path=None):
"""第三步:下载生成的视频"""
print("\n" + "=" * 60)
print("第三步:下载视频")
print("=" * 60)
if output_path is None:
output_path = f"sora_video_{video_id.split('_')[-1]}.mp4"
headers = {'Authorization': API_KEY}
content_url = f"{BASE_URL}/{video_id}/content"
print(f"📥 开始下载视频...")
response = requests.get(content_url, headers=headers, stream=True)
if response.status_code == 200:
total_size = int(response.headers.get('content-length', 0))
with open(output_path, 'wb') as f:
if total_size == 0:
f.write(response.content)
else:
downloaded = 0
for chunk in response.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
downloaded += len(chunk)
percent = (downloaded / total_size) * 100
print(f"\r 下载进度: {percent:.1f}%", end='')
print(f"\n✅ 视频下载成功!")
print(f" 保存路径: {os.path.abspath(output_path)}")
print(f" 文件大小: {os.path.getsize(output_path)} 字节")
return True
else:
print(f"❌ 下载失败: {response.status_code}")
return False
def main():
"""完整的异步流程"""
print("\n🎬 开始 Sora-2 视频生成完整流程")
print(f"⏰ 开始时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
# 第一步:提交请求
video_id = step1_submit_request()
if not video_id:
print("\n❌ 流程终止:视频请求提交失败")
return
# 第二步:轮询状态
success = step2_poll_status(video_id)
if not success:
print("\n❌ 流程终止:视频生成未完成")
return
# 第三步:下载视频
success = step3_download_video(video_id)
if success:
print("\n" + "=" * 60)
print("🎉 完整流程执行成功!")
print("=" * 60)
print(f"⏰ 结束时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
if __name__ == "__main__":
main()
最佳实践
Prompt 编写建议
好的 Prompt 应该包含:场景描述、主体动作、镜头风格、艺术风格。
优秀示例:
一只可爱的金毛犬在绿色草地上追逐红色飞盘,阳光明媚,
背景是蓝天白云和绿树,运动流畅,特写镜头跟随犬的动作,
电影级画质,暖色调
不佳示例:
参考图片建议
- 分辨率:建议 1280x720 或更高
- 格式:PNG 或 JPG
- 文件大小:< 10MB
- 内容:清晰、主体明确、光线良好
- 匹配度:图片内容应与 prompt 描述相关
轮询策略建议
推荐设置
- 轮询间隔:30 秒
- 最长等待:10 分钟(600 秒)
- 典型耗时:3-5 分钟
避免设置
- 轮询间隔:< 30 秒(可能触发限流)
- 最长等待:< 5 分钟(可能提前放弃)
错误重试策略
import time
def retry_with_backoff(func, max_retries=3):
"""指数退避重试策略"""
for i in range(max_retries):
try:
return func()
except Exception as e:
if i == max_retries - 1:
raise
wait_time = 2 ** i # 1s, 2s, 4s
print(f"重试 {i+1}/{max_retries},等待 {wait_time} 秒...")
time.sleep(wait_time)
配额和限制
| 限制项 | 值 | 说明 |
|---|
| 请求速率 | 10 次/分钟 | 超过会返回 429 错误 |
| 并发任务 | 5 个 | 同时处理的视频数量 |
| 视频时长 | 10 或 15 秒 | 不支持其他时长 |
| 图片大小 | < 10MB | 建议 < 5MB |
| Prompt 长度 | < 1000 字符 | 建议 100-300 字符 |
错误处理
常见错误码
| 状态码 | 说明 | 解决方案 |
|---|
| 200 | 成功 | - |
| 400 | 请求参数错误 | 检查必填参数是否完整 |
| 401 | 认证失败 | 检查 API Key 是否正确 |
| 403 | 无权限 | 检查 API Key 是否有效或余额不足 |
| 404 | 资源不存在 | 检查 video_id 是否正确 |
| 429 | 请求过于频繁 | 增加轮询间隔 |
| 500 | 服务器错误 | 稍后重试 |
常见问题
通常需要 3-5 分钟,具体时间取决于服务器负载和视频复杂度。建议设置轮询间隔为 30 秒,最长等待时间为 10 分钟。
- 异步 API:三步流程(提交→轮询→下载),适合批量处理和后台任务,需要自己管理轮询逻辑
- 同步 API:流式输出,实时返回进度,适合需要即时反馈的场景
详见:同步流式 API 文档
可以,支持最多 50 个并发任务(不够用可以联系技术客服加)。您可以同时提交多个请求,分别轮询它们的状态。注意不要超过请求速率限制(10 次/分钟)。
建议视频生成完成后立即下载,避免文件过期。具体保存时长请咨询技术支持。
检查响应中的错误信息,常见原因:
- 内容违规(修改 prompt 或更换图片)
- 配额不足(充值或升级套餐)
- 参数错误(检查参数格式和值)
- 服务器负载过高(稍后重试)
相关资源
飞书版本的 Sora 2 异步调用文档
查看飞书文档可下载示例代码包
API 基础手册
了解 API 认证、请求格式等基础知识