GPT-6 Sol、Claude Opus 5.5 已上线GPT-6 Sol 价格仅为 5.6 Sol 的一半

Nano Banana Pro API:Python 调用、改图和价格

一次 POST、一次轮询、一次下载,脚本复制就能跑。

Kiki, OmniaKey COO9 分钟阅读
本页内容

Nano Banana Pro 就是 Google 的 gemini-3-pro-image。在 OmniaKey 上一次 POST /v1/media/tasks 就能调。我们跑了三张 3:4 的图,像素分别是 896x1200、1792x2400 和 3584x4800。海报上的字一个都没错。

先说结论

  • 模型: gemini-3-pro-image 是 Google 的 GA 模型 ID。Vertex 模型卡写的发布日期是 2026 年 5 月 28 日。
  • 调用: 向 POST https://api.omniakey.com/v1/media/tasks 发请求,带上 Idempotency-Key;轮询 GET /v1/media/tasks/{id} 到 succeeded,再下载 assets[0].url。
  • 参数: parameters.aspect_ratio 和 parameters.image_size,尺寸值写 1K、2K、4K,K 要大写。
  • 请求上限: 整个请求体 1 MiB,内联 Base64 图片也算在里面。
  • Google 价格: 1K/2K 每张 $0.134,4K 每张 $0.24,数字来自 Google Gemini API 价格页。
  • 我们的 token 数: 三次任务分别报了 1,133、1,225、2,480 个输出 token。按每百万图片 token $120 算,是 $0.136、$0.147、$0.298。
  • 改图: 用 operation: "edit",源图放进 input.image,格式是 {data, mime_type}。

OmniaKey 的 Nano Banana Pro 模型页 也接受 gemini-3-pro-image-preview 这个旧快照 ID,价格一样。

模型 ID 和要准备的东西

代码里写 gemini-3-pro-image。Google 的 Vertex 模型卡 把它列为 GA,发布日期 2026 年 5 月 28 日,支持 1K、2K、4K 输出。

gemini-3-pro-image-preview 指向同一个模型。OmniaKey 的 图片模型表 把它标成“Same model, -preview snapshot id”,按次收费的价格一样。

准备两样东西:

  1. OmniaKey API key,放进环境变量:export OMNIAKEY_API_KEY="your-key"。
  2. Python 3。下面的脚本只用标准库:urllib、json、time、uuid、base64 和 pathlib,不用装 SDK。

Python 脚本怎么跑

三步:创建任务、轮询状态、下载图片。保存为 nano_banana.py,运行 python3 nano_banana.py。

python
import base64
import json
import os
import time
import urllib.request
import uuid
from pathlib import Path

API = "https://api.omniakey.com/v1/media/tasks"
HEADERS = {
    "Authorization": f"Bearer {os.environ['OMNIAKEY_API_KEY']}",
    "Content-Type": "application/json",
}


def call(url, payload=None, headers=None, method=None):
    body = json.dumps(payload).encode() if payload is not None else None
    req = urllib.request.Request(url, data=body, headers=headers or HEADERS, method=method)
    with urllib.request.urlopen(req, timeout=60) as resp:
        return resp.status, json.loads(resp.read())


def create_task(prompt, aspect_ratio="3:4", image_size="2K", image_path=None):
    body = {
        "model": "gemini-3-pro-image",
        "type": "image",
        "operation": "generate" if image_path is None else "edit",
        "input": {"prompt": prompt},
        "parameters": {"aspect_ratio": aspect_ratio, "image_size": image_size},
    }
    if image_path:
        encoded = base64.b64encode(Path(image_path).read_bytes()).decode("utf-8")
        body["input"]["image"] = {"data": encoded, "mime_type": "image/png"}
    headers = {**HEADERS, "Idempotency-Key": str(uuid.uuid4())}
    status, task = call(API, body, headers, "POST")
    print("created", task["id"], "HTTP", status)
    return task


def wait(task_id, interval=3, timeout=300):
    deadline = time.time() + timeout
    while time.time() < deadline:
        _, task = call(f"{API}/{task_id}")
        print(task["status"], task["progress"]["percent"])
        if task["status"] in ("succeeded", "failed", "canceled"):
            return task
        time.sleep(interval)
    # A timeout is not a failure: keep the task id and poll it again.
    raise TimeoutError(f"task {task_id} is still running")


def download(task, out_path):
    asset = task["assets"][0]
    with urllib.request.urlopen(asset["url"], timeout=120) as resp:
        Path(out_path).write_bytes(resp.read())
    print("saved", out_path, asset["mime_type"], asset["byte_size"], "bytes")


if __name__ == "__main__":
    task = create_task(
        "A vintage travel poster for the Night Train from Zürich to Milano, "
        "departing 21:40 from platform 7. A steam train crosses a stone arch "
        "bridge below snowy mountains under a deep blue night sky, with a cream "
        "border. Spell every word exactly as written.",
        aspect_ratio="3:4",
        image_size="2K",
    )
    task = wait(task["id"])
    if task["status"] != "succeeded":
        raise SystemExit(f"{task['status']}: {task.get('error')}")
    download(task, "night-train.jpg")

image_size 只认 1K、2K、4K。Google 的图片指南写得很明确:“K 必须大写……小写参数(例如 1k)会被拒绝。”写 2K,别写 2k。

Idempotency-Key 是必填项。最简单的做法是每次请求生成一个新的 UUID;只有重试同一个请求体时才复用同一个 key。OmniaKey 用 HTTP 200 返回原来的任务,不会重复扣费;同一个 key 换了请求体则返回 409。

创建任务返回 202 和一个 id。OmniaKey 的 媒体任务文档 写了完整流程。任务完成后,返回的字段就是下面这些:

json
{
  "id": "task_AbMRVqzSnVh0VwBj0S7NuMUxy5sZtfHP",
  "status": "succeeded",
  "progress": {"percent": 100, "stage": "completed"},
  "usage": {"total_tokens": 1133},
  "assets": [
    {
      "kind": "image",
      "mime_type": "…",
      "url": "https://…signed-url…"
    }
  ]
}

拿到 assets[0].url 就马上下载:签名链接大约一小时过期,任务记录保留 24 小时。格式看 mime_type 字段,Gemini 模型通常返回 JPEG。

同一个脚本换成 1:1、2K,提示词改成中文招牌,得到的是:

砖墙上的深色金属招牌,三行中文和一行电话号码
2K、1:1:2048x2048,47.2 秒。三行中文和 010-6789 4321 全对,锈迹盖住了第一个 0 的下半截。

怎么改一张现有的图

用 operation: "edit",源图放进 input.image,格式是 {data, mime_type}。上面的脚本只要传 image_path 就会走这条路:

python
task = create_task(
    "Hang this poster in a thin black frame on a warm white wall, with a brass "
    "picture light above it, a low wooden cabinet below and a trailing plant on "
    "the right. Keep the poster exactly as it is.",
    aspect_ratio="1:1",
    image_size="2K",
    image_path="night-train-2k.png",
)

实际发出去的请求体是这样:

json
{
  "model": "gemini-3-pro-image",
  "type": "image",
  "operation": "edit",
  "input": {
    "prompt": "Hang this poster in a thin black frame on a warm white wall…",
    "image": {"data": "…base64…", "mime_type": "image/png"}
  },
  "parameters": {"aspect_ratio": "1:1", "image_size": "2K"}
}

示例源图是 PNG,所以脚本标的是 image/png;换成 JPEG 就改这个值。要放多张参考图,用 input.images,每个元素的格式同样是 {data, mime_type}。Google 的指南写最多 14 张参考图;gemini-3-pro-image 的分配是 6 张物体、5 张人物、3 张风格参考。

请求体要压在 1 MiB 以内。Base64 会让文件大约大三分之一,编码前先把源图缩小或压缩。我们这次改图用的是 2K 海报,海报上的每个字和版式都保住了:

夜车海报装进黑色画框挂在墙上,上方有画灯,右侧有植物
2K、1:1 改图:2048x2048,49.9 秒。海报的文字和设计完整保留,画框是规整的矩形。

1K、2K、4K 分别买到什么

同一段 3:4 海报提示词,三个尺寸各跑一次。像素和 Google 的 3:4 表完全对得上:1K 是 896x1200,2K 是 1792x2400,4K 是 3584x4800。三档的字都写对了。

1K 的夜车海报:石拱桥上的蒸汽火车、雪山和深蓝夜空
1K、3:4:896x1200,28.4 秒。海报四行字全对,车灯、车轮和连杆挤在一起。
同一张夜车海报的 2K 版,右侧山坡多了小村庄和两座尖塔
2K、3:4:1792x2400,48.2 秒。文字一样全对,右侧山坡多了小村庄和两座尖塔。
同一张夜车海报的 4K 版,车头后面画出三节车厢和煤水车
4K、3:4:3584x4800,66.9 秒。三节车厢和煤水车都画了出来,砖缝粗细不一。

尺寸变大,多出来的是细节:

  • 1K: 车头挤在一起,车灯、车轮和连杆靠得很近。
  • 2K: 右侧山坡出现小村庄和两座尖塔,烟囱冒出一缕浅色烟,石桥能看到 7 个拱洞。
  • 4K: 三节车厢和煤水车分得开,砖缝粗细不一。车底机械仍然简化。

耗时也跟着涨:28.4 秒、48.2 秒和 66.9 秒。每个尺寸只跑了一次,这三个数就是单次结果。

Google 按每百万图片 token $120 计费,表里 1K 和 2K 都是 1,120 token,4K 是 2,000 token。按它的数算,就是 Google 自己的估算:

text
1,120 × $120 ÷ 1,000,000 = $0.134 per 1K image
1,120 × $120 ÷ 1,000,000 = $0.134 per 2K image
2,000 × $120 ÷ 1,000,000 = $0.24  per 4K image

我们的任务报的 token 比 Google 举的例子多。同样的算法用我们的数:

text
1,133 × $120 ÷ 1,000,000 = $0.136 per 1K image
1,225 × $120 ÷ 1,000,000 = $0.147 per 2K image
2,480 × $120 ÷ 1,000,000 = $0.298 per 4K image
尺寸像素(3:4)我们的耗时我们的 tokenGoogle 估算
1K896x120028.4 秒1,133$0.134
2K1792x240048.2 秒1,225$0.134
4K3584x480066.9 秒2,480$0.24

OmniaKey 按次收费,不看 token 数,所以扣费不随上面的 token 变;当前每次的价格在 模型页,任务失败会退回。充值支持支付宝和微信支付,按人民币直充,一个 key 可以调多家模型。Google 对同样三张图的 token 费率估算是 $0.134、$0.134 和 $0.24。

会碰到哪些报错

这里的失败大多是字段名或文件大小的问题,跟模型本身关系不大。OmniaKey 的媒体文档列了下面这几种:

HTTP错误码或状态什么意思怎么办
400invalid_request请求体格式错、操作不支持或参数不对检查 JSON 和下面的字段名
503no_available_channel当前没有渠道服务这个模型换一个模型;重复调用解决不了
—failed任务结束但没有结果看 error.code 和 error.message

任务 failed 不是 HTTP 错误:创建请求已经成功,所以要轮询任务并读它的 error 对象。失败和取消的任务会自动退款。

原图直接转成 Base64 很容易把请求体推过 1 MiB。先缩图,再看编码后的长度,不要只看文件大小。

Google 的指南会拒绝小写 1k。写 1K、2K 或 4K。

OmniaKey 的图片文档也会拒绝 Gemini 模型上的 size 和顶层的 mime_type。这两个不是 Gemini 的参数。改用 parameters.aspect_ratio 和 parameters.image_size。输出格式从响应的 mime_type 字段读。

常见问题

Nano Banana Pro 的 API 模型 ID 是什么?

gemini-3-pro-image。Google 的 Vertex 模型卡标为 GA,发布日期 2026 年 5 月 28 日,OmniaKey 用同一个 ID。旧的 gemini-3-pro-image-preview 还能用,指向同一个模型。

一张 Nano Banana Pro 图片多少钱?

Google 的估算是 1K/2K 每张 $0.134,4K 每张 $0.24,按每百万图片 token $120 算。我们的任务报了 1,133、1,225、2,480 个 token,按同样费率是 $0.136、$0.147、$0.298。OmniaKey 模型页按次标价。

Nano Banana Pro 能写中文吗?

能。我们那张 2K 招牌回来了三行正确的中文——同福客栈、住宿 餐饮 茶水、010-6789 4321——11 个数字和连字符都对。

1K、2K、4K 选哪个?

像我们这张海报,2K 是比较合适的中间档。三个尺寸都把海报字写对了,4K 多的是细节,比如分开的车厢和砖缝,文字正确率不会更高。只要 896x1200 够用,1K 更省时间。

改图报 400 invalid_request 怎么办?

先看三件事:请求体有没有超过 1 MiB、源图有没有放进 input.image、有没有给 Gemini 模型传 size 或顶层的 mime_type。源图写成 {data, mime_type}。编码后控制在 1 MiB 以内,参数只用 aspect_ratio 和 image_size。

来源

更新记录

  • 2026-11-03:第一版,当天通过 OmniaKey 跑了 5 次测试。

文中提到的模型

Nano Banana ProGemini 图片图片 APIPythonAPI 教程

相关文章

最新文章

热门指南