Nano Banana 2.1とNano Banana 2を同じポスター編集で比較
Nano Banana 2.1と2に同じポスター生成・文字変更・色変更を依頼。6枚の実画像、応答時間、報告トークンと移行時の確認点を比較します。
テスト日:2026年10月13日。 OfoxのGemini APIネイティブルートを使い、Nano Banana 2.1とNano Banana 2に同じ3つのプロンプトを送りました。各モデルにイベントポスターを生成させ、見出しを変更し、続けてボウルの色を変更しました。これはモデルごとに1回の3段階の連続処理であり、独立した3回の試行でも、各モデルの総合的な品質を測るベンチマークでもありません。
この記事はOfoxが公開しており、ここでテストしたゲートウェイもOfoxが運営しています。記事の下書きにはAIを使用しました。APIリクエストと出力ファイルはツールで検証し、公開前に別途AIレビューも実施しています。以下の6枚の生成画像が、視覚的な比較の根拠です。公開されているモデルページの画面表示は、根拠ではありません。ファイルとリクエスト関連資料は再現用キットから確認できます。
6つの出力
| ステップ | Nano Banana 2.1 | Nano Banana 2 |
|---|---|---|
| ポスターを生成 | ![]() | ![]() |
| 見出しを編集 | ![]() | ![]() |
| ボウルの色を編集 | ![]() | ![]() |
この実行では、どちらのモデルも指定した文字と被写体を保ちながら、一連の変更を完了しました。最初のポスターでは、どちらもORCHARD MARKETとSATURDAY 10 AMを正しく表記し、青いボウルに赤いリンゴを3個描いています。見出しの編集後は、どちらも小さい文字の行、リンゴ、青いボウルを残したまま、見出しがORCHARD FAIRになっています。3ターン目の出力では、どちらもボウルを濃い緑色に変更し、指定された文字とレイアウトを保っています。
共通する見落としもあります。最初のプロンプトには「no border」と指定したにもかかわらず、どちらのモデルも外側に余白や影のある紙面としてデザインを表現しました。「no border」が画像の端まで絵柄を広げるという意味なら、最初の出力はどちらもその条件を満たしていません。ポスターのコンセプトを作る用途には役立つ結果ですが、どちらかのモデルがレイアウトの指示をすべて厳密に守る証拠ではありません。
送信した内容と、この比較から分かること
使用したプロンプトは、次のとおりです。
Create a square minimalist event poster on warm cream paper. Large exact headline: ORCHARD MARKET. Smaller exact line: SATURDAY 10 AM. Draw three red apples in a blue ceramic bowl below the text. No other text, no logos, no border.Change only the headline from ORCHARD MARKET to ORCHARD FAIR. Keep SATURDAY 10 AM exactly unchanged. Preserve the three red apples, blue bowl, cream background, composition and all other pixels as closely as possible.Now change only the bowl from blue to dark green. Preserve ORCHARD FAIR, SATURDAY 10 AM, the three red apples and the layout.
各モデルとも、2ターン目にはそのモデルが生成したポスターを含めました。3ターン目には、そのモデルとの直前までの会話と見出し編集を含めています。表示用PNGから内容を組み立て直すのではなく、直前の candidates[0].content 全体をモデルのターン(role: "model")として送り返しました。返却されたコンテンツには、会話を続けるために必要なパーツが含まれている場合があるためです。
テストしたOfoxのルートは POST https://api.ofox.io/gemini/v1beta/models/{model}:generateContent で、認証には x-goog-api-key を使用しました。モデルIDは、2.1が google/gemini-nano-banana-2.1、旧モデルが google/gemini-3.1-flash-image です。どちらの連続処理でも、responseModalities: ["TEXT", "IMAGE"]、アスペクト比 1:1、画像サイズ 1K を指定しました。seedも、明示的な推論レベルも設定していません。そのため、モデルごとに異なるデフォルト設定が使われた可能性があります。同じプロンプトと画像設定を指定しても、内部設定まで一致するわけではありません。
6件すべての呼び出しで、HTTP 200、終了理由 STOP、1024 × 1024のPNGが返されました。反復試験、他言語、他のアスペクト比、本番環境の負荷を使ったテストは行っていません。上記の視覚評価は、この6ファイルだけを対象としています。特に「ほかのピクセルをできるだけ維持する」は指示であって、ピクセル単位の編集や編集可能なレイヤーを保証するものではありません。見出し編集後、変化がないように見える下部にも、多数のRGBピクセルの差があります。ピクセルの完全一致を基準にすると、細かな質感や色の違いも変更として数えられますが、それは視覚的な損傷の評価値ではありません。製品の特定領域をより厳密に制御する手法については、マスクを使った保持方法とシーン参照を1枚使う場合と複数使う場合の別記事を参照してください。
処理時間と返却された使用量:観測結果であり、速度の順位ではない
以下は、6件のリクエストで実測した経過時間と、返却された使用量フィールドです。「未報告」はフィールドが存在しなかったことを意味し、推論トークンがゼロだったことや、それに関連する費用がなかったことを意味しません。
| モデルとターン | 経過時間(秒) | 入力トークン | 報告されたテキスト出力トークン | 画像出力トークン | 推論トークン |
|---|---|---|---|---|---|
| 2.1 — ポスター | 15.46 | 54 | 80 | 1,120 | 639 |
| 2.1 — 見出し編集 | 17.48 | 1,167 | 未報告 | 1,120 | 358 |
| 2.1 — ボウル編集 | 18.44 | 2,272 | 未報告 | 1,120 | 未報告 |
| 2 — ポスター | 10.08 | 54 | 未報告 | 1,120 | 未報告 |
| 2 — 見出し編集 | 13.99 | 1,167 | 未報告 | 1,120 | 未報告 |
| 2 — ボウル編集 | 13.06 | 2,272 | 未報告 | 1,120 | 未報告 |
最初の2.1の応答では、TEXT出力トークンが80と報告されましたが、目に見えるテキストパートは含まれていませんでした。この表が示しているのはメタデータ上の分類であり、目に見える単語数ではありません。
今回の3組の比較では、Nano Banana 2のほうが毎回早く返答しました。ただし、制御された負荷条件も反復試験もない、逐次実行の6リクエストだけでは、一般にこちらのほうが速いとは結論できません。同様に、今回の主なテキストと編集タスクを両方が完了したからといって、さまざまなプロンプトで信頼性が同等だとは言えません。入力トークン数の増加は、APIから報告された複数ターンのリクエストを反映しています。それだけでは、送信した会話履歴がどのように課金されたかを正確に特定できません。以下の移行手順では、今回の限定的な観測結果を、自分のワークロードで確認するためのチェック項目に落とし込みます。
3段階の連続処理を再現する
キットには、テスト素材と出力画像が含まれています。新たにリクエストを送るには、requestsをインストールし、Ofox APIキーを設定して、以下のスクリプトを実行してください。スクリプトは上記と同じプロンプトを使い、返されたインライン画像パートをすべて保存します。また、次のターンに渡せるよう、各レスポンスの候補コンテンツ全体を保持します。新しく生成した画像は、公開した6枚のPNGと一致するとは限りません。
python -m pip install requests
export OFOX_API_KEY="your-key"
python compare_posters.py
# compare_posters.py
import base64
import json
import os
import time
from pathlib import Path
import requests
KEY = os.environ["OFOX_API_KEY"]
OUT = Path("poster-comparison")
OUT.mkdir(exist_ok=True)
PROMPTS = [
"Create a square minimalist event poster on warm cream paper. Large exact headline: ORCHARD MARKET. Smaller exact line: SATURDAY 10 AM. Draw three red apples in a blue ceramic bowl below the text. No other text, no logos, no border.",
"Change only the headline from ORCHARD MARKET to ORCHARD FAIR. Keep SATURDAY 10 AM exactly unchanged. Preserve the three red apples, blue bowl, cream background, composition and all other pixels as closely as possible.",
"Now change only the bowl from blue to dark green. Preserve ORCHARD FAIR, SATURDAY 10 AM, the three red apples and the layout.",
]
MODELS = {
"21": "google/gemini-nano-banana-2.1",
"2": "google/gemini-3.1-flash-image",
}
STAGES = ("poster", "edit", "turn3")
for label, model in MODELS.items():
history = []
url = f"https://api.ofox.io/gemini/v1beta/models/{model}:generateContent"
for stage, prompt in zip(STAGES, PROMPTS):
user_turn = {"role": "user", "parts": [{"text": prompt}]}
payload = {
"contents": history + [user_turn],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {"aspectRatio": "1:1", "imageSize": "1K"},
},
}
started = time.monotonic()
response = requests.post(
url,
headers={"x-goog-api-key": KEY},
json=payload,
timeout=180,
)
elapsed = time.monotonic() - started
response.raise_for_status()
body = response.json()
candidates = body.get("candidates") or []
if not candidates:
raise RuntimeError(f"{label}/{stage}: no candidate: {body}")
candidate = candidates[0]
if candidate.get("finishReason") != "STOP":
raise RuntimeError(
f"{label}/{stage}: finishReason={candidate.get('finishReason')}"
)
content = candidate["content"] # Keep all returned parts intact.
saved = []
for index, part in enumerate(content.get("parts", [])):
inline = part.get("inlineData")
if not inline:
continue
mime = inline.get("mimeType", "")
if not mime.startswith("image/"):
continue
extension = ".png" if mime == "image/png" else ".img"
path = OUT / f"{stage}-{label}-{index}{extension}"
path.write_bytes(base64.b64decode(inline["data"]))
saved.append(str(path))
if not saved:
raise RuntimeError(f"{label}/{stage}: STOP but no inline image")
print(json.dumps({
"model": model, "stage": stage, "seconds": round(elapsed, 2),
"images": saved, "usageMetadata": body.get("usageMetadata"),
}))
history += [user_turn, content]
このコードはテキストパートをテキストとして扱い、画像として扱いません。また、HTTPレスポンスが成功していても、候補がない場合、終了理由が STOP 以外の場合、インライン画像がない場合には、エラーが明示されます。画像生成をワークフローに組み込む前に、こうしたケースへの対応を検討してください。公開されているOfox 2.1モデルページには、モデルとプロトコルが記載されていますが、埋め込みのPlaygroundにはログインが必要です。モデルページのスクリーンショットは公開インターフェースの証拠であり、今回の画像がそこで生成された証拠ではありません。認証済みのAgentモデル選択テストは実施していないため、Agentが自動的に2.1を選択するとは、この記事では主張しません。レスポンス処理での失敗については、画像が返らない場合のエラーガイドとGoogleのAPIトラブルシューティングドキュメントを参照してください。
トークンから分かること、分からないこと
画像トークン、入力トークン、報告されたテキスト出力、報告された推論トークンは、それぞれ別の使用量項目です。10月13日時点のOfoxランタイムカタログのスナップショットでは、2.1の料金は入力100万トークンあたり$1.50、テキスト出力100万トークンあたり$7.50、画像出力100万トークンあたり$30でした。旧モデルの同じ時点のスナップショットでは、対応する料金が$0.50、$3、$60と記載されていました。2.1のスナップショットには、検索リクエスト1件あたり$0.014も記載されていましたが、今回のポスターテストでは検索を使用していません。プロバイダー料金フィールドがnullでも、プロバイダーによる割引が確認されたことにはなりません。Ofoxのカタログエンドポイントは動的で、サイトのGitリポジトリ内に固定された料金表ではありません。また、スナップショットをもとにした計算は、確認済みの請求書ではありません。予算を立てる前に、最新の料金ガイドと請求記録を確認してください。
2.1で最初のポスターを生成したリクエストについて、スナップショットの料金を当てはめると、画像分は 1,120 × $30 / 1,000,000 = $0.0336、入力分は 54 × $1.50 / 1,000,000 = $0.000081、報告されたテキスト出力分は 80 × $7.50 / 1,000,000 = $0.0006 です。報告された推論トークン639個にも同じテキスト出力料金が課金されると仮定した場合、推定で $0.0047925 が加わり、例示上の合計は $0.0390735 になります。この条件付きの計算は請求額ではありません。旧モデルで推論トークンのフィールドがないことを、課金がゼロだったという仮定に置き換えないでください。
スナップショットの画像料金では、2.1で1K画像を100枚生成すると、画像分だけで $3.36 です。採用する画像100枚を得るために125枚生成する場合(採用率80%という例)には、画像分が $4.20 になります。入力、テキスト、課金される可能性のある推論処理、再試行、その他の適用料金は、この画像分だけの金額に含まれません。旧モデルで1,120トークンの画像出力にかかる画像分は $0.0672 ですが、これらの金額から、モデルを切り替えれば特定のワークロード全体の請求額や採用デザイン1件あたりの費用が下がるとは証明できません。
GoogleのGemini料金ページにも、2.1のテキスト出力+思考と画像の料金が掲載されており、1K画像は1,120画像トークンとされています。公開されているGoogleの情報では、4Kの数値は一貫していません。画像生成の料金表では2,520トークンですが、Vertexのドキュメントでは3,780とされています。今回は4Kのリクエストを送っていません。どちらの数値も、このテストにおけるOfoxの4K料金として正確な値だと示すべきではありません。
既存のワークフローでモデルIDを切り替えるべきか
今回の6枚で普遍的な勝者が証明されたからではなく、自分で確認した課題の解決に、このモデルの挙動や利用可能な機能が役立つ場合に切り替えを検討してください。GoogleはNano Banana 2.1のモデル機能と画像生成ワークフローを公開しており、より高解像度の選択肢や参照画像を使うワークフローも説明しています。ただし、機能の説明があることは、Ofox経由でそのすべてを検証したという意味ではありません。今回の比較では1Kを使用し、外部の参照画像は使わず、英語のプロンプトだけを使いました。ProやLiteとの比較も行っていません。それらのモデルについて文書で説明されている位置づけは、異なるニーズに応じて評価する理由にはなりますが、今回のテストで優位性が測定されたわけではありません。
慎重にアップグレードするための手順は4つです。
- モデルIDを固定する。 本番環境の呼び出しを一斉に切り替えるのではなく、テスト設定で
google/gemini-3.1-flash-imageをgoogle/gemini-nano-banana-2.1に変更します。 - 設定と会話履歴を明示して記録する。 指定した解像度、アスペクト比、モダリティ、プロンプト、ターン間で受け渡したモデルのコンテンツ全体を記録します。今回の出力を再現できるかのように、根拠のないseed、temperature、top-pの調整方法を紹介しないでください。
- 実際の成果物に合わせて出力を確認する。 正確な文言、不要な余白、必要に応じた参照画像の扱い、画像が返らない場合の応答、採用率、レイテンシの分布、自分の素材を使った請求対象の使用量全体をテストします。この種の作業に関する制約は、詳しいポスター編集ガイドで説明しています。APIガイドでは連携方法を扱っています。
- 元に戻せるようにする。 新しいモデルが確認項目を満たすまでは、古いIDとルーティング設定を保持します。今回のテストから、旧IDの提供が終了したとは言えません。
最後に、魅力的なポスターが生成されたからといって、権利処理が済んでいることや、安全なデータ利用方針が確保されることにはなりません。商用利用や機密データの利用前に、提供する入力素材の権利と適用されるGemini API利用規約を確認してください。SynthIDのドキュメントは、目に見えるウォーターマーク、独占的な所有権、非侵害を約束するものとして解釈すべきではありません。ここから導ける結論は、より限定的です。つまり、同じ英語プロンプトを使った1回の3ターンのポスター編集では、両モデルとも指定された文字とボウルの編集を行いましたが、どちらも「no border」の指示には従いませんでした。








