Appearance
API 能力 Sora 2 视频生成(异步调用) Sora 2 异步视频生成 API - 完整的三步流程:提交请求、轮询状态、下载视频
概述 Sora 2 异步 API 采用标准的异步处理机制,适合需要更精细控制视频生成流程的场景。与同步流式 API 不同,异步 API 将视频生成分为三个独立步骤,让您可以更灵活地管理任务状态和下载时机。 异步 API 特别适合批量处理、后台任务、以及需要长时间等待的场景。如果您需要实时进度反馈,建议使用同步流式 API。
核心特性 独立的任务管理 提交后获得任务 ID,可随时查询状态 灵活的轮询策略 自定义轮询间隔,避免不必要的请求 可靠的视频下载 生成完成后独立下载,支持断点续传 批量处理支持 同时提交多个任务,并发处理更高效
完整流程 异步 API 采用三步流程:
Copy 第一步:提交请求 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 分钟。
端点地址
Copy 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
Python
JavaScript
Copy curl -X POST "https://api.apiyi.com/v1/videos"
-H "Authorization: YOUR_API_KEY"
-H "Accept: application/json"
-F "prompt=一只可爱的金毛犬在公园草地上追逐飞盘,阳光明媚,背景是绿树和蓝天"
-F "model=sora-2"
-F "size=1280x720"
-F "seconds=10"
图生视频示例 支持上传参考图片,生成基于图片的视频。
cURL
Python
Copy curl -X POST "https://api.apiyi.com/v1/videos"
-H "Authorization: YOUR_API_KEY"
-H "Accept: application/json"
-F "prompt=参考配图,使得动物们活跃起来,在场地里绕场一周的追逐"
-F "model=sora-2"
-F "size=1280x720"
-F "seconds=10"
-F "input_reference=@/path/to/image.png"
响应格式
Copy { "id": "video_abc123def456", "status": "submitted", "progress": 0, "prompt": "一只可爱的金毛犬在公园草地上追逐飞盘,阳光明媚,背景是绿树和蓝天", "model": "sora-2", "size": "1280x720", "seconds": "10", "created_at": 1704067200, "url": null, "completed_at": null }
第二步:轮询查询视频状态 提交请求后,需要定期轮询查询视频生成状态。
请求方式
Copy GET /v1/videos/
查询示例
cURL
Python
JavaScript
Copy curl -X GET "https://api.apiyi.com/v1/videos/video_abc123def456"
-H "Authorization: YOUR_API_KEY"
状态说明 状态 说明 下一步操作 submitted 请求已提交,等待处理 继续轮询查询 in_progress 视频生成中 继续轮询查询,可查看进度百分比 completed 视频生成完成 可以下载视频 failed 视频生成失败 检查错误信息,重新提交
生成中的响应示例
Copy { "id": "video_abc123def456", "status": "in_progress", "progress": 45, "prompt": "一只可爱的金毛犬在公园草地上追逐飞盘,阳光明媚,背景是绿树和蓝天", "model": "sora-2", "size": "1280x720", "seconds": "10", "created_at": 1704067200, "url": null, "completed_at": null }
完成后的响应示例
Copy { "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),可以下载视频文件。
请求方式
Copy GET /v1/videos/{video_id}/content
下载示例
cURL
Python
JavaScript
Copy curl -X GET "https://api.apiyi.com/v1/videos/video_abc123def456/content"
-H "Authorization: YOUR_API_KEY"
-o video.mp4 视频文件可能在一段时间后过期,建议生成完成后立即下载并保存到本地。
完整流程示例 以下是完整的三步流程集成示例:
Python 完整流程
Bash 完整流程
Copy 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 应该包含:场景描述、主体动作、镜头风格、艺术风格。 优秀示例:
Copy 一只可爱的金毛犬在绿色草地上追逐红色飞盘,阳光明媚, 背景是蓝天白云和绿树,运动流畅,特写镜头跟随犬的动作, 电影级画质,暖色调 不佳示例:
Copy 狗追飞盘
参考图片建议 分辨率:建议 1280x720 或更高 格式:PNG 或 JPG 文件大小:< 10MB 内容:清晰、主体明确、光线良好 匹配度:图片内容应与 prompt 描述相关
轮询策略建议 推荐设置 轮询间隔:30 秒 最长等待:10 分钟(600 秒) 典型耗时:3-5 分钟 避免设置 轮询间隔:< 30 秒(可能触发限流) 最长等待:< 5 分钟(可能提前放弃)
错误重试策略
Copy 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 服务器错误 稍后重试