5 طرق لحل خطأ أبعاد الصورة في Sora 2 API: دليل استكشاف الأخطاء وإصلاحها الشامل لخطأ Inpaint image must match

عند استخدام Sora 2 API لتحويل الصور إلى فيديو (Image-to-Video)، يعد عدم تطابق حجم صورة الإدخال (Image Reference) أحد أكثر الأخطاء شيوعاً التي يواجهها المطورون. سنقوم في هذا المقال بتحليل السبب الجذري لخطأ Inpaint image must match the requested width and height بالتفصيل، ونقدم 5 حلول مجربة.

القيمة الجوهرية: بقراءتك لهذا المقال، ستتقن قواعد التحقق من حجم الصورة في Sora 2 API، وتتعلم كيفية استخدام Python Pillow وFFmpeg لمعالجة الصور مسبقاً، مما يحل مشكلة أخطاء الحجم بشكل نهائي.

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


تحليل أسباب خطأ حجم صورة الإدخال في Sora 2 API

عند استدعاء وظيفة تحويل الصور إلى فيديو في Sora 2 API، إذا رأيت رسالة الخطأ التالية:

{
  "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 جميع التنسيقات الثلاثة مقبولة
نقل الملفات multipart/form-data يجب الرفع كملف

دقة الفيديو المدعومة في Sora 2 API

وفقاً للوثائق الرسمية من OpenAI، تدعم واجهة Sora 2 API حالياً الدقات التالية:

الدقة العرض × الارتفاع النسبة سيناريوهات الاستخدام
720p أفقي 1280 x 720 16:9 يوتيوب، فيديوهات الويب
720p عمودي 720 x 1280 9:16 تيك توك، ريلز
1080p أفقي (Pro) 1792 x 1024 ~16:9 فيديوهات أفقية عالية الدقة
1080p عمودي (Pro) 1024 x 1792 ~9:16 فيديوهات عمودية عالية الدقة

🎯 تنبيه هام: يجب أن تكون صورة الإدخال الخاصة بك متطابقة تماماً بالبكسل مع دقة الهدف المختارة. على سبيل المثال، إذا اخترت دقة 1280×720، يجب أن تكون الصورة بالضبط 1280×720 بكسل؛ أي اختلاف ولو ببكسل واحد سيؤدي إلى خطأ.

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


5 حلول لأخطاء حجم الصور المرجعية في واجهة برمجة تطبيقات Sora 2

الحل الأول: القص والملء الذكي باستخدام Python Pillow

باستخدام طريقة ImageOps.pad() من مكتبة Pillow، يمكنك معالجة الصور بأي حجم بذكاء، مع الحفاظ على نسبة العرض إلى الارتفاع وملء الحواف للوصول إلى الحجم المطلوب:

from PIL import Image, ImageOps
import openai

# دقة الصور القياسية التي تدعمها واجهة برمجة تطبيقات Sora 2
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"""
    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 - عبر واجهة 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
    )

🚀 بداية سريعة: نوصي باستخدام منصة APIYI (apiyi.com) لاختبار واجهة برمجة تطبيقات Sora 2 بسرعة، حيث توفر المنصة واجهة موحدة جاهزة للاستخدام تتيح لك إتمام التكامل دون تعقيدات في الإعدادات.

الحل الثاني: القص المركزي باستخدام Python Pillow (للحفاظ على العناصر الأساسية)

إذا كنت تفضل الحفاظ على المحتوى الأساسي للصورة دون وجود حواف سوداء، يمكنك استخدام طريقة القص المركزي:

from PIL import Image

def center_crop_for_sora(image_path, target_width, target_height):
    """القص المركزي للصورة لتتوافق مع متطلبات حجم واجهة برمجة تطبيقات Sora 2"""
    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)

الحل الثالث: المعالجة الدفعية عبر سطر أوامر 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 الأفقي بدقة 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

الحل الرابع: استخدام معامل crop_bounds (القص المدمج في API)

توفر واجهة برمجة تطبيقات Sora 2 معامل crop_bounds الذي يتيح لك تحديد منطقة القص مباشرة من خلال طلب API:

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 تظل المنطقة المقصوصة بحاجة للتوافق مع دقة الفيديو المستهدفة، لذا يُنصح بدمجها مع المعالجة المسبقة.

الحل الخامس: فئة أدوات كاملة للمعالجة المسبقة للصور

إليك فئة أدوات (Utility class) جاهزة للاستخدام في بيئة الإنتاج، تتضمن أوضاعاً متعددة للمعالجة:

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

class SoraImagePreprocessor:
    """أداة المعالجة المسبقة للصور المرجعية لواجهة Sora 2"""

    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 إلى تدفق بايتات لاستخدامها في رفع الملفات عبر 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"""

    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 إلى تدفق بايتات"""
        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:
        معرف مهمة إنشاء الفيديو
    """
    # 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
    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-ar 图示

وضع المعالجة المسبقة طريقة المعالجة المزايا العيوب السيناريو الموصى به
Pad (التعبئة) الحفاظ على النسبة مع إضافة حواف سوداء الحفاظ على الصورة كاملة قد تظهر حواف سوداء عندما تكون سلامة المحتوى ضرورية
Cover (القص) الحفاظ على النسبة مع القص من المنتصف لا توجد حواف سوداء، صورة ممتلئة قد يتم قص أطراف الصورة الصور التي يتوسطها العنصر الأساسي
Stretch (التمدد) تمدد قسري للصورة بسيط ومباشر تشويه في أبعاد الصورة لا ينصح باستخدامه

💡 نصيحة للاختيار: يعتمد اختيار وضع المعالجة المسبقة بشكل أساسي على محتوى صورتك والنتيجة النهائية التي تطمح إليها. نوصي بإجراء تجارب فعلية عبر منصة APIYI (apiyi.com) للتحقق بسرعة من الفوارق بين الأوضاع المختلفة.

الأوضاع الموصى بها لمختلف السيناريوهات

نوع الصورة الوضع الموصى به التوضيح
صور الأشخاص (Portrait) Cover للحفاظ على الشخص في المنتصف وبشكل كامل
صور المناظر الطبيعية Pad أو Cover اختر بناءً على تكوين الصورة (Composition)
صور المنتجات Pad لضمان ظهور المنتج بالكامل دون أي نقص
الصور الفنية Pad للحفاظ على التكامل الفني للعمل
لقطات واجهة المستخدم (UI) Cover عادةً ما تتركز المعلومات الهامة في المركز

الأسئلة الشائعة حول الصور المرجعية في Sora 2 API

س1: لماذا يفرض Sora 2 API قيوداً صارمة على أبعاد الصور المرجعية؟

يستخدم Sora 2 الصورة المرجعية (Image Prompt) كإطار أول (first frame) للفيديو، حيث يحتاج النموذج إلى البدء من هذا الإطار لتوليد المحتوى الديناميكي اللاحق. إذا لم تتطابق أبعاد الصورة مع الفيديو المستهدف، فلن يتمكن النموذج من تهيئة عملية التوليد بشكل صحيح. هذا قيد تقني من تصميم OpenAI لضمان استمرارية وجودة التوليد.

عند الاستدعاء عبر منصة APIYI apiyi.com، نوصي بإكمال المعالجة المسبقة للصور على جهة العميل (Client-side) للحصول على أفضل نتائج التوليد.

س2: أي تنسيق صور يجب أن أختار عند المعالجة المسبقة؟

يدعم Sora 2 API ثلاثة تنسيقات: JPEG و PNG و WebP:

  • JPEG: يوصى به للصور الفوتوغرافية، حيث يتميز بصغر حجم الملف وسرعة الرفع.
  • PNG: مناسب للحالات التي تتطلب خلفيات شفافة أو جودة غير منقوصة (Lossless).
  • WebP: يوازن بين الجودة والحجم، لكن توافقه قد يكون أقل قليلاً في بعض البيئات القديمة.

يُنصح باستخدام تنسيق JPEG مع ضبط معامل الجودة (quality) بين 90-95 لضمان الجودة مع التحكم في حجم الملف.

س3: ماذا أفعل إذا انخفضت جودة الصورة بعد المعالجة؟

عادةً ما ينتج انخفاض جودة الصورة عن الأسباب التالية:

  1. الضغط المفرط: ارفع جودة JPEG إلى 95.
  2. التكبير الزائد: حاول استخدام صور أصلية بدقة قريبة من الدقة المستهدفة.
  3. خوارزمية إعادة العينات: استخدم Image.LANCZOS بدلاً من Image.NEAREST.
# إعدادات معالجة عالية الجودة
img = img.resize(target_size, Image.LANCZOS)  # استخدام خوارزمية Lanczos
img.save(output_path, "JPEG", quality=95)     # حفظ بجودة عالية
س4: كيف يمكنني معالجة كمية كبيرة من الصور دفعة واحدة؟

بالنسبة لسيناريوهات المعالجة الجماعية، يوصى باستخدام FFmpeg أو تعدد الخيوط (Multi-threading) في بايثون:

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

يمكنك الحصول على حصص API للمعالجة الجماعية عبر منصة APIYI apiyi.com، وهي مناسبة لمشاريع توليد الفيديو واسعة النطاق.

س5: هل سيتم رفض الصور التي تحتوي على وجوه بشرية؟

نعم، وفقاً لسياسات OpenAI، سيتم حالياً رفض الصور المرجعية التي تحتوي على وجوه بشرية حقيقية بواسطة Sora 2 API. إذا كان عملك يتطلب فيديوهات لأشخاص، فنحن نقترح:

  1. استخدام صور لا تظهر فيها ملامح الوجه بوضوح.
  2. استخدام صور لشخصيات افتراضية تم إنشاؤها بواسطة الذكاء الاصطناعي.
  3. استخدام صور لأشخاص تمت معالجتها بشكل تجريدي أو فني.

جدول مرجعي سريع لأبعاد صور Sora 2 API

لتسهيل البحث السريع، إليك الجدول الكامل لمطابقة الأبعاد:

الفيديو المستهدف عرض الصورة ارتفاع الصورة معامل size في الـ API المنصات المناسبة
720p أفقي 1280 720 "1280×720" YouTube، ويب
720p رأسي 720 1280 "720×1280" Douyin، TikTok
Pro أفقي 1792 1024 "1792×1024" شاشات أفقية عالية الدقة
Pro رأسي 1024 1792 "1024×1792" شاشات رأسية عالية الدقة

📌 نصيحة: تشمل المنصات المتاحة APIYI apiyi.com، والـ API الرسمي لـ OpenAI، وغيرها. يُنصح باختيار المنصات التي تتميز بسرعة استجابة وأسعار تنافسية لأعمال التطوير والاختبار.


الخلاصة

يُعد خطأ حجم الصورة المرجعية (Reference Image) في Sora 2 API أحد أكثر المشكلات شيوعاً التي يواجهها المطورون، وتتمثل فكرة الحل الأساسية في:

  1. فهم القواعد: يجب أن يتطابق حجم الصورة المرجعية مع أبعاد الفيديو المستهدف على مستوى البكسل.
  2. اختيار الوضع: اختر وضع Pad أو Cover بناءً على محتوى الصورة.
  3. المعالجة المسبقة: استخدم مكتبة Python Pillow أو أداة FFmpeg للمعالجة المسبقة.
  4. التحقق من الأبعاد: تحقق من مطابقة أبعاد الصورة بعد المعالجة.

نوصي باستخدام APIYI (apiyi.com) للتحقق بسرعة من فعالية المعالجة المسبقة للصور وجودة إنشاء الفيديو.


المؤلف: فريق APIYI | لمزيد من تقنيات تطوير الذكاء الاصطناعي، يرجى زيارة apiyi.com

المصادر:

  1. وثائق OpenAI Sora API: شرح واجهة تحويل الصور إلى فيديو
    • الرابط: 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

موضوعات ذات صلة