> ## 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.

# 文生影片 API 參考

> Sora 2 文生影片 API 參考與線上除錯 — JSON 請求體、非同步任務三步流程、4/8/12 秒靈活時長。

<Info>
  右側的互動式 Playground 支援直接線上除錯。請在 **Authorization** 中填入你的 API Key（格式：`Bearer sk-xxx`），輸入 prompt、選擇 model / size / seconds 後一鍵傳送即可。
</Info>

<Tip>
  **場景說明**：本頁用於「純文本提示詞生成影片」——不傳 `input_reference`、走 `application/json` 請求體。如需基於一張參考圖生成影片（圖生影片），請使用 [圖生影片介面](/zh-Hant/api-capabilities/sora-2/image-to-video)（同一端點 + `input_reference` 檔案上傳）。
</Tip>

<Warning>
  **⚠️ 三步非同步流程，本頁只覆蓋第一步（提交）**

  * **第 1 步（本頁）**：`POST /v1/videos` → 返回 `video_id` + `status: "queued"`
  * **第 2 步**：`GET /v1/videos/{video_id}` 輪詢，直到 `status: "completed"`
  * **第 3 步**：`GET /v1/videos/{video_id}/content` 下載 MP4 檔案

  POST 提交本身耗時秒級，**不會**等到影片生成完成。完整流程見下方 Python 程式碼示例。
</Warning>

## 程式碼示例

### Python（OpenAI SDK 直連）

```python theme={null}
from openai import OpenAI
import time

client = OpenAI(
    api_key="sk-your-api-key",
    base_url="https://api.apiyi.com/v1"
)

# 第 1 步：提交生成任務
video = client.videos.create(
    model="sora-2",
    prompt="A golden retriever running on the beach at sunset, cinematic, golden hour, slow motion",
    seconds="8",
    size="1280x720"
)
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 步：下載影片
content = client.videos.download_content(video.id)
content.write_to_file("output.mp4")
print("Saved: output.mp4")
```

### Python（原生 requests）

```python theme={null}
import requests
import time

API_KEY = "sk-your-api-key"
BASE_URL = "https://api.apiyi.com/v1"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}

# 第 1 步：提交（JSON 請求體）
resp = requests.post(
    f"{BASE_URL}/videos",
    headers={**HEADERS, "Content-Type": "application/json"},
    json={
        "model": "sora-2",
        "prompt": "A serene Japanese garden with cherry blossoms, koi pond, traditional bridge, golden hour, ultra detailed",
        "seconds": "8",
        "size": "1280x720"
    },
    timeout=30  # POST 提交本身只是入隊，30 秒足夠
).json()
video_id = resp["id"]
print(f"Video ID: {video_id}, status: {resp['status']}")

# 第 2 步：輪詢（最長等 15 分鐘）
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

```bash theme={null}
{/* 第 1 步：提交任務 */}
curl -X POST "https://api.apiyi.com/v1/videos" \
  -H "Authorization: Bearer sk-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "sora-2",
    "prompt": "A futuristic cityscape at night with neon lights and flying vehicles, cyberpunk style, cinematic",
    "seconds": "8",
    "size": "1280x720"
  }'

{/* 第 2 步：輪詢狀態（替換 video_id）*/}
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）

```javascript theme={null}
import fs from 'node:fs';

const API_KEY = 'sk-your-api-key';
const BASE_URL = 'https://api.apiyi.com/v1';

// 第 1 步：提交
const submitResp = await fetch(`${BASE_URL}/videos`, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${API_KEY}`
    },
    body: JSON.stringify({
        model: 'sora-2',
        prompt: 'Aerial drone shot over snowy mountain range at sunrise, cinematic, ultra wide',
        seconds: '8',
        size: '1280x720'
    })
});
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 statusResp = await fetch(`${BASE_URL}/videos/${videoId}`, {
        headers: { 'Authorization': `Bearer ${API_KEY}` }
    });
    const data = await statusResp.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}` }
});
const buffer = Buffer.from(await contentResp.arrayBuffer());
fs.writeFileSync('output.mp4', buffer);
console.log('Saved: output.mp4');
```

### 瀏覽器 JavaScript

```javascript theme={null}
{/* 僅作演示，生產請走後端代理避免 Key 洩露；影片檔案較大也不適合直接在瀏覽器下載 */}
const submitResp = await fetch('https://api.apiyi.com/v1/videos', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer sk-your-api-key'
    },
    body: JSON.stringify({
        model: 'sora-2',
        prompt: 'Watercolor northern lights over snowy mountains, gentle motion',
        seconds: '4',
        size: '720x1280'
    })
});
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` | 輸出解析度，需匹配模型支援檔位（見 [概覽頁技術規格](/zh-Hant/api-capabilities/sora-2/overview#技術規格)） |

<Tip>
  詳細的引數約束、可選值、示例請檢視右側 Playground 中的欄位說明，所有 enum 欄位均支援下拉選擇。**圖生影片相關引數（`input_reference` 檔案上傳）見 [圖生影片介面](/zh-Hant/api-capabilities/sora-2/image-to-video)**。
</Tip>

## 響應格式

### 第 1 步 - 提交後立即返回

```json theme={null}
{
  "id": "video_abc123def456",
  "object": "video",
  "model": "sora-2",
  "status": "queued",
  "progress": 0,
  "created_at": 1712697600,
  "size": "1280x720",
  "seconds": "8",
  "quality": "standard"
}
```

### 第 2 步 - 輪詢返回（生成中）

```json theme={null}
{
  "id": "video_abc123def456",
  "object": "video",
  "model": "sora-2",
  "status": "in_progress",
  "progress": 45,
  "created_at": 1712697600,
  "size": "1280x720",
  "seconds": "8"
}
```

### 第 2 步 - 輪詢返回（完成）

```json theme={null}
{
  "id": "video_abc123def456",
  "object": "video",
  "model": "sora-2",
  "status": "completed",
  "progress": 100,
  "created_at": 1712697600,
  "completed_at": 1712697900,
  "size": "1280x720",
  "seconds": "8"
}
```

<Warning>
  **⚠️ 響應欄位陷阱**

  * **沒有直接的 `video_url` 欄位** —— 影片檔案需要通過 `GET /v1/videos/{id}/content` 端點單獨下載（返回 `video/mp4` 二進位制流），**不要**期待響應裡直接出現一個 CDN 連結
  * `progress` 欄位在不同生成階段會跳變（如 0 → 45 → 80 → 100），不是嚴格線性的
  * `status: "failed"` 時不一定帶詳細 `error` 欄位，多見於內容稽核或服務過載，**直接重試或調整 prompt** 即可
  * 影片內容在 OpenAI 上**只保留 1 天**，過期後 `/content` 返回 404
</Warning>

<Info>
  本端點是非同步任務式入口，**計費在生成完成時按 `seconds` 單價結算**（見 [概覽頁定價表](/zh-Hant/api-capabilities/sora-2/overview#模型定價)）。POST 提交、輪詢查詢、影片下載本身**不計費**，失敗任務也**不計費**。
</Info>


## OpenAPI

````yaml api-reference/sora-2-text-to-video-openapi.yaml POST /v1/videos
openapi: 3.1.0
info:
  title: Sora 2 文生视频 API
  description: >
    OpenAI Sora 2 / Sora 2 Pro 系列视频生成模型 — 文生视频接口（不传 `input_reference`，走
    `application/json`）。


    - 两个活跃模型：`sora-2`（720p，\$0.10/秒）与 `sora-2-pro`（720p / 1024p / 1080p 三档）

    - 时长支持 `"4"` / `"8"` / `"12"` 秒（**字符串枚举**）

    - 同步音轨视频输出（含环境音、对话、配乐）

    - **异步任务式端点**：本端点只提交任务，需配合 `GET /v1/videos/{id}` 轮询和 `GET
    /v1/videos/{id}/content` 下载

    - 视频在 OpenAI 服务器仅保留 1 天，请生成完成后立即下载落地

    - 如需基于参考图生成视频，请使用 [图生视频接口](/api-capabilities/sora-2/image-to-video)（同端点 +
    multipart 上传 `input_reference`）


    **认证方式**：在请求头中添加 `Authorization: Bearer YOUR_API_KEY`


    **API Key 配置**：必须在 API易控制台把分组切到 **Sora2官转**、计费模式切到 **按量计费**，否则返回 403


    **获取 API Key**：访问 [API易控制台](https://api.apiyi.com/token) 创建令牌
  version: 1.0.0
servers:
  - url: https://api.apiyi.com
    description: 主要端点
  - url: https://vip.apiyi.com
    description: 备用端点
security:
  - bearerAuth: []
paths:
  /v1/videos:
    post:
      tags:
        - 视频生成
      summary: 文生视频：根据文本提示词生成视频任务
      description: >
        提交一个 Sora 2 视频生成任务（异步），返回 `video_id` 和 `status: "queued"`。


        - 必填：`model`、`prompt`

        - 可选：`seconds`（默认 `"4"`）、`size`（默认 `"720x1280"`）

        - **响应不会包含视频文件**，需要轮询 `GET /v1/videos/{video_id}` 直到 `status:
        "completed"`，再调 `GET /v1/videos/{video_id}/content` 下载 MP4

        - 典型生成耗时：sora-2 4 秒 ≈ 3 分钟；sora-2-pro 12 秒 1080p ≈ 8–10 分钟

        - 若使用参考图生成（图生视频），请改用 [图生视频接口](/api-capabilities/sora-2/image-to-video)
      operationId: generateSora2TextToVideo
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Sora2TextToVideoRequest'
            example:
              model: sora-2
              prompt: >-
                A golden retriever running on the beach at sunset, cinematic,
                golden hour, slow motion
              seconds: '8'
              size: 1280x720
      responses:
        '200':
          description: 任务已提交，返回 video_id 与 queued 状态
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Sora2VideoTask'
        '400':
          description: 参数非法（seconds 不在 4/8/12、size 不支持当前模型、prompt 缺失等）
        '401':
          description: 未授权 - API Key 无效
        '403':
          description: 内容审核拦截 / 计费模式不是按量计费 / 分组未选 Sora2官转
        '429':
          description: 请求频率超限或余额不足
        '500':
          description: 上游 OpenAI 网关错误，建议重试 1–2 次
      security:
        - bearerAuth: []
components:
  schemas:
    Sora2TextToVideoRequest:
      type: object
      required:
        - model
        - prompt
      properties:
        model:
          type: string
          description: 模型 ID。`sora-2` 仅支持 720p；`sora-2-pro` 支持 720p / 1024p / 1080p 三档分辨率
          enum:
            - sora-2
            - sora-2-pro
          default: sora-2
        prompt:
          type: string
          description: 视频生成提示词，建议详细描述场景、镜头运动、风格、光线、人物动作
          example: >-
            A serene Japanese garden with cherry blossoms, koi pond, traditional
            bridge, golden hour, ultra detailed
        seconds:
          type: string
          description: |
            视频时长，**字符串枚举**（不是数字）：
            - `"4"` —— 4 秒（默认），适合短演示、单镜头、快速试错
            - `"8"` —— 8 秒，标准短视频，最常用
            - `"12"` —— 12 秒，长镜头、连续动作

            传 `"10"` / `"15"` 或数字 `4` 会返回 400
          enum:
            - '4'
            - '8'
            - '12'
          default: '4'
        size:
          type: string
          description: |
            输出分辨率，**`sora-2` 与 `sora-2-pro` 支持档位不同**：

            - `sora-2`（仅 720p）：`720x1280`（竖屏，默认）/ `1280x720`（横屏）
            - `sora-2-pro` 额外支持：
              - `1024x1792` / `1792x1024`（1024p，\$0.50/秒）
              - `1080x1920` / `1920x1080`（1080p，\$0.70/秒）

            给 `sora-2` 传 1024p / 1080p 会返回 400
          enum:
            - 720x1280
            - 1280x720
            - 1024x1792
            - 1792x1024
            - 1080x1920
            - 1920x1080
          default: 720x1280
    Sora2VideoTask:
      type: object
      properties:
        id:
          type: string
          description: 任务 ID，用于后续轮询和下载
          example: video_abc123def456
        object:
          type: string
          description: 对象类型，固定 `video`
          example: video
        model:
          type: string
          description: 本次任务使用的模型 ID
          example: sora-2
        status:
          type: string
          description: |
            任务状态：
            - `queued` —— 已提交，排队等待
            - `in_progress` —— 正在生成
            - `completed` —— 完成，可下载（`/v1/videos/{id}/content`）
            - `failed` —— 失败（不计费），可重试
          enum:
            - queued
            - in_progress
            - completed
            - failed
          example: queued
        progress:
          type: integer
          description: 生成进度百分比（0–100），不严格线性
          example: 0
        created_at:
          type: integer
          description: 任务创建 Unix 时间戳（秒）
          example: 1712697600
        completed_at:
          type: integer
          description: 任务完成 Unix 时间戳（秒），仅 completed 状态返回
          example: 1712697900
        size:
          type: string
          description: 实际输出分辨率（与请求的 `size` 一致）
          example: 1280x720
        seconds:
          type: string
          description: 实际生成时长（与请求的 `seconds` 一致）
          example: '8'
        quality:
          type: string
          description: 画质档位（`standard` 对应 sora-2，`high` 对应 sora-2-pro）
          example: standard
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 在 API易控制台获取的 API Key（必须配置 Sora2官转 分组 + 按量计费）

````