Unlock exclusive introductory pricing for the newly launched Gemini 3.5 Flash.
O

Sora 2

每秒:$0.08
發布時間:Oct 9, 2025

超強大的影片生成模型,具備音效,支援對話格式。

熱門
商業用途

Sora 2 的 Playground

探索 Sora 2 的 Playground — 一個互動式環境,可測試模型並即時執行查詢。嘗試提示、調整參數,並立即迭代以加速開發並驗證使用案例。

關鍵功能

  • 物理寫實與連貫性:改進物體恆常性、運動與物理的模擬,以減少視覺偽影。
  • 音訊同步:生成與畫面動作對齊的對白與音效
  • 可控性與風格範圍:更精細地控制鏡頭構圖、風格選擇,以及面向不同美學的提示條件化。
  • 創作控制:更一致的多鏡頭序列、改進的物理與運動寫實性,並相較於 Sora 1 提供風格與時間/節奏的控制。

技術細節

OpenAI 表示,Sora 系列模型利用潛在空間影片擴散流程,結合以 Transformer 為基礎的去雜訊器與多模態條件化,以產生時間連貫的畫面與對齊的音訊。Sora 2 著重於提升運動的物理性(遵循動量、浮力)、更長且一致的鏡頭,以及在生成視覺與生成語音/音效之間的明確同步。公開資料強調模型層級的安全與內容審核掛鉤(對特定不允許內容的硬性封鎖、針對未成年人的加強門檻,以及與肖像相關的同意流程)。

限制與安全考量

  • 仍有不完善之處:Sora 2 會犯錯(時間性偽影、邊緣情境中的物理不精確、語音/口腔發音錯誤)—Sora 2 有所改進但並不完美。OpenAI 明確指出該模型仍存在失敗模式。
  • 濫用風險:未經同意的肖像生成、深偽、版權疑慮,以及青少年福祉/參與風險。OpenAI 正在推出同意工作流程、更嚴格的客串許可、針對未成年人的審核門檻,以及人工審核團隊
  • 內容與法律限制:應用與模型會封鎖露骨/暴力內容,並在未獲同意的情況下限制公眾人物的肖像生成;據報導,OpenAI 也對受版權保護的來源採用退出機制。在投入生產使用前,從業者應評估智慧財產與隱私/法律風險。
  • 當前部署重點在短片(應用功能提及約 ~10 秒的創意短片),並對大量或不受限制的擬真上傳有所限制。

主要與實務用例

  • 社群創作與病毒式短片:快速生成與混剪用於社群動態的直式短片(Sora 應用場景)。
  • 原型製作與預視化:為創意團隊快速提供場景樣稿、分鏡、概念視覺,並配合同步的臨時音訊。
  • 廣告與短形式內容:在已取得道德/法律許可的前提下,用於概念驗證的創意測試與小型活動素材。
  • 研究與工具鏈增強:供媒體實驗室研究世界建模與多模態對齊的工具(受授權與安全防護限制)。

常見問題

Sora 2 的定價

探索 Sora 2 的競爭性定價,專為滿足各種預算和使用需求而設計。我們靈活的方案確保您只需為實際使用量付費,讓您能夠隨著需求增長輕鬆擴展。了解 Sora 2 如何在保持成本可控的同時提升您的專案效果。

Model NameTagsOrientationResolutionPrice
sora-2videosPortrait720x1280$0.08 / sec
sora-2videosLandscape1280x720$0.08 / sec
sora-2-all-Universal / All-$0.08000

Sora 2 的範例程式碼和 API

Sora 2 是 OpenAI 的旗艦級文本轉影片與音訊生成系統,旨在生成具備同步對白與音效、持續的場景狀態,以及顯著提升的物理真實感的短篇電影感片段。Sora 2 代表 OpenAI 在生成具同步音訊(語音與音效)、更高物理合理性(運動、動量、浮力)與更強安全控制的可控短片方面,較早期的文本轉影片系統更進一步。

# Create a video with sora-2
# Step 1: Submit the video generation request
echo "Submitting video generation request..."
response=$(curl -s https://api.cometapi.com/v1/videos \
  -H "Authorization: Bearer $COMETAPI_KEY" \
  -F "model=sora-2" \
  -F "prompt=A calico cat playing a piano on stage")

echo "Response: $response"

# Extract video_id from response (handle JSON with spaces like "id": "xxx")
video_id=$(echo "$response" | tr -d '
' | sed 's/.*"id"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
echo "Video ID: $video_id"

# Step 2: Poll for progress until 100%
echo ""
echo "Checking video generation progress..."
while true; do
  status_response=$(curl -s "https://api.cometapi.com/v1/videos/$video_id" \
    -H "Authorization: Bearer $COMETAPI_KEY")

  # Parse progress from "progress": "0%" format
  progress=$(echo "$status_response" | grep -o '"progress":"[^"]*"' | head -1 | sed 's/"progress":"//;s/"$//')
  # Parse status from the outer level
  status=$(echo "$status_response" | grep -o '"status":"[^"]*"' | head -1 | sed 's/"status":"//;s/"$//')

  echo "Progress: $progress, Status: $status"

  if [ "$progress" = "100%" ]; then
    echo "Video generation completed!"
    break
  fi

  if [ "$status" = "FAILURE" ] || [ "$status" = "failed" ]; then
    echo "Video generation failed!"
    echo "$status_response"
    exit 1
  fi

  sleep 10
done

# Step 3: Download the video to output directory
echo ""
echo "Downloading video to ./output/$video_id.mp4..."
mkdir -p ./output
curl -s "https://api.cometapi.com/v1/videos/$video_id/content" \
  -H "Authorization: Bearer $COMETAPI_KEY" \
  -o "./output/$video_id.mp4"

if [ -f "./output/$video_id.mp4" ]; then
  echo "Video saved to ./output/$video_id.mp4"
  ls -la "./output/$video_id.mp4"
else
  echo "Failed to download video"
  exit 1
fi

cURL Code Example

# Create a video with sora-2
# Step 1: Submit the video generation request
echo "Submitting video generation request..."
response=$(curl -s https://api.cometapi.com/v1/videos \
  -H "Authorization: Bearer $COMETAPI_KEY" \
  -F "model=sora-2" \
  -F "prompt=A calico cat playing a piano on stage")

echo "Response: $response"

# Extract video_id from response (handle JSON with spaces like "id": "xxx")
video_id=$(echo "$response" | tr -d '\n' | sed 's/.*"id"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')
echo "Video ID: $video_id"

# Step 2: Poll for progress until 100%
echo ""
echo "Checking video generation progress..."
while true; do
  status_response=$(curl -s "https://api.cometapi.com/v1/videos/$video_id" \
    -H "Authorization: Bearer $COMETAPI_KEY")
  
  # Parse progress from "progress": "0%" format
  progress=$(echo "$status_response" | grep -o '"progress":"[^"]*"' | head -1 | sed 's/"progress":"//;s/"$//')
  # Parse status from the outer level
  status=$(echo "$status_response" | grep -o '"status":"[^"]*"' | head -1 | sed 's/"status":"//;s/"$//')
  
  echo "Progress: $progress, Status: $status"
  
  if [ "$progress" = "100%" ]; then
    echo "Video generation completed!"
    break
  fi
  
  if [ "$status" = "FAILURE" ] || [ "$status" = "failed" ]; then
    echo "Video generation failed!"
    echo "$status_response"
    exit 1
  fi
  
  sleep 10
done

# Step 3: Download the video to output directory
echo ""
echo "Downloading video to ./output/$video_id.mp4..."
mkdir -p ./output
curl -s "https://api.cometapi.com/v1/videos/$video_id/content" \
  -H "Authorization: Bearer $COMETAPI_KEY" \
  -o "./output/$video_id.mp4"

if [ -f "./output/$video_id.mp4" ]; then
  echo "Video saved to ./output/$video_id.mp4"
  ls -la "./output/$video_id.mp4"
else
  echo "Failed to download video"
  exit 1
fi

Python Code Example

# Create a video with sora-2 using raw HTTP requests
import os
import time
import requests

api_key = os.environ.get("COMETAPI_KEY")
base_url = "https://api.cometapi.com/v1"

headers = {"Authorization": f"Bearer {api_key}"}

# Step 1: Submit the video generation request
print("Submitting video generation request...")
response = requests.post(
    f"{base_url}/videos",
    headers=headers,
    files={
        "model": (None, "sora-2"),
        "prompt": (None, "A calico cat playing a piano on stage"),
    },
)

result = response.json()
print(f"Response: {result}")

video_id = result.get("id")
print(f"Video ID: {video_id}")

# Step 2: Poll for progress until 100%
print("\nChecking video generation progress...")
while True:
    try:
        status_response = requests.get(f"{base_url}/videos/{video_id}", headers=headers)
        status_result = status_response.json()

        # Parse progress and status from response
        data = status_result.get("data", {})
        if data is None:
            data = {}
        progress = data.get("progress", "0%")
        status = data.get("status", "unknown")

        print(f"Progress: {progress}, Status: {status}")

        if status in ["FAILURE", "failed"]:
            print("Video generation failed!")
            print(status_result)
            exit(1)

        if progress == "100%":
            print("Video generation completed!")
            break
    except Exception as e:
        print(f"Temporary error: {e}, retrying...")

    time.sleep(10)

# Step 3: Download the video to output directory
print(f"\nDownloading video to ./output/{video_id}.mp4...")
os.makedirs("./output", exist_ok=True)

video_response = requests.get(f"{base_url}/videos/{video_id}/content", headers=headers)

output_path = f"./output/{video_id}.mp4"
with open(output_path, "wb") as f:
    f.write(video_response.content)

if os.path.exists(output_path):
    file_size = os.path.getsize(output_path)
    print(f"Video saved to {output_path}")
    print(f"File size: {file_size} bytes")
else:
    print("Failed to download video")
    exit(1)

JavaScript Code Example

// Create a video with sora-2 using raw HTTP requests
import fs from "fs";
import path from "path";

const apiKey = process.env.COMETAPI_KEY;
const baseUrl = "https://api.cometapi.com/v1";

async function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

async function main() {
  // Step 1: Submit the video generation request
  console.log("Submitting video generation request...");

  const formData = new FormData();
  formData.append("model", "sora-2");
  formData.append("prompt", "A calico cat playing a piano on stage");

  const submitResponse = await fetch(`${baseUrl}/videos`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${apiKey}`,
    },
    body: formData,
  });

  const result = await submitResponse.json();
  console.log("Response:", JSON.stringify(result, null, 2));

  const videoId = result.id;
  console.log("Video ID:", videoId);

  // Step 2: Poll for progress until 100%
  console.log("\nChecking video generation progress...");

  while (true) {
    try {
      const statusResponse = await fetch(`${baseUrl}/videos/${videoId}`, {
        headers: {
          Authorization: `Bearer ${apiKey}`,
        },
      });

      const text = await statusResponse.text();
      if (text.startsWith("<")) {
        console.log("Temporary server error, retrying...");
        await sleep(10000);
        continue;
      }

      const statusResult = JSON.parse(text);

      // Parse progress and status from response
      const data = statusResult.data || {};
      const progress = data.progress || "0%";
      const status = data.status || "unknown";

      console.log(`Progress: ${progress}, Status: ${status}`);

      if (status === "FAILURE" || status === "failed") {
        console.log("Video generation failed!");
        console.log(JSON.stringify(statusResult, null, 2));
        process.exit(1);
      }

      if (progress === "100%") {
        console.log("Video generation completed!");
        break;
      }
    } catch (e) {
      console.log(`Temporary error: ${e.message}, retrying...`);
    }

    await sleep(10000);
  }

  // Step 3: Download the video to output directory
  console.log(`\nDownloading video to ./output/${videoId}.mp4...`);

  const outputDir = "./output";
  if (!fs.existsSync(outputDir)) {
    fs.mkdirSync(outputDir, { recursive: true });
  }

  const videoResponse = await fetch(`${baseUrl}/videos/${videoId}/content`, {
    headers: {
      Authorization: `Bearer ${apiKey}`,
    },
  });

  const outputPath = path.join(outputDir, `${videoId}.mp4`);
  const videoBuffer = Buffer.from(await videoResponse.arrayBuffer());
  fs.writeFileSync(outputPath, videoBuffer);

  if (fs.existsSync(outputPath)) {
    const stats = fs.statSync(outputPath);
    console.log(`Video saved to ${outputPath}`);
    console.log(`File size: ${stats.size} bytes`);
  } else {
    console.log("Failed to download video");
    process.exit(1);
  }
}

main().catch(console.error);