> ## Documentation Index
> Fetch the complete documentation index at: https://docs.laozhang.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Редактирование изображений через Nano Banana API (Standard)

> Правка и объединение изображений через gemini-2.5-flash-image в LaoZhang API, который всё ещё обслуживает модель после даты отключения у Google, и переход на Nano Banana 2.

> [!WARNING]
>
> **Дата отключения `gemini-2.5-flash-image` у Google уже прошла. LaoZhang API пока обслуживает модель, но она может перестать работать в любой момент, поэтому переходите на новую модель заранее.**
>
> * Даты у Google расходятся: на 8 октября 2026 года его [страница об устаревших моделях](https://ai.google.dev/gemini-api/docs/deprecations) указывает 15 марта 2027 года, а страница цен всё ещё предупреждает о 2 октября 2026 года. На 5 октября 2026 года LaoZhang API берёт прежние \$0.02 за вызов, без гарантированной даты окончания.
> * Перенесите правки на Nano Banana 2 (`gemini-3.1-flash-image`) или на более дешёвую Nano Banana 2.1 (`gemini-nano-banana-2.1`, \$0.045 за вызов). Обе модели принимают те же запросы, поэтому достаточно сменить ID модели; см. раздел «Переход на Nano Banana 2».

Nano Banana Standard (`gemini-2.5-flash-image`) редактирует изображения по текстовой инструкции и может объединить до трёх изображений в одно. Ниже показано, как отправить правку, сохранить результат и перейти на Nano Banana 2.

| Параметр | Значение |
| - | - |
| ID модели | `gemini-2.5-flash-image` |
| Правки | Добавление и удаление объектов, замена фона, смена стиля фотографии, объединение до трёх изображений |
| Эндпоинты | OpenAI-совместимый `POST /v1/chat/completions` на `https://api.laozhang.ai`; нативный `generateContent`, если нужно конкретное соотношение сторон |
| Вход | Одна инструкция и 1–3 изображения PNG, JPEG или WebP в одном запросе |
| Выход | Одно изображение примерно 1K в Base64, которое нужно декодировать и сохранить |
| Соотношение сторон | 10 вариантов, только в нативном маршруте Gemini |
| Маска | Нет; опишите изменяемую область в инструкции |
| Цена | \$0.02 за вызов (публичные цены на 24 сентября 2026 года, см. [Цены на API моделей ИИ](https://docs.laozhang.ai/ru/models.md)) |
| Оплата | Каждый ответ HTTP 200 тарифицируется как один вызов, даже без изображения; см. [правила оплаты](https://docs.laozhang.ai/ru/api-capabilities/nano-banana-image.md) |

Standard — исходная модель Nano Banana; на этом сайте её называют Standard, чтобы отличать от всего семейства. Сравнение с Nano Banana 2 Lite, Nano Banana 2 и Nano Banana Pro приведено в [обзоре Nano Banana](https://docs.laozhang.ai/ru/api-capabilities/nano-banana-image.md).

## Подготовка

**1. Создайте API-ключ**

В разделе [Управление токенами](https://api.laozhang.ai/token) откройте диалог создания токена (创建令牌), в поле **Режим оплаты** (计费模式) выберите **«сначала по использованию»** (按量优先, рекомендуется) или **«оплата за вызов»** (按次计费) и нажмите **Создать** (创建). У моделей Nano Banana есть только цена за вызов: ключ с режимом «сначала по использованию» вызывает и их, и модели с оплатой по использованию, а ключ с режимом «оплата за вызов» — только модели с оплатой за вызов. Группа `default` включает `gemini-2.5-flash-image`.

![Диалог создания токена в консоли LaoZhang API с режимом оплаты «оплата за вызов» (按次计费)](https://mintcdn.com/laozhangai-edd05f2c/_loZ0Jy0ZI__xJ9z/images/token-create-per-request.png?fit=max\&auto=format\&n=_loZ0Jy0ZI__xJ9z\&q=85\&s=1fdceb804bb3ad50f83a21ec65b4d807)

**2. Задайте ключ и установите зависимости**

```bash theme={null}
export LAOZHANG_API_KEY="sk-..."  # замените на свой API-ключ LaoZhang API
python -m pip install openai requests
```

Для примеров с cURL нужен также `jq`, например `brew install jq` или `sudo apt-get install jq`.

**3. Сохраните модуль для обработки ответа**

Сохраните этот модуль как `nano_banana_save.py`. Примеры на Python импортируют его, а после запроса через cURL его запускают на сохранённом ответе. Модуль находит все изображения в ответе chat completions или `generateContent`, восстанавливает выравнивание Base64 и называет каждый файл по его настоящему формату:

```python theme={null}
"""Сохранение изображений из ответа Nano Banana (chat completions или generateContent)."""
import base64
import json
import re
import sys
from pathlib import Path

DATA_URL = re.compile(r"data:image/[\w.+-]+;base64,([A-Za-z0-9+/=]+)")


def _extension(raw):
    if raw.startswith(b"\x89PNG"):
        return "png"
    if raw.startswith(b"\xff\xd8\xff"):
        return "jpg"
    if raw[:4] == b"RIFF" and raw[8:12] == b"WEBP":
        return "webp"
    return "bin"


def save_images(body, stem):
    """Записывает каждое изображение из тела ответа в stem.png, stem-2.png и так далее."""
    if body.get("error"):
        raise RuntimeError(f"Ошибка API: {body['error']}")
    if "choices" in body:  # chat completions: data URL внутри message.content
        text = body["choices"][0]["message"].get("content") or ""
        found = DATA_URL.findall(text)
        detail = text[:300]
    else:  # generateContent: части inlineData; части thought не являются итоговым результатом
        parts = [
            part
            for candidate in body.get("candidates") or []
            for part in (candidate.get("content") or {}).get("parts") or []
            if not part.get("thought")
        ]
        blobs = [part.get("inlineData") or part.get("inline_data") for part in parts]
        found = [blob["data"] for blob in blobs if blob]
        detail = body.get("promptFeedback") or [c.get("finishReason") for c in body.get("candidates") or []]
    if not found:
        raise RuntimeError(f"Изображение не получено: {detail!r}")
    saved = []
    for number, encoded in enumerate(found, start=1):
        encoded = "".join(encoded.split())
        raw = base64.b64decode(encoded + "=" * (-len(encoded) % 4))
        suffix = "" if number == 1 else f"-{number}"
        path = Path(f"{stem}{suffix}.{_extension(raw)}")
        path.write_bytes(raw)
        saved.append(path)
    return saved


if __name__ == "__main__":
    # После запроса через cURL: python nano_banana_save.py response.json имя-файла
    response_body = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
    for saved_path in save_images(response_body, sys.argv[2]):
        print("Сохранено:", saved_path)
```

## Редактирование изображения

Поместите в одно сообщение пользователя сначала инструкцию, а за ней изображение. Локальный файл передаётся как data URL с MIME-типом, соответствующим файлу, например `data:image/jpeg;base64,...`.

> [tab] Python
>
> Сохраните скрипт как `nano_banana_edit.py`. Он отправляет инструкцию с одним–тремя изображениями — локальными файлами или публичными HTTPS-адресами — и сохраняет результат:
>
> ```python theme={null}
> """Редактирование и объединение изображений через Nano Banana Standard (gemini-2.5-flash-image)."""
> import argparse
> import base64
> import os
> import sys
> from pathlib import Path
>
> from openai import OpenAI
>
> from nano_banana_save import save_images
>
> MIME_TYPES = {".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".webp": "image/webp"}
>
> parser = argparse.ArgumentParser(description="Отредактировать одно изображение или объединить до трёх.")
> parser.add_argument("prompt", help="инструкция для правки")
> parser.add_argument("images", nargs="+", help="локальные файлы PNG, JPEG или WebP либо публичные HTTPS-адреса")
> parser.add_argument("--out", default="nano-banana-edit", help="имя выходного файла без расширения")
> args = parser.parse_args()
> if len(args.images) > 3:
>     sys.exit("gemini-2.5-flash-image лучше всего работает не более чем с 3 входными изображениями.")
>
> content = [{"type": "text", "text": args.prompt}]
> for source in args.images:
>     if source.startswith("https://"):
>         url = source  # публичный URL изображения отправляется как есть
>     else:
>         mime = MIME_TYPES.get(Path(source).suffix.lower())
>         if mime is None:
>             sys.exit(f"Нужен файл PNG, JPEG или WebP: {source}")
>         url = f"data:{mime};base64," + base64.b64encode(Path(source).read_bytes()).decode("ascii")
>     content.append({"type": "image_url", "image_url": {"url": url}})
>
> # max_retries=0: автоповтор после таймаута мог бы сгенерировать и оплатить изображение дважды
> client = OpenAI(api_key=os.environ["LAOZHANG_API_KEY"], base_url="https://api.laozhang.ai/v1", timeout=300, max_retries=0)
> reply = client.chat.completions.create(
>     model="gemini-2.5-flash-image",
>     messages=[{"role": "user", "content": content}],
> )
> for path in save_images(reply.model_dump(), args.out):
>     print("Сохранено:", path)
> ```
>
> Замените фон на фотографии товара:
>
> ```bash theme={null}
> python nano_banana_edit.py "Замени фон на однотонную светло-серую студийную стену. Товар, его этикетку и тень оставь без изменений." product.jpg --out product-studio
> ```

> [tab] cURL
>
> Закодируйте файл и соберите тело через `jq`, затем отправьте тело из файла, чтобы большое изображение не превысило лимиты аргументов shell. MIME-тип в data URL (здесь `image/jpeg`) должен соответствовать файлу:
>
> ```bash theme={null}
> base64 < product.jpg | tr -d '\n' > product.b64
> jq -n --rawfile image product.b64 '{
>   model: "gemini-2.5-flash-image",
>   stream: false,
>   messages: [{
>     role: "user",
>     content: [
>       {type: "text", text: "Замени фон на однотонную светло-серую студийную стену. Товар, его этикетку и тень оставь без изменений."},
>       {type: "image_url", image_url: {url: ("data:image/jpeg;base64," + $image)}}
>     ]
>   }]
> }' > edit-request.json
>
> curl --fail-with-body --max-time 300 \
>   "https://api.laozhang.ai/v1/chat/completions" \
>   -H "Authorization: Bearer $LAOZHANG_API_KEY" \
>   -H "Content-Type: application/json" \
>   --data-binary @edit-request.json \
>   -o edit-response.json
>
> python nano_banana_save.py edit-response.json product-studio
> ```

Отредактированное изображение сохраняется как `product-studio.png`, `.jpg` или `.webp` — в зависимости от формата, который вернула модель. Формулируйте изменение как инструкцию: на промпт, похожий на вопрос, модель может ответить только текстом.

### Объединение двух или трёх изображений

Перечислите файлы после инструкции в том порядке, в котором вы на них ссылаетесь, и назовите в промпте роль каждого изображения:

```bash theme={null}
python nano_banana_edit.py "Посади кошку с первого изображения на диван со второго изображения. Согласуй её с освещением комнаты, диван не меняй." cat.png sofa.jpg --out cat-on-sofa
```

По словам Google, `gemini-2.5-flash-image` лучше всего работает не более чем с тремя входными изображениями. Если референсов больше или нужно сохранить внешность нескольких людей на разных изображениях, используйте [Nano Banana 2.1](https://docs.laozhang.ai/ru/api-capabilities/nano-banana-2-1-image.md), [Nano Banana 2](https://docs.laozhang.ai/ru/api-capabilities/nano-banana2-image.md) или [Nano Banana Pro](https://docs.laozhang.ai/ru/api-capabilities/nano-banana-pro-image-edit.md): они принимают до 14 изображений.

### Передача изображения по URL

Вместо локального файла можно передать публичный адрес `https://`; скрипт отправит его без изменений как `image_url`:

```bash theme={null}
python nano_banana_edit.py "Добавь радугу над холмами. Всё остальное оставь без изменений." https://example.com/images/hills.jpg --out hills-rainbow
```

Изображение скачивается по этому адресу во время запроса, поэтому оно должно открываться без входа, cookie и проверок на ботов. Если скачать его не удаётся, загрузите файл к себе и передайте локальную копию.

## Выбор соотношения сторон

На OpenAI-совместимом маршруте соотношение сторон задать нельзя. Чтобы выбрать форму результата, вызовите нативный эндпоинт Gemini и задайте `generationConfig.imageConfig.aspectRatio` одним из этих значений:

| Форма | Допустимые значения |
| - | - |
| Квадрат | `1:1` |
| Портретная | `2:3`, `3:4`, `4:5`, `9:16` |
| Альбомная | `3:2`, `4:3`, `5:4`, `16:9`, `21:9` |

* При любом соотношении Standard выдаёт изображение примерно 1K, поэтому `imageSize` не передавайте.
* Без `aspectRatio`, согласно документации Google, размер результата повторяет размер входного изображения.

> [tab] cURL
>
> ```bash theme={null}
> base64 < street.jpg | tr -d '\n' > street.b64
> jq -n --rawfile image street.b64 '{
>   contents: [{
>     role: "user",
>     parts: [
>       {text: "Преврати эту дневную уличную фотографию в дождливую ночь с неоновыми отражениями. Здания не меняй."},
>       {inlineData: {mimeType: "image/jpeg", data: $image}}
>     ]
>   }],
>   generationConfig: {
>     responseModalities: ["IMAGE"],
>     imageConfig: {aspectRatio: "16:9"}
>   }
> }' > native-edit-request.json
>
> curl --fail-with-body --max-time 300 \
>   "https://api.laozhang.ai/v1beta/models/gemini-2.5-flash-image:generateContent" \
>   -H "Authorization: Bearer $LAOZHANG_API_KEY" \
>   -H "Content-Type: application/json" \
>   --data-binary @native-edit-request.json \
>   -o native-edit-response.json
>
> python nano_banana_save.py native-edit-response.json street-night
> ```

> [tab] Python
>
> ```python theme={null}
> """Правка изображения через Nano Banana Standard в нативном маршруте Gemini с выбором соотношения сторон."""
> import base64
> import os
> import sys
> from pathlib import Path
>
> import requests
>
> from nano_banana_save import save_images
>
> image = base64.b64encode(Path("street.jpg").read_bytes()).decode("ascii")
> response = requests.post(
>     "https://api.laozhang.ai/v1beta/models/gemini-2.5-flash-image:generateContent",
>     headers={"Authorization": f"Bearer {os.environ['LAOZHANG_API_KEY']}"},
>     json={
>         "contents": [{
>             "role": "user",
>             "parts": [
>                 {"text": "Преврати эту дневную уличную фотографию в дождливую ночь с неоновыми отражениями. "
>                          "Здания не меняй."},
>                 {"inlineData": {"mimeType": "image/jpeg", "data": image}},
>             ],
>         }],
>         "generationConfig": {"responseModalities": ["IMAGE"], "imageConfig": {"aspectRatio": "16:9"}},
>     },
>     timeout=300,
> )
> if response.status_code != 200:
>     sys.exit(f"HTTP {response.status_code}: {response.text[:500]}")
> for path in save_images(response.json(), "street-night"):
>     print("Сохранено:", path)
> ```

На этом маршруте изображения передаются частями `inlineData` с `mimeType`, соответствующим каждому файлу, а эндпоинт принимает ключ как в `Authorization: Bearer`, так и в `x-goog-api-key`. Настройка клиента Google Gen AI SDK описана на странице [Протокол Gemini](https://docs.laozhang.ai/ru/api-reference/gemini.md).

## Обработка ответа

`nano_banana_save.py` обрабатывает оба формата ответа. Если вы разбираете ответы сами:

* **Chat completions**: изображение находится в тексте `choices[0].message.content`, обычно как изображение Markdown вида `![image](data:image/png;base64,iVBORw0...)`. Берите формат из data URL, а не считайте его PNG по умолчанию, перед декодированием уберите префикс `data:image/...;base64,`, а если длина не кратна 4, добавьте выравнивание `=`.
* **generateContent**: каждое изображение — это часть `inlineData` в `candidates[].content.parts[]` с `mimeType` и данными `data` в Base64.
  * Часть с пометкой `thought: true` не является итоговым результатом, пропускайте её.
* **Нет изображения**: ответ содержит только текст или ни в одной части нет `inlineData`.
  * В нативных ответах проверьте `finishReason` каждого кандидата и `promptFeedback`, если он есть.
  * Возможные значения: `IMAGE_SAFETY`, `IMAGE_PROHIBITED_CONTENT`, `NO_IMAGE`.

## Как писать инструкции для правки

* Назовите, что нужно изменить и что должно остаться прежним, например: «Замени только синий диван на коричневый кожаный. Подушки, остальную комнату и освещение не меняй». Параметра маски нет; Google называет такой подход семантической маской.
* В композиции ссылайтесь на каждое изображение по порядку и роли: «платье с первого изображения», «женщина со второго изображения».
* Чтобы защитить лицо или логотип, подробно опишите его и прямо скажите, что его нельзя менять.
* Описывайте нужный стиль, освещение или расположение, а не пишите «лучше» или «красивее».
* Если важна точность, вносите одно изменение за запрос. Для многошаговой правки отправляйте сохранённый результат на вход следующего запроса.

## Ошибки и оплата

Каждый вызов оплачивается по цене за вызов, включая запрос, который вернул HTTP 200 без изображения, например из-за блокировки проверкой безопасности. Не отправляйте такой запрос повторно без изменений; см. раздел «Как не платить за пустые ответы» в [обзоре Nano Banana](https://docs.laozhang.ai/ru/api-capabilities/nano-banana-image.md). [Правила оплаты](https://docs.laozhang.ai/ru/api-capabilities/nano-banana-image.md) действуют для всех моделей Nano Banana, а статус и списание по каждому запросу видны в [журнале вызовов](https://api.laozhang.ai/log).

* **HTTP 401**: проверьте API-ключ и заголовок `Authorization: Bearer`. Нужен API-ключ из раздела «Управление токенами», а не AccessToken аккаунта.
* **HTTP 400**: проверьте ID модели, JSON тела запроса и значение `aspectRatio`. Не передавайте `imageSize` в Standard.
* **HTTP 429, 5xx или таймаут**: повторите запрос с экспоненциальной задержкой. После таймаута сначала найдите запрос в журнале вызовов, чтобы не заплатить дважды за одну и ту же правку.
* **Большие фотографии**: Base64 увеличивает файл примерно на треть, поэтому очень крупные изображения уменьшайте перед кодированием.

## Переход на Nano Banana 2

Nano Banana 2 (`gemini-3.1-flash-image`) принимает те же запросы chat completions и `generateContent`, что и Standard, поэтому для перехода достаточно изменить одно значение:

```diff theme={null}
- "model": "gemini-2.5-flash-image"
+ "model": "gemini-3.1-flash-image"
```

В нативном маршруте Gemini ID модели входит в URL: `https://api.laozhang.ai/v1beta/models/gemini-3.1-flash-image:generateContent`. В скриптах на этой странице замените `gemini-2.5-flash-image` в аргументе `model` или в URL запроса. После перехода:

* Каждый вызов стоит \$0.055 (публичные цены на 24 сентября 2026 года).
* Правка может использовать до 14 референсов: не больше 10 изображений объектов и 4 изображений персонажей.
* В нативном маршруте Gemini доступны 14 соотношений сторон и параметр `imageSize` с одним из значений:
  * `512`, `1K`, `2K` или `4K`
* Результат для одного и того же промпта может отличаться, поэтому прогоните выборку своих обычных правок, прежде чем переводить рабочий трафик.

В руководстве Google по генерации изображений тем, кто уходит со Standard, рекомендована Nano Banana 2 Lite (`gemini-3.1-flash-lite-image`, \$0.025 за вызов). Lite редактирует одиночные изображения в 1K и использует тот же формат запроса.

Google отмечает, что Lite не оптимизирована для нескольких референсов и последовательной многошаговой правки, поэтому композиции оставьте на Nano Banana 2.1 или Nano Banana 2. Пример правки в Lite есть в разделе «Редактирование изображения» [руководства по Nano Banana 2 Lite](https://docs.laozhang.ai/ru/api-capabilities/nano-banana-2-lite-api.md).

## Частые вопросы

### Можно ли вызывать `gemini-2.5-flash-image` после 2 октября 2026 года?

Пока да. Страница цен Google предупреждала об отключении 2 октября 2026 года, а страница об устаревших моделях теперь указывает 15 марта 2027 года (на 8 октября 2026 года). На 5 октября 2026 года LaoZhang API обслуживает модель по прежней цене.

* LaoZhang API не гарантирует, как долго модель останется доступной; она может перестать работать в любой момент.
* После отключения запросы будут завершаться ошибкой. В отличие от ID с суффиксом `-preview`, эта модель не сопоставлена другой, поэтому запросы не перейдут на новую модель сами.

Переведите запросы на Nano Banana 2.1 или Nano Banana 2, а для правок одного изображения в 1K — на Nano Banana 2 Lite уже сейчас, чтобы правки не прервались.

### Может ли правка Standard вернуть 2K или 4K?

Нет. Standard выдаёт примерно 1K при любом соотношении сторон и не принимает `imageSize`; выбрать можно только соотношение, как в разделе «Выбор соотношения сторон». Для правок в 2K или 4K перейдите на Nano Banana 2 (см. раздел «Переход на Nano Banana 2») или используйте Nano Banana Pro и добавьте в запрос `imageSize`.

### Можно ли ещё использовать `gemini-2.5-flash-image-preview`?

Нет. Google отключил её 15 января 2026 года, согласно своей [странице об устаревших моделях](https://ai.google.dev/gemini-api/docs/deprecations), и в списке моделей LaoZhang API её нет. Поскольку дата отключения `gemini-2.5-flash-image` тоже прошла и модель может перестать работать в любой момент, переходите сразу на Nano Banana 2 (`gemini-3.1-flash-image`).

## Связанные материалы и источники

* [Обзор Nano Banana](https://docs.laozhang.ai/ru/api-capabilities/nano-banana-image.md) — сравнение пяти моделей, двух форматов запроса и правил оплаты
* [Nano Banana 2](https://docs.laozhang.ai/ru/api-capabilities/nano-banana2-image.md) — модель для перехода: до 14 референсов и вывод от 512px до 4K
* [Nano Banana 2 Lite](https://docs.laozhang.ai/ru/api-capabilities/nano-banana-2-lite-api.md) — недорогая генерация 1K и правка одного изображения
* [Редактирование Pro](https://docs.laozhang.ai/ru/api-capabilities/nano-banana-pro-image-edit.md) — правка нескольких изображений: до 14 референсов и вывод 4K
* [Журнал вызовов](https://docs.laozhang.ai/en/faq/call-logs.md) — статус и списание по запросу
* [Google: Nano Banana image generation](https://ai.google.dev/gemini-api/docs/image-generation) — промпты для правки, лимиты входа и выбор модели
* [Google: устаревшие модели Gemini API](https://ai.google.dev/gemini-api/docs/deprecations) — дата отключения `gemini-2.5-flash-image`
* [Google: справочник generateContent](https://ai.google.dev/api/generate-content) — поля `imageConfig`


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.