跳转到主要内容

概述

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 分钟。

端点地址

https://api.apiyi.com/v1/videos

第一步:提交视频生成请求

请求参数

参数类型必填说明
promptstring视频生成的文本描述,建议详细描述场景、动作、风格
modelstring固定值:sora-2
sizestring1280x720(横屏)或 720x1280(竖屏)
secondsstring视频时长,可选值:1015
input_referencefile参考图片文件(PNG/JPG/JPEG),可选,用于图生视频

文生视频示例

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 -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"

响应格式

{
  "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: 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
}

第三步:下载生成的视频

视频生成完成后(statuscompleted),可以下载视频文件。

请求方式

GET /v1/videos/{video_id}/content

下载示例

curl -X GET "https://api.apiyi.com/v1/videos/video_abc123def456/content" \
  -H "Authorization: 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 或更换图片)
  • 配额不足(充值或升级套餐)
  • 参数错误(检查参数格式和值)
  • 服务器负载过高(稍后重试)
通过 size 参数控制:
  • 1280x720:横屏
  • 720x1280:竖屏

相关资源