Sora 2 APIの参照画像サイズエラーを解決する5つの方法:Inpaint image must match 完全トラブルシューティングガイド

Sora 2 APIを使用してImage-to-Video(画像から動画生成)を行う際、参照画像のサイズ不一致は、開発者が最も頻繁に遭遇するエラーの一つです。本記事では、Inpaint image must match the requested width and height というエラーの根本原因を詳しく解説し、検証済みの5つの解決策を紹介します。

コアバリュー: この記事を読み終える頃には、Sora 2 APIの参照画像サイズチェックのルールをマスターし、PythonのPillowやFFmpegを使用した画像の事前処理方法を習得して、サイズエラーの問題を完全に解決できるようになります。

sora-2-api-inpaint-image-size-error-solution-ja 图示


Sora 2 API 参照画像サイズエラーの原因分析

Sora 2 APIのImage-to-Video機能を呼び出す際、以下のようなエラーメッセージが表示されることがあります。

{
  "error": {
    "message": "Inpaint image must match the requested width and height",
    "type": "invalid_request_error",
    "param": null,
    "code": null
  }
}

これは、アップロードした参照画像(input_reference)のサイズが、目標とする動画の解像度と一致していないことを示しています。

Sora 2 API 参照画像サイズ強制一致ルール

Sora 2 APIは、参照画像に対して 厳格なサイズ検証メカニズム を持っています:

チェック項目 要件 説明
幅の一致 参照画像の幅 = 動画の幅 ピクセル単位で一致必須
高さの一致 参照画像の高さ = 動画の高さ ピクセル単位で一致必須
対応形式 JPEG、PNG、WebP 3つの形式すべて利用可能
ファイル転送 multipart/form-data ファイル形式でのアップロード必須

Sora 2 API がサポートする動画解像度

OpenAIの公式ドキュメントによると、Sora 2 APIは現在以下の解像度をサポートしています:

解像度 幅 x 高さ アスペクト比 適用シーン
720p 横向き 1280 x 720 16:9 YouTube、ウェブ動画
720p 縦向き 720 x 1280 9:16 TikTok、Reels、ショート動画
1080p 横向き (Pro) 1792 x 1024 ~16:9 高画質横向き動画
1080p 縦向き (Pro) 1024 x 1792 ~9:16 高画質縦向き動画

🎯 重要提示: 参照画像は、選択した目標解像度と ピクセル単位で完全に一致 している必要があります。例えば、1280×720の解像度を選択した場合、参照画像も正確に1280×720ピクセルである必要があり、1ピクセルでも異なるとエラーになります。

sora-2-api-inpaint-image-size-error-solution-ja 图示


Sora 2 API 画像サイズエラーを解決する 5 つの方法

解決策1:Python Pillow によるスマートなクロップとパディング

Pillow の ImageOps.pad() メソッドを使用すると、アスペクト比を維持しながら任意のサイズの画像をスマートに処理し、ターゲットサイズに合わせることができます。

from PIL import Image, ImageOps
import openai

# Sora 2 API がサポートする標準解像度
SORA_RESOLUTIONS = {
    "landscape_720p": (1280, 720),
    "portrait_720p": (720, 1280),
    "landscape_1080p": (1792, 1024),
    "portrait_1080p": (1024, 1792),
}

def preprocess_image_for_sora(image_path, target_resolution="landscape_720p"):
    """Sora 2 API のサイズ要件に合わせて画像を前処理する"""
    target_size = SORA_RESOLUTIONS[target_resolution]

    # 元の画像を開く
    img = Image.open(image_path)

    # pad メソッドを使用:アスペクト比を維持し、背景を黒で塗りつぶす
    processed = ImageOps.pad(img, target_size, color=(0, 0, 0))

    # 処理後の画像を保存
    output_path = image_path.replace(".jpg", "_sora_ready.jpg")
    processed.save(output_path, "JPEG", quality=95)

    return output_path

# 使用例
processed_image = preprocess_image_for_sora("my_image.jpg", "landscape_720p")

# Sora 2 API を呼び出す - APIYI 統合インターフェース経由
client = openai.OpenAI(
    api_key="YOUR_API_KEY",
    base_url="https://api.apiyi.com/v1"  # APIYI 統合インターフェースを使用
)

with open(processed_image, "rb") as f:
    response = client.videos.create(
        model="sora-2",
        prompt="A serene landscape comes to life",
        size="1280x720",
        input_reference=f
    )

🚀 クイックスタート: Sora 2 API を素早くテストするには、APIYI (apiyi.com) プラットフォームの使用をお勧めします。このプラットフォームは、複雑な設定なしですぐに統合できるインターフェースを提供しています。

解決策2:Python Pillow センタークロップ(被写体を維持)

画像の主要な内容を維持し、黒帯を追加したくない場合は、センタークロップ(中央切り抜き)を使用できます。

from PIL import Image

def center_crop_for_sora(image_path, target_width, target_height):
    """Sora 2 API のサイズ要件に合わせて画像をセンタークロップする"""
    img = Image.open(image_path)
    orig_width, orig_height = img.size

    # ターゲットのアスペクト比を計算
    target_ratio = target_width / target_height
    orig_ratio = orig_width / orig_height

    if orig_ratio > target_ratio:
        # 元の画像の方が横長:高さに合わせてスケーリングし、左右をクロップ
        new_height = target_height
        new_width = int(orig_width * (target_height / orig_height))
    else:
        # 元の画像の方が縦長:幅に合わせてスケーリングし、上下をクロップ
        new_width = target_width
        new_height = int(orig_height * (target_width / orig_width))

    # まずリサイズ
    img = img.resize((new_width, new_height), Image.LANCZOS)

    # 次にセンタークロップ
    left = (new_width - target_width) // 2
    top = (new_height - target_height) // 2
    right = left + target_width
    bottom = top + target_height

    cropped = img.crop((left, top, right, bottom))

    output_path = image_path.replace(".jpg", f"_{target_width}x{target_height}.jpg")
    cropped.save(output_path, "JPEG", quality=95)

    return output_path

# 横長 720p ビデオ用のリファレンス画像を準備
processed = center_crop_for_sora("my_photo.jpg", 1280, 720)

解決策3:FFmpeg コマンドラインによる一括処理

大量の画像を処理する必要があるシーンでは、FFmpeg がより効率的な選択肢となります。

センタークロップモード (Cover):

# 比率を維持してスケーリングし、ターゲットサイズにセンタークロップ
ffmpeg -i input.jpg -vf "scale=1280:720:force_original_aspect_ratio=increase,crop=1280:720" output_sora.jpg

パディングモード (Letterbox):

# 元の比率を維持してスケーリングし、足りない部分を黒で塗りつぶす
ffmpeg -i input.jpg -vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2:black" output_sora.jpg

一括処理スクリプト:

#!/bin/bash
# カレントディレクトリ内のすべての jpg 画像を Sora 2 API 720p 横長形式に一括処理

for file in *.jpg; do
    ffmpeg -i "$file" \
        -vf "scale=1280:720:force_original_aspect_ratio=increase,crop=1280:720" \
        -q:v 2 \
        "sora_ready_$file"
done

解決策4:crop_bounds パラメータの使用(API 組み込みクロップ)

Sora 2 API は、API レベルでクロップ領域を指定できる crop_bounds パラメータを提供しています。

import openai

client = openai.OpenAI(
    api_key="YOUR_API_KEY",
    base_url="https://api.apiyi.com/v1"  # APIYI 統合インターフェースを使用
)

# crop_bounds を使用してクロップ領域を指定(比率形式)
with open("full_size_image.jpg", "rb") as f:
    response = client.videos.create(
        model="sora-2",
        prompt="ダイナミックなビデオ効果",
        size="1280x720",
        input_reference=f,
        crop_bounds={
            "left_fraction": 0.1,    # 左側を 10% カット
            "top_fraction": 0.1,     # 上部を 10% カット
            "right_fraction": 0.9,   # 右側を 90% まで保持
            "bottom_fraction": 0.9   # 下部を 90% まで保持
        },
        frame_index=0  # 画像を最初のフレームとして使用
    )

⚠️ 注意: crop_bounds を使用する場合でも、クロップ後の領域がターゲットビデオの解像度と一致している必要があります。事前の前処理と組み合わせて使用することをお勧めします。

解決策5:包括的な画像前処理ツールクラス

以下は、複数の処理モードを備えた実運用レベルの画像前処理ツールクラスです。

from PIL import Image, ImageOps
from pathlib import Path
import io

class SoraImagePreprocessor:
    """Sora 2 API リファレンス画像前処理ツール"""

    RESOLUTIONS = {
        "1280x720": (1280, 720),
        "720x1280": (720, 1280),
        "1792x1024": (1792, 1024),
        "1024x1792": (1024, 1792),
    }

    def __init__(self, target_resolution="1280x720"):
        if target_resolution not in self.RESOLUTIONS:
            raise ValueError(f"サポートされていない解像度: {target_resolution}")
        self.target_size = self.RESOLUTIONS[target_resolution]

    def pad(self, image_path, bg_color=(0, 0, 0)):
        """パディングモード:元の比率を維持し、背景色を追加"""
        img = Image.open(image_path)
        return ImageOps.pad(img, self.target_size, color=bg_color)

    def cover(self, image_path):
        """カバーモード:元の比率を維持し、センタークロップ"""
        img = Image.open(image_path)
        return ImageOps.fit(img, self.target_size, Image.LANCZOS)

    def stretch(self, image_path):
        """ストレッチモード:強制的にターゲットサイズに引き延ばす(非推奨)"""
        img = Image.open(image_path)
        return img.resize(self.target_size, Image.LANCZOS)

    def to_bytes(self, img, format="JPEG", quality=95):
        """PIL Image を API アップロード用のバイトストリームに変換"""
        buffer = io.BytesIO()
        img.save(buffer, format=format, quality=quality)
        buffer.seek(0)
        return buffer

    def process_and_save(self, image_path, mode="cover", output_path=None):
        """画像を処理して保存"""
        if mode == "pad":
            processed = self.pad(image_path)
        elif mode == "cover":
            processed = self.cover(image_path)
        elif mode == "stretch":
            processed = self.stretch(image_path)
        else:
            raise ValueError(f"サポートされていないモード: {mode}")

        if output_path is None:
            p = Path(image_path)
            output_path = p.parent / f"{p.stem}_sora_{self.target_size[0]}x{self.target_size[1]}{p.suffix}"

        processed.save(output_path, quality=95)
        return output_path

# 使用例
preprocessor = SoraImagePreprocessor("1280x720")

# 方法1:処理して保存
output = preprocessor.process_and_save("my_image.jpg", mode="cover")
print(f"処理完了: {output}")

# 方法2:API 呼び出し用にバイトストリームを直接取得
img = preprocessor.cover("my_image.jpg")
image_bytes = preprocessor.to_bytes(img)
完全な呼び出し例コードを表示
import openai
from PIL import Image, ImageOps
import io

class SoraImagePreprocessor:
    """Sora 2 API リファレンス画像前処理ツール"""

    RESOLUTIONS = {
        "1280x720": (1280, 720),
        "720x1280": (720, 1280),
        "1792x1024": (1792, 1024),
        "1024x1792": (1024, 1792),
    }

    def __init__(self, target_resolution="1280x720"):
        if target_resolution not in self.RESOLUTIONS:
            raise ValueError(f"サポートされていない解像度: {target_resolution}")
        self.target_size = self.RESOLUTIONS[target_resolution]

    def cover(self, image_path):
        """カバーモード:元の比率を維持し、センタークロップ"""
        img = Image.open(image_path)
        return ImageOps.fit(img, self.target_size, Image.LANCZOS)

    def to_bytes(self, img, format="JPEG", quality=95):
        """PIL Image をバイトストリームに変換"""
        buffer = io.BytesIO()
        img.save(buffer, format=format, quality=quality)
        buffer.seek(0)
        return buffer


def generate_video_with_image(image_path, prompt, resolution="1280x720"):
    """
    前処理済みの画像を使用して Sora 2 ビデオを生成

    Args:
        image_path: オリジナル画像のパス
        prompt: ビデオ説明用のプロンプト
        resolution: ターゲット解像度

    Returns:
        ビデオ生成タスク ID
    """
    # 1. 画像の前処理
    preprocessor = SoraImagePreprocessor(resolution)
    processed_img = preprocessor.cover(image_path)
    image_bytes = preprocessor.to_bytes(processed_img)

    # 2. クライアントの初期化 - APIYI 統合インターフェース経由
    client = openai.OpenAI(
        api_key="YOUR_API_KEY",
        base_url="https://api.apiyi.com/v1"
    )

    # 3. Sora 2 API を呼び出し
    response = client.videos.create(
        model="sora-2",
        prompt=prompt,
        size=resolution,
        input_reference=image_bytes,
        duration=5  # ビデオの長さ(秒)
    )

    return response


# 完全な実行例
if __name__ == "__main__":
    result = generate_video_with_image(
        image_path="landscape_photo.jpg",
        prompt="The scene comes alive with gentle wind moving through the trees",
        resolution="1280x720"
    )
    print(f"ビデオ生成タスクが送信されました: {result}")

Sora 2 API 画像前処理モードの比較

ビデオの効果を最大限に引き出すためには、適切な前処理モードを選択することが重要です。

sora-2-api-inpaint-image-size-error-solution-ja 图示

前処理モード 処理方法 利点 欠点 推奨シーン
Pad (パディング) 比率を維持、黒帯を追加 画面全体を保持 黒帯が発生する可能性 内容の完全性が重要な場合
Cover (クロップ) 比率を維持、中央切り抜き 黒帯なし、画面が充実 端がカットされる可能性 被写体が中央にある画像
Stretch (ストレッチ) 強制的に引き延ばす 単純明快 画面が歪む 非推奨

💡 選択のアドバイス: どの前処理モードを選択するかは、画像の内容と最終的なビデオの要件によります。APIYI (apiyi.com) プラットフォームで実際にテストを行い、各モードの効果の違いを素早く検証することをお勧めします。

シーン別推奨モード

画像タイプ 推奨モード 説明
人物写真 Cover 人物という被写体を中央に完全な状態で維持
風景写真 Pad または Cover 構図に応じて選択
製品写真 Pad 製品が欠けずに表示されることを保証
アート画像 Pad 芸術的な完全性を保持
UI スクリーンショット Cover 通常、情報は中央に集中しているため

Sora 2 API リファレンス画像(垫图)に関するよくある質問

Q1: なぜ Sora 2 API はリファレンス画像のサイズにこれほど厳しいのですか?

Sora 2 は、提供された画像を動画の最初のフレーム(ファーストフレーム)として使用します。大規模言語モデルは、このフレームを起点として、その後の動的なコンテンツの生成を開始します。画像のサイズがターゲット動画の解像度と一致しない場合、モデルは生成プロセスを正しく初期化することができません。これは、生成品質の一貫性を確保するための OpenAI による技術的な制限です。

APIYI (apiyi.com) プラットフォーム経由で呼び出す際は、クライアント側であらかじめ画像のプリプロセス(前処理)を完了させておくことをお勧めします。これにより、最適な生成結果を得ることができます。

Q2: プリプロセスでは、どの画像形式を選択すべきですか?

Sora 2 API は、JPEG、PNG、WebP の 3 つの形式をサポートしています:

  • JPEG: 写真系の画像に推奨されます。ファイルサイズが小さく、アップロードが高速です。
  • PNG: 背景の透過が必要な場合や、画質を一切落としたくない(ロスレス)シーンに適しています。
  • WebP: 品質とファイルサイズのバランスに優れていますが、互換性がわずかに劣る場合があります。

一般的には JPEG 形式を使用し、quality パラメータを 90〜95 に設定することをお勧めします。これにより、品質を維持しつつファイルサイズを抑えることができます。

Q3: 処理後の画像品質が低下した場合はどうすればよいですか?

画像品質の低下は、通常以下の原因によって引き起こされます:

  1. 過度な圧縮: JPEG の quality 設定を 95 まで上げてください。
  2. 過度な拡大: ターゲットの解像度に近い解像度の元画像を使用するようにしてください。
  3. リサンプリングアルゴリズム: Image.NEAREST ではなく、Image.LANCZOS を使用してください。
# 高品質な処理設定
img = img.resize(target_size, Image.LANCZOS)  # Lanczos アルゴリズムを使用
img.save(output_path, "JPEG", quality=95)     # 高品質で保存
Q4: 大量の画像をバッチ処理するにはどうすればよいですか?

大量の画像を処理するシナリオでは、FFmpeg または Python のマルチスレッド処理を利用することをお勧めします:

from concurrent.futures import ThreadPoolExecutor
import os

def batch_process(image_dir, output_dir, resolution="1280x720"):
    preprocessor = SoraImagePreprocessor(resolution)

    def process_single(filename):
        input_path = os.path.join(image_dir, filename)
        output_path = os.path.join(output_dir, f"sora_{filename}")
        return preprocessor.process_and_save(input_path, "cover", output_path)

    image_files = [f for f in os.listdir(image_dir) if f.endswith(('.jpg', '.png'))]

    with ThreadPoolExecutor(max_workers=4) as executor:
        results = list(executor.map(process_single, image_files))

    return results

APIYI (apiyi.com) プラットフォームでは、バッチ処理用の API クォータを取得できるため、大規模な動画生成プロジェクトに適しています。

Q5: 画像に人顔が含まれている場合、拒否されますか?

はい。OpenAI のポリシーに基づき、実在の人物の顔を含むリファレンス画像は、現在 Sora 2 API での処理が拒否されます。人物が登場する動画が必要な場合は、以下の方法を検討してください:

  1. はっきりとした顔が写っていない画像を使用する
  2. AI によって生成された仮想の人物画像を使用する
  3. 抽象化または芸術的な加工を施した人物画像を使用する

Sora 2 API リファレンス画像サイズ早見表

迅速な確認のために、以下に完全なサイズ対応表をまとめました:

ターゲット動画 画像の幅 画像の高さ API size パラメータ 適用プラットフォーム
720p 横向き 1280 720 "1280×720" YouTube, ウェブサイト
720p 縦向き 720 1280 "720×1280" TikTok, Instagram リール
Pro 横向き 1792 1024 "1792×1024" 高解像度横向き動画
Pro 縦向き 1024 1792 "1024×1792" 高解像度縦向き動画

📌 ヒント: 利用可能なプラットフォームには APIYI (apiyi.com) や OpenAI 公式 API などがあります。開発やテストの際は、レスポンスが速く、コストパフォーマンスの良いプラットフォームを選択することをお勧めします。


まとめ

Sora 2 APIの画像プロンプト(Image-to-Video)におけるサイズエラーは、開発者が最も頻繁に直面する問題の一つです。その核となる解決策は以下の通りです:

  1. ルールの理解: 参照用画像は、ターゲットとなる動画のピクセルサイズと完全に一致している必要があります。
  2. モードの選択: 画像の内容に応じて Pad(余白あり)または Cover(切り抜き)モードを選択します。
  3. 前処理の実行: PythonのPillowやFFmpegを使用して画像の前処理を行います。
  4. サイズの検証: 処理後に画像サイズが正しく一致しているかを確認します。

APIYI(apiyi.com)を利用して、画像の前処理効果や動画生成のクオリティを素早く検証することをおすすめします。


著者: APIYI Team | AI開発のさらなるテクニックについては apiyi.com をご覧ください。

参考資料:

  1. OpenAI Sora API ドキュメント: Image-to-Video インターフェースの説明
    • リンク: platform.openai.com/docs/guides/video-generation
  2. Pillow 公式ドキュメント: ImageOps 画像処理モジュール
    • リンク: pillow.readthedocs.io/en/stable/reference/ImageOps.html
  3. FFmpeg 公式ドキュメント: 動画および画像処理フィルター
    • リンク: ffmpeg.org/ffmpeg-filters.html

類似投稿