壁紙アプリ向けに背景画像を数百枚まとめて作ろうとしたとき、最初にぶつかるのは品質ではなく、生成が終わらないことと、月末に届く請求の金額でした。一枚一枚は数秒でも、数百枚を高品質モデルで回すと、時間もコストも想像より膨らみます。今回 Gemini ファミリーに加わった Nano Banana 2 Lite は、この「大量に、速く、安く」という現場の要求にちょうど噛み合うモデルです。最速かつ最も低コストな Gemini 画像モデルとして提供が始まりました。
ただ、安いモデルに全部を寄せればいいという話ではありません。速くて安いモデルには、その速さと引き換えに苦手な領域があります。ここでは、私自身が個人開発で画像を量産するときに使っている、コストを測って使い分けを決めるための型を紹介します。
1枚あたりコストを、推測ではなく式で持つ
大量生成のコスト設計でいちばん危ういのは、「たぶんこれくらい」という感覚で本番を回すことです。まず 1 枚あたりのコストを、次の要素に分解して式で持ちます。生成 1 回のモデル料金、失敗して作り直した分の再生成率、そして採用されずに捨てた分の歩留まりです。
捨てた画像にもコストはかかっています。ここを見落とすと、実効コストが見積もりの倍近くになることがあります。式にするとこうなります。
実効コスト/採用1枚 = モデル1回コスト × (1 + 再生成率) ÷ 採用率
例)モデル1回 = 仮に X 円、再生成率 = 8%、採用率 = 70% のとき
実効コスト = X × 1.08 ÷ 0.70 ≒ X × 1.54
つまり「1枚 X 円」と思っていたものが、
採用ベースでは約1.5倍かかっている、と読む。ここで大事なのは、X の絶対値を私が断定することではありません。モデルの料金は改定されますし、あなたのプロンプトや解像度でも変わります。やるべきは、最初の 50 枚を実際に生成して、再生成率と採用率という二つの実測値を自分の手で取ることです。この二つが分かれば、あとは枚数を掛けるだけで月次のコストが読めるようになります。
実測が効くのは、生成コストだけを見ていると判断を誤りやすいからです。私の壁紙アプリは App Store と Google Play の両方で配信していて、収益は主に AdMob の広告に支えられています。画像一枚あたりの生成コストがいくら安くても、その画像がユーザーに刺さらず継続率が上がらなければ、広告収益では回収できません。だからコストは常に、採用した画像がアプリ内でどれだけ使われたか、という後段の指標とセットで見るようにしています。安いモデルで大量に出せること自体が目的ではなく、採用に足る候補を安く得るための手段だと捉えると、Lite の使いどころが自然に定まります。
安いモデルと品質モデルの二層で受ける
Nano Banana 2 Lite の速さと安さは、大量の「たたき台」を作る工程で最も効きます。一方で、最終的に前面に出す一枚や、細部の破綻が許されない画像は、上位の品質モデルに任せたほうが結局は安くつくことがあります。作り直しが減るからです。
そこで私が採っているのは、Lite で候補を大量に出し、そこから選んだものだけを品質モデルで仕上げる、あるいはそのまま採用する二層構成です。次のコードは、Lite で候補群を生成し、簡単なスコアで足切りしてから、通過したものだけを次工程に渡す骨格です。
import os
from google import genai
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
LITE_MODEL = "nano-banana-2-lite" # 大量の候補生成に使う最速・最安モデル
def generate_candidates(prompt: str, n: int) -> list[bytes]:
"""Lite モデルで候補画像を n 枚生成して返す。"""
images = []
for i in range(n):
resp = client.models.generate_images(
model=LITE_MODEL,
prompt=prompt,
config={"number_of_images": 1},
)
images.append(resp.generated_images[0].image.image_bytes)
return images
def keep_or_drop(image_bytes: bytes) -> bool:
"""採用/不採用の最小判定。まずは解像度とファイルサイズの下限だけで足切り。"""
# 極端に小さい出力(生成崩れの兆候)を弾く一次フィルタ
return len(image_bytes) > 40_000 # 実データを見て閾値を調整する
def run_batch(prompt: str, want: int) -> list[bytes]:
kept, attempts = [], 0
while len(kept) < want and attempts < want * 3: # 無限ループの上限を必ず置く
for img in generate_candidates(prompt, want - len(kept)):
attempts += 1
if keep_or_drop(img):
kept.append(img)
return keptattempts < want * 3 の上限は必ず置きます。プロンプトが難しくて採用率が極端に低いとき、上限がないとバッチが延々と回り続け、時間もコストも青天井になります。上限に達したら止めて、プロンプト側を見直す合図とみなします。
失敗の扱いを、静かなリトライにしない
大量生成では、一時的なエラーや空応答が一定の割合で必ず出ます。ここで安易に無制限リトライを入れると、障害時にリトライが雪崩を打って請求だけが膨らむ事故になります。リトライは回数の上限と待ち時間を持たせ、失敗した入力は捨てずに記録します。
| 失敗の種類 | やりがちな対処 | 推奨する扱い |
|---|---|---|
| 一時的なレート制限 | 即時に無限リトライ | 指数バックオフで最大3回まで |
| 空応答・生成崩れ | 気づかず採用 | 足切りフィルタで弾き、再生成は1回だけ |
| プロンプト起因の低採用率 | 枚数を増やして力技 | バッチを止めてプロンプトを直す |
| 途中中断 | 最初からやり直し | 採用済みを保存し、続きから再開 |
途中中断からの再開は、大量生成では効果が大きい設計です。300 枚のうち 250 枚まで採用できていたのに、残り 50 枚のエラーで全部を捨てて最初からやり直すのは、時間もコストも無駄になります。採用済みを逐次保存しておけば、続きだけを埋められます。
移行と廃止のスケジュールも一緒に見ておく
画像モデルは入れ替わりが速い領域です。実際、一部の画像生成モデルには提供終了の予定が告知されています。いま最安だからと一つのモデル名をコードに直書きしてしまうと、廃止のたびに全体を触ることになります。モデル名は設定値として一箇所にまとめ、切り替えを一行で済ませられるようにしておくと、次の改定や新モデル登場のときに慌てずに済みます。
私の場合は、モデル名と 1 回コストの仮値を小さな設定ファイルに置き、月初にその値と実測の採用率だけを更新する運用にしています。これだけで、生成の本数を変えたときの月次コストが即座に読めるようになりました。
使い分けの起点をどこに置くか
Nano Banana 2 Lite は、大量の候補を速く安く出す工程の主役です。前面に出す一枚や破綻の許されない画像は品質モデルへ、その手前のたたき台は Lite へ、という切り分けを最初に決めておくと、コストと品質のどちらも取りこぼしにくくなります。
次の一歩としては、いま高品質モデルだけで回している生成のうち、最終採用まで見られていない「候補出し」の工程を一つ選び、そこだけを Lite に置き換えて、50 枚で再生成率と採用率を測ってみるのがよいと思います。その二つの数字が手元にあれば、どこまで Lite に寄せてよいかを、感覚ではなく実測で決められます。
実装の役に立てば嬉しいです。最後までお読みいただきありがとうございました。