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);