HiAPI
Блог

Руководство

Генерация изображений товаров точных размеров через API: соотношения сторон и требования торговых площадок

Jul 9, 2026
Генерация изображений товаров точных размеров через API: соотношения сторон и требования торговых площадок

Каждый канал продаж требует своих размеров изображений товара: Amazon нужны большие квадратные изображения на белом фоне, Instagram — вертикальная композиция 4:5, Pinterest — пин 2:3, а главному баннеру вашего собственного магазина нужны сверхширокие изображения. В этом руководстве рассказывается, как программно генерировать изображения всех этих размеров с помощью hiapi API — используя gpt-image-2 и wan2.7-image — а также как каждый раз точно попадать в целевой размер в пикселях.

Предварительные требования: ключ hiapi API (создаётся в консоли), а также curl или Python. Общая стоимость зависит от выбранной модели и разрешения — см. цены.

Как на самом деле работают размеры изображений в API

Сначала о самом запутанном моменте: модели изображений на hiapi не принимают размеры в пикселях. Нет полей size, width или height. Если вы попытаетесь их передать, API прямо сообщит:

{
  "code": 400,
  "error_code": "INVALID_REQUEST",
  "message": "invalid input: <root>: additional properties 'size' not allowed"
}

Вместо этого размером управляют два поля в input:

  • aspect_ratio — форма кадра, выбирается из фиксированного списка каждого модели.
  • resolution — уровень вывода: "1K", "2K" или "4K" (длинная сторона примерно 1024 / 2048 / 4096 пикселей; точное количество пикселей зависит от соотношения, поэтому обязательно проверяйте полученный файл).

Ниже приведены параметры, которые реально принимают две модели из этого руководства (проверено на рабочем API):

gpt-image-2 wan2.7-image/text-to-image
prompt обязательно обязательно
aspect_ratio auto, 1:1, 3:2, 2:3, 4:3, 3:4, 5:4, 4:5, 16:9, 9:16, 2:1, 1:2, 3:1, 1:3, 21:9, 9:21 — всего 16 значений 1:1, 16:9, 4:3, 21:9, 3:4, 9:16, 8:1, 1:8 — всего 8 значений
resolution 1K, 2K, 4K 1K, 2K, 4K
Дополнительные возможности Вариант «изображение в изображение» (gpt-image-2/image-to-image) seed (целое число) для воспроизводимости
Пиксельный size / n не принимается не принимается

Практическая разница такова: gpt-image-2 покрывает соотношения, необходимые для форматов социальных сетей и электронной коммерции (4:5, 2:3, 5:4 — уникальны для gpt-image-2), а wan2.7-image добавляет сверхширокие полосы 8:1/1:8, которых нет ни в одном другом списке соотношений — подходит для узких рекламных баннеров — и является обычным выбором для 4K студийных снимков.

Таким образом, для точного контроля размеров рецепт состоит из двух шагов:

  1. Генерировать с соответствующим соотношением сторон и выбрать минимальный уровень разрешения, при котором длинная сторона достигает или превышает целевой размер (затем уменьшать, никогда не увеличивать).
  2. Локально привести возвращённый файл к точным целевым пикселям — одна строка кода Pillow.

Шпаргалка по требованиям торговых площадок

Ниже приведены типичные публичные требования, сопоставленные с параметрами API:

Канал Типичная цель aspect_ratio resolution Примечания по модели
Главное изображение Amazon длинная сторона ≥1000 пикселей (масштабирование включается при 1600+ пикселях), квадрат, чисто белый фон 1:1 2K подходят обе
Страница товара Shopify рекомендуется 2048×2048 1:1 2K подходят обе
Лента Instagram (вертикальная) 1080×1350 4:5 2K только gpt-image-2
Stories / Reels / TikTok 1080×1920 9:16 2K подходят обе
Пин Pinterest 1000×1500 2:3 2K только gpt-image-2
Листинг на Etsy рекомендуется 2700×2025 4:3 4K подходят обе (нужен уровень 4K)
Главный баннер сайта например, ширина 2560 пикселей 21:9 4K подходят обе
Узкий рекламный баннер сверхширокий 8:1 2K/4K только wan2.7-image

(Требования площадок меняются; рассматривайте эти целевые пиксели как типичные публичные рекомендации и сверяйтесь с актуальной документацией каждой платформы.)

Минимальный рабочий пример (curl)

Всё работает через единый эндпоинт асинхронных задач: создание через POST /v1/tasks, опрос через GET /v1/tasks/<id>. Создаём квадратное изображение в стиле Amazon с уровнем 2K:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2/text-to-image",
    "input": {
      "prompt": "Studio product photo of a stainless steel water bottle on a pure white background, centered, soft shadow, e-commerce catalog style",
      "aspect_ratio": "1:1",
      "resolution": "2K"
    }
  }'

Идентификатор задачи в ответе находится в data.taskId. Опрашиваем его:

curl -s https://api.hiapi.ai/v1/tasks/TASK_ID \
  -H "Authorization: Bearer sk-YOUR_KEY"

Опрашивайте, пока data.status не станет "success" (или "fail", подробности в data.error). URL изображения находится в data.output[0].url. Этот URL истекает (объект вывода содержит expireAt), поэтому сразу скачивайте и перехостите его в своё хранилище — никогда не используйте прямые ссылки в листингах товаров.

Продакшн-скрипт: один товар, все каналы, точные пиксели

Этот пакетный скрипт заранее создаёт все задачи (они выполняются на платформе параллельно), опрашивает каждую до завершения, а затем приводит изображение к точному целевому размеру с помощью Pillow. ImageOps.fit за один вызов выполняет и уменьшение, и любую незначительную обрезку.

import os
import time
from io import BytesIO

import requests
from PIL import Image, ImageOps

API = "https://api.hiapi.ai/v1"
HDRS = {
    "Authorization": f"Bearer {os.environ['HIAPI_KEY']}",
    "Content-Type": "application/json",
}

# канал -> параметры генерации + точная цель в пикселях
SPECS = {
    "amazon-main":    {"model": "gpt-image-2/text-to-image", "aspect_ratio": "1:1",  "resolution": "2K", "px": (1600, 1600)},
    "shopify":        {"model": "gpt-image-2/text-to-image", "aspect_ratio": "1:1",  "resolution": "2K", "px": (2048, 2048)},
    "instagram-feed": {"model": "gpt-image-2/text-to-image", "aspect_ratio": "4:5",  "resolution": "2K", "px": (1080, 1350)},
    "story-reel":     {"model": "gpt-image-2/text-to-image", "aspect_ratio": "9:16", "resolution": "2K", "px": (1080, 1920)},
    "pinterest-pin":  {"model": "gpt-image-2/text-to-image", "aspect_ratio": "2:3",  "resolution": "2K", "px": (1000, 1500)},
    "etsy-listing":   {"model": "wan2.7-image/text-to-image", "aspect_ratio": "4:3",  "resolution": "4K", "px": (2700, 2025)},
    "hero-banner":    {"model": "wan2.7-image/text-to-image", "aspect_ratio": "21:9", "resolution": "4K", "px": (2560, 1097)},
}

PROMPT = (
    "Studio product photo of a stainless steel water bottle on a pure white "
    "background, centered, soft shadow, high detail, e-commerce catalog style"
)


def create_task(model: str, prompt: str, aspect_ratio: str, resolution: str) -> str:
    body = {
        "model": model,
        "input": {"prompt": prompt, "aspect_ratio": aspect_ratio, "resolution": resolution},
    }
    data = requests.post(f"{API}/tasks", json=body, headers=HDRS, timeout=60).json()
    task_id = (data.get("data") or {}).get("taskId")
    if not task_id:
        raise RuntimeError(f"create failed: {data}")
    return task_id


def wait_task(task_id: str, timeout_s: int = 600) -> str:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        data = requests.get(f"{API}/tasks/{task_id}", headers=HDRS, timeout=30).json()
        task = data.get("data") or {}
        if task.get("status") == "success":
            return task["output"][0]["url"]
        if task.get("status") == "fail":
            err = task.get("error") or {}
            raise RuntimeError(f"task {task_id} failed: {err.get('code')} {err.get('message')}")
        time.sleep(5)
    raise TimeoutError(f"task {task_id} did not finish in {timeout_s}s")


def save_exact(url: str, px: tuple, path: str) -> None:
    # URL вывода истекает — скачиваем сразу, затем подгоняем под точные пиксели.
    raw = requests.get(url, timeout=120).content
    img = Image.open(BytesIO(raw))
    ImageOps.fit(img, px, Image.LANCZOS).save(path)


if __name__ == "__main__":
    # Сначала создаём все задачи: задачи выполняются на платформе параллельно
    tasks = {
        name: create_task(s["model"], PROMPT, s["aspect_ratio"], s["resolution"])
        for name, s in SPECS.items()
    }
    for name, task_id in tasks.items():
        url = wait_task(task_id)
        save_exact(url, SPECS[name]["px"], f"{name}.png")
        print(f"{name}: {SPECS[name]['px']} -> {name}.png")

Даже если вы перепишете всё остальное, стоит скопировать две детали:

  • Выбирайте уровень разрешения так, чтобы длинная сторона была ≥ целевой. Цель Etsy в 2700 пикселей превышает примерно 2048 пикселей уровня 2K, поэтому генерируйте в 4K, а затем уменьшайте. Уменьшение LANCZOS визуально неразрушающе для каталогов товаров; увеличение — нет.
  • Сразу сохраняйте taskId после создания задачи. Если ваш worker упадёт, при восстановлении опрашивайте сохранённый id, а не создавайте задачу заново — повторное создание сгенерирует (и спишет оплату) за второе изображение.

Вместо этого перекомпонуйте проверенное главное изображение

Часто вам нужны не семь независимо сгенерированных изображений, а одно и то же проверенное изображение товара, перекомпонованное для каждого канала. Для этого есть gpt-image-2/image-to-image: он принимает input_urls (массив публично доступных URL изображений) и prompt, а также принимает те же 16 значений aspect_ratio:

{
  "model": "gpt-image-2/image-to-image",
  "input": {
    "prompt": "Extend the background naturally to fill the new frame; keep the product unchanged and centered",
    "input_urls": ["https://your-cdn.com/hero-shot.png"],
    "aspect_ratio": "9:16"
  }
}

Тот же жизненный цикл задачи и та же финальная подгонка под точные пиксели. Полный разбор см. в How to Use gpt-image-2 Image-to-Image via the hiapi API.

Замечания для продакшна

Используйте обратный вызов вместо опроса. На серверной стороне передайте верхнеуровневый callback при создании задачи и полностью пропустите цикл опроса:

{
  "model": "gpt-image-2/text-to-image",
  "input": {"prompt": "...", "aspect_ratio": "1:1", "resolution": "2K"},
  "callback": {"url": "https://yourapp.com/hooks/hiapi", "when": "final"}
}

Вы получите один POST на финальном статусе. Относитесь к обратному вызову как к сигналу, а не источнику истины: перед действием повторно запросите GET /v1/tasks/<id> и дедуплицируйте по taskId. Если обратный вызов так и не пришёл, см. Why your hiapi task callback isn't firing.

Обработка ошибок. Неудачная аутентификация возвращает 401 permission_denied — сначала проверьте заголовок Authorization: Bearer sk-.... Ошибка валидации возвращает 400 с error_code: "INVALID_REQUEST", и её сообщение особенно полезно: оно перечисляет точные разрешённые значения (так и была проверена таблица соотношений выше). Схема ввода зависит от модели — wan2.7-image принимает seed, gpt-image-2 не принимает; некоторые быстрые модели полностью отклоняют resolution — поэтому перед жёстким кодированием полей сверяйтесь со страницей каждой модели.

Контроль затрат. Цена зависит от модели и уровня разрешения. При итерации промптов генерируйте в 1K и переключайтесь на 2K/4K только для финальных версий — актуальные цены за изображение на странице цен.

Связанные материалы

Часто задаваемые вопросы

Могу ли я передать в запросе точные размеры в пикселях, например 1080×1350? Нет. size, width и height отклоняются с 400 (additional properties ... not allowed). Генерируйте с соответствующим aspect_ratio и уровнем resolution не ниже целевого, а затем локально уменьшайте до точных пикселей — это та самая одна строка Pillow выше.

Какие настройки использовать для главного изображения Amazon? aspect_ratio: "1:1", resolution: "2K", затем приведите к целевому размеру (1600×1600 — надёжное значение по умолчанию — выше порога масштабирования в 1000 пикселей). Главное изображение Amazon также требует чисто белого фона, поэтому включите это в промпт и проверяйте вывод перед публикацией.

Моего целевого соотношения нет в списке (например, 1.91:1 для рекламных форматов). Что делать? Генерируйте с ближайшим более широким или равным соотношением, которое полностью покрывает цель — для 1.91:1 подойдут 2:1 или 16:9 — затем обрезайте по центру. ImageOps.fit в скрипте делает именно это: за один вызов обрезает лишнее и приводит к размеру.

Как получить настоящие 4K изображения товаров? Установите resolution: "4K" на обеих моделях. wan2.7-image — обычный выбор для изображений в 4K студийном стиле; шаблоны промптов см. в руководстве по Wan 2.7 для электронной коммерции.

Истекают ли URL сгенерированных изображений? Да — каждый вывод содержит expireAt. Сразу после успеха задачи скачайте файл и перехостите его в своё хранилище. Никогда не вставляйте URL вывода задачи в листинги товаров.

Могу ли я сгенерировать несколько вариантов за один запрос? Нет — у этих моделей нет параметра n. Создавайте по одной задаче на изображение; задачи выполняются параллельно, поэтому пакетная обработка в цикле (как в скрипте выше) на практике так же быстра. В wan2.7-image можно менять seed, чтобы получить контролируемые варианты одного и того же промпта.

Похожие статьи

Все статьи →

Начните работать с постоянными артефактами ИИ

Получите API-ключ и вызывайте модели изображений, видео и аудио через один API на основе tasks.

Читать документацию API