# OpenRouter 教程：用代码调用 Nano Banana 2 编辑图像

- 来源：OpenRouter：Announcements（RSS）
- 发布时间：2026-09-09 08:00
- AIHOT 分数：64
- AIHOT 标记：精选
- AIHOT 链接：https://aihot.news/items/cmtwlujuv02r0row7odx8rss3
- 原文链接：https://openrouter.ai/blog/tutorials/nano-banana

## 精选理由

原文给出完整可运行的图像编辑请求代码和提示词写法，读者可以照搬并把模型换成其他供应商做对比。

## AI 摘要

OpenRouter 发布教程，演示通过 API 向 google/gemini-3.1-flash-image（即 Nano Banana 2）发送源图和文本指令完成图像编辑，编辑结果以 base64 形式在响应中返回。教程给出 Python 和 TypeScript 示例、提示词写法、多轮小步编辑方法，以及更换模型只需改一个字段，并介绍了 Nano Banana 系列四个成员的价格与质量差异。

## 正文

本指南展示如何在代码中通过文本提示词编辑图像。你通过 OpenRouter API 将源图像和编辑提示词发送给 google/gemini-3.1-flash-image，编辑后的图像会在响应中返回。"Nano Banana" 是 Google Gemini 图像模型的昵称。此 slug 为 Nano Banana 2，是该系列中默认的快速模型。由于你通过 一个 API 访问它，之后只需更改一个字段即可使用不同的编辑模型。

图像编辑是对现有图像进行修改。图像生成是根据文本创建新图像。本指南涵盖的是编辑，因此这里的每个请求都包含一张源图像。如需根据文本创建图像，请参阅 图像生成文档或 图像生成教程。

简而言之

编辑只需一次请求。将源图像放入 input_references，将指令放入 prompt，然后从 data[0].b64_json 读取编辑后的图像并将其解码到磁盘。

google/gemini-3.1-flash-image 是 Nano Banana 2，默认的快速 Gemini 图像模型。在使用某个模型之前，请确认它接受图像输入，因为编辑支持情况各不相同。

对于本地或私有文件，将输入作为 base64 数据 URL 发送；对于托管图像，则使用普通的 HTTP(S) URL。

以小步进行编辑。将每次返回的图像作为下一次的源图像发回，每次调用只给一条指令，这样修改就会逐步叠加。

只需编辑一个字段即可更改编辑模型。

前置条件

你需要三样东西：

一个来自密钥页面的 OpenRouter API key，以及基础 URL https://openrouter.ai/api/v1。

一个 HTTP 客户端。示例使用 Python requests 和 TypeScript fetch。你也可以使用 curl 或 OpenRouter SDK。任何能发送带 Authorization 头的 JSON POST 请求的客户端都可以。

一张源图像，可以是本地文件或公开 URL。

使用哪个模型

本指南的默认模型是 google/gemini-3.1-flash-image，即 Nano Banana 2。它以图像作为输入并返回编辑后的图像。Nano Banana 系列目前有四个成员：Nano Banana 2（google/gemini-3.1-flash-image）是本指南的默认模型，Nano Banana 2 Lite（google/gemini-3.1-flash-lite-image）最便宜、最快，Nano Banana Pro（google/gemini-3-pro-image）速度较慢但质量更高，而最初的 Nano Banana（google/gemini-2.5-flash-image）是这个昵称最初来源的较旧模型。

图像目录经常变化。模型会被新增、弃用和重新定价，因此你今天固定的 slug 之后可能会被停用。在基于某个模型进行开发之前，请确认它接受图像输入并支持你所需的编辑功能。你可以在 图像模型合集中浏览支持编辑的模型。如需了解目录的完整介绍，请参阅 图像生成模型。

下面的示例使用每个请求中所示的 slug，因此你可以按原样运行它们，之后再更改模型。请将你的密钥保存在环境变量中，而不是代码里：

export OPENROUTER_API_KEY="sk-or-..."

你的第一次图像编辑

要编辑图像，请在单个请求中发送源图像和文本指令。编辑后的图像会在响应中返回。以下是一个可运行的 Python 请求，它对本地文件进行编码：

import base64, os, requests

api_key = os.environ["OPENROUTER_API_KEY"]

# Encode a local source image as a base64 data URL. with open("portrait.jpg", "rb") as f: encoded = base64.b64encode(f.read()).decode() source = f"data:image/jpeg;base64,{encoded}"

resp = requests.post( "https://openrouter.ai/api/v1/images", headers={"Authorization": f"Bearer {api_key}"}, json={ "model": "google/gemini-3.1-flash-image", "prompt": "Add a red wool scarf around the person's neck. Keep everything else the same.", "input_references": [ {"type": "image_url", "image_url": {"url": source}} ], }, ) resp.raise_for_status()

TypeScript 中的相同请求：

import { readFileSync } from "node:fs";

const apiKey = process.env.OPENROUTER_API_KEY!; const encoded = readFileSync("portrait.jpg").toString("base64"); const source = `data:image/jpeg;base64,${encoded}`;

const resp = await fetch("https://openrouter.ai/api/v1/images", { method: "POST", headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ model: "google/gemini-3.1-flash-image", prompt: "Add a red wool scarf around the person's neck. Keep everything else the same.", input_references: [{ type: "image_url", image_url: { url: source } }], }), });

两种语言的请求体相同。将参考图像放入 input_references，将指令放入 prompt。这就是整个请求。

对输入图像进行编码：base64 或 URL

input_references 字段接受 base64 数据 URL 或 HTTP(S) URL。上面的示例对本地文件进行编码。如果你的图像已经公开托管，直接传入链接并跳过编码即可：

"input_references": [ {"type": "image_url", "image_url": {"url": "https://example.com/portrait.jpg"}} ]

当图片是公开托管时，请使用 URL，因为这样可以保持请求体较小。对于本地或私有文件，请使用 base64。Gemini 接受 image/png、image/jpeg、image/webp、image/heic 和 image/heif 输入。支持的格式因模型而异，因此发送前请查看模型页面。

从响应中获取编辑后的图像

API 会将编辑后的图像以 base64 数据的形式返回在 data 数组中。解码 b64_json 值并将其写入文件：

data = resp.json()["data"][0] with open("edited.png", "wb") as out: out.write(base64.b64decode(data["b64_json"]))

TypeScript 版本：

import { writeFileSync } from "node:fs";

const { data } = await resp.json(); writeFileSync("edited.png", Buffer.from(data[0].b64_json, "base64"));

打开 edited.png 查看结果。如果你想要类型化客户端而非原始 HTTP，OpenRouter SDK 提供了一个 images 资源，它调用同一个端点：

from openrouter import OpenRouter

client = OpenRouter(api_key=api_key) result = client.images.generate( model="google/gemini-3.1-flash-image", prompt="Add a red wool scarf around the person's neck. Keep everything else the same.", input_references=[{"type": "image_url", "image_url": {"url": source}}], )

使用 pip install openrouter 安装 SDK。它复用之前定义的 api_key，因此无需额外设置。

编写编辑提示词

生成提示词描述一整张新图像。编辑提示词则说明要更改什么、保留什么。先说明更改内容，再指明必须保持不变的部分：

物体替换：“将咖啡杯替换为一杯橙汁。保持手部位置和背景不变。”

背景更换：“将背景更改为夜晚的雪天街道。保持主体完全不变。”

风格迁移：“把这张照片渲染成水彩画。保留构图和主体的姿态。”

文字修复：“把招牌上的文字改成‘OPEN’。匹配原有的字体和颜色。”

你也可以把提示词写成一小段 JSON 文本：

"prompt": "{\"edit\": \"add sunglasses\", \"preserve\": [\"face\", \"hair\", \"lighting\"], \"style\": \"photorealistic\"}"

API 会把它当作纯文本处理，所以这并不是一种特殊模式。这种结构有助于模型区分哪些要改、哪些要保留。可以在你自己的图片上分别试试句子形式和 JSON 形式，哪种效果更好就用哪种。

再次编辑结果

一次编辑并不总能得到你想要的效果。要再跑一遍，就把返回的图片作为下一次的源图传回去。从响应中取出 b64_json 值，把它转成 data URL，然后在下一个 input_references 中传入：

def edit(source_data_url, prompt): resp = requests.post( "https://openrouter.ai/api/v1/images", headers={"Authorization": f"Bearer {api_key}"}, json={ "model": "google/gemini-3.1-flash-image", "prompt": prompt, "input_references": [ {"type": "image_url", "image_url": {"url": source_data_url}} ], }, ) resp.raise_for_status() item = resp.json()["data"][0] media_type = item.get("media_type", "image/png") return f"data:{media_type};base64,{item['b64_json']}"

step1 = edit(source, "Add a red wool scarf. Keep everything else the same.") step2 = edit(step1, "Now make the scarf navy blue instead of red.") step3 = edit(step2, "Add soft morning light coming from the left.")

每次调用都会编辑上一次的结果，因此之前的改动会延续下来。每次调用只给一条指令。小改动更容易检查，出错时也更容易重做。模型不会记住你之前的提示词，所以每次新的提示词里都要重复那些应当保持不变的部分。

更换编辑模型

要把同一个编辑请求发给另一个模型，只需更改 model 字段。源图、提示词以及响应处理代码都保持不变：

json={ "model": "openai/gpt-5-image", # was google/gemini-3.1-flash-image "prompt": "Add a red wool scarf. Keep everything else the same.", "input_references": [ {"type": "image_url", "image_url": {"url": source}} ], },

使用google/gemini-3.1-flash-image作为快速的默认选择。当你想要最低价格时，使用google/gemini-3.1-flash-lite-image。当你想要更高质量并能接受更高延迟时，使用google/gemini-3-pro-image。原有的google/gemini-2.5-flash-image仍可使用相同的请求结构，但上述更新的模型是更好的默认选择。当你想要openai/gpt-5-image时，使用来自其他提供商的模型，例如比较质量、成本或速度在你自己的图像上。这一单字段的更改仅适用于接受图像输入并支持相同input_references结构的模型，因此在切换之前请确认该模型具备编辑能力。

要按环境设置模型及其选项，而不是在代码中设置，请使用 OpenRouter Presets。

错误与成本

这些失败足够常见，值得提前规划应对：

不支持的输入。模型可能会拒绝它不支持的图片格式，也可能拒绝它无法访问的 URL。发送前请检查文件类型和 URL。

图片过大。大文件可能会超时或失败。请先缩小图片，因为大多数编辑并不需要 4000 万像素的源图。

返回文本而非图片。像“这张照片里有什么？”这样的提问可能会让模型用文本作答，而不是生成图片。API 会将其作为 400 错误返回，例如 Gemini could not generate an image (STOP)，而不是空响应。请改写为指令而非提问，并在解码前检查 HTTP 状态码。

当用量数据可用时，响应会以美元报告每个请求的成本。将其记录下来以跟踪支出：

usage = resp.json().get("usage") if usage: print(f"This edit cost ${usage['cost']}")

对于批处理任务，请遵守速率限制。对 429 和 5xx 响应进行重试，并在每次尝试之间逐步延长延迟，同时限制同时运行的编辑数量。在开始下一次编辑之前保存每一张返回的图像，这样即使某次失败也不会丢失已完成的工作。

后续步骤

复制第一个请求，换成你自己的图像，然后运行一次编辑。如果想改为根据文本生成图像，请参阅图像生成文档。要查找当前支持编辑的模型，请浏览图像模型合集。

常见问题

我可以用 Gemini API 编辑图像吗？

可以。通过 OpenRouter API 向 google/gemini-3.1-flash-image 发送一个请求，其中包含源图像和文本指令，编辑后的图像会以 base64 形式在响应中返回。该模型是 Nano Banana 2。整个请求一屏就能放下，你可以用 Python、TypeScript 或 curl 运行它。

图像生成和图像编辑有什么区别？

图像编辑是对已有图像进行修改。图像生成则是根据文本创建新图像。每个编辑请求都包含 input_references 中的源图像，以及一条说明要更改什么、保留什么的指令。如果你的请求没有源图像，仅凭文本提示词生成，那就是生成。

如何向 API 发送图像，用 URL 还是 base64？

input_references 字段接受用于本地或私有文件的 base64 数据 URL，或用于公开托管图像的普通 HTTP(S) URL。当图像已经在线时，使用 URL 形式可以保持请求体积较小；当文件在你的机器上时，使用 base64 形式。Gemini 接受 png、jpeg、webp、heic 和 heif 输入（image/png、image/jpeg、image/webp、image/heic、image/heif）。支持的格式因模型而异，因此发送前请查看模型页面。

我可以使用 Gemini 以外的模型来编辑图像吗？

可以。更改 model 字段，其余请求保持不变。请先查看 图像模型集合，因为编辑支持、价格和速度因模型而异。

如何提示 AI 模型编辑图像？

先描述要更改的内容，然后说明要保留的内容，例如“把背景改成夜晚的雪街。主体保持原样。”每个请求只给一条指令效果最好。为了获得精确结果，请以小步骤进行编辑，并将每次返回的图像作为下一个提示词的源图像发回。

参考文献

OpenRouter API keys：创建并管理每次请求中使用的密钥。

图像模型集合：具备编辑能力的完整模型集及其输入支持。

图像生成文档：从文本创建图像的配套指南。

预设指南：按环境固定模型及其选项，而无需在代码中设置。
