サイト制作で使う素材画像を、ストックフォトの購入からGemini APIでの内製に切り替えました。3枚生成して数十円です。ただし最初の1枚が出るまでに、思わぬところで止まりました。画像生成モデルには無料枠が一切ありません。テキスト生成の無料枠を使ったことがあると、同じ感覚で叩いて429を返され続けます。
実際に導入して詰まった箇所と、そこで決めた運用の型をそのまま書きます。金額・解像度・補正のパラメータまで具体的に載せます。

きっかけ:欲しいカットが無料素材に存在しなかった
医療系サイトのトップに、屋外で運動している人物のカットを使いたい場面がありました。無料の素材サイトをひととおり探しましたが、条件に合うものが見つかりません。
そして見つかったカットにも問題がありました。スポーツウェアにロゴやエンブレム、スポンサーマーク、背番号が写り込んでいるものが多いのです。実在するチームやブランドが判別できる素材は、医療機関のサイトには使いにくい。ここが決め手になりました。
生成なら「ロゴの一切ない無地のウェア」と指定できます。ストックフォトを1枚買う金額で何案も試せますし、気に入らなければ作り直せばいい。固定費がかからず、生成から補正、サイトへの反映までを一続きの作業にできるのも利点でした。
最初に、作業する場所を3つに分けて整理する
- Google AI Studio(準備する場所)。APIキーの発行と、請求先の紐づけをここで行います
- ターミナル(生成する場所)。curlでAPIを叩き、返ってきたbase64を画像ファイルに戻します
- 画像処理(仕上げる場所)。出力サイズがサイトの想定と合わないときに拡大と補正をかけます
用語は3つだけ覚えれば足りる
- アスペクト比:出力する画像の縦横比。16:9や1:1などを指定します
- レスポンスの形式指定:既定では文章が返ってくるので、画像を返すよう明示的に指定します
- base64:画像がテキストとして返ってくる形式。デコードしてファイルに保存します
手順0:使えるモデルを確認する【ターミナル】
この分野はモデルの入れ替わりが速く、記事や書籍のモデル名はすぐ古くなります。まず自分のキーで何が叩けるかを確認してください。
curl -s "https://generativelanguage.googleapis.com/v1beta/models?key=$GEMINI_API_KEY" \
| python3 -c "import json,sys; [print(m['name']) for m in json.load(sys.stdin)['models'] if 'image' in m['name']]"
ここに出てこない名前を指定すると404が返ります。私は最初にモデル名で取り違えて404を踏み、キーや権限の問題だと思い込んで無駄に時間を使いました。404はまずモデル名を疑ってください。
手順1:キーを発行し、請求先を紐づける【AI Studio】
ここが最大の落とし穴です。画像生成モデルには無料枠がありません。公式の料金表でも、画像生成モデルの無料枠の欄は軒並み「利用不可」と書かれています。テキスト生成とは別扱いです。
請求先を紐づけないまま叩くと、次のようなエラーで止まります。
429 RESOURCE_EXHAUSTED
quotaId: "generate_content_free_tier_requests"
quotaValue: "0"
上限に達したのではなく、上限が最初から0という意味です。「使いすぎた」と誤読して待っても、いつまでも通りません。AI Studioのキー管理画面からプロジェクトに請求先を紐づけて、前払いの階層に上げてください。
手順2:1枚生成する【ターミナル】
APIキーは環境変数に置き、コマンドの履歴やスクリプトに直接書かないようにします。
MODEL=gemini-3-pro-image
curl -s "https://generativelanguage.googleapis.com/v1beta/models/${MODEL}:generateContent?key=$GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"contents": [{ "parts": [{ "text": "ここにプロンプト" }] }],
"generationConfig": {
"responseModalities": ["IMAGE"],
"imageConfig": { "aspectRatio": "16:9" }
}
}' \
| python3 -c "
import json,sys,base64
d=json.load(sys.stdin)
for p in d['candidates'][0]['content']['parts']:
if 'inlineData' in p:
open('out.png','wb').write(base64.b64decode(p['inlineData']['data']))
print('saved out.png')
"
画像はcandidates[].content.parts[].inlineData.dataにbase64で入っています。responseModalitiesの指定を忘れると、画像ではなく文章の説明が返ってきます。
なお、この分野は仕様の更新が速く、公式ドキュメントには新しいモデルとリクエストの書き方が追加されています。上記は実際に動いた形ですが、導入時には最新のドキュメントも併せて確認してください。
手順3:プロンプトを型で書く【プロンプト】
思いつきで書くと毎回ぶれます。次の順で組み立てると安定しました。
- 被写体の年代・国籍・顔立ち
- 動作(何をしているところか)
- 「ロゴ・エンブレム・スポンサーマーク・番号の一切ない無地の◯色のウェア」
- 光と背景
- 色調とムード
- レンズと画質
- 構図(被写体を三分割のどこに置くか)
- 末尾に
No text, no watermarks
3番目が重要です。指定しないとロゴらしき模様が入ることがあり、結局ストックフォトと同じ問題に戻ります。無料素材を避けた理由が、そのまま指定すべき項目になっています。
もうひとつ。1案ずつ直すより、構図だけ変えた3案を同時に投げて選ぶほうが速いです。3案出しても数十円なので、選択肢を増やすコストはほぼ無視できます。文章で細かく修正を指示するより、条件を変えて出し直したほうが早く決まります。

この3枚で分かることがもうひとつあります。構図の指定は効きますが、厳密ではありません。Aは「左三分割に置く」と指定しましたが、出てきたのは中央寄りでした。Bの「右に寄せる」は意図どおりです。狙った構図が一発で出る前提で1枚ずつ作り直すより、複数出して選ぶほうが結果的に早い理由がここにあります。
手順4:サイトの幅に合わせる【画像処理】
16:9で生成したところ、出てきたのは1376×768でした。これは標準的な解像度(1K相当)です。より大きなサイズを選べる指定もありますが、既存素材が1800px幅で組まれていたため、拡大して合わせました。
単純に拡大すると眠い絵になります。拡大アルゴリズムにLANCZOSを使い、そのあとアンシャープマスクをかけると実用に耐えます。
from PIL import Image, ImageFilter
im = Image.open('out.png').convert('RGB')
w = 1800
im = im.resize((w, round(im.height * w / im.width)), Image.LANCZOS)
im = im.filter(ImageFilter.UnsharpMask(radius=1.4, percent=55, threshold=3))
im.save('hero.jpg', quality=88, optimize=True, progressive=True)
アンシャープマスクの数値は、強くしすぎると輪郭が不自然になります。radius=1.4 / percent=55 / threshold=3あたりが、拡大による甘さを戻しつつ加工感が出ない範囲でした。

つまずき早見表
| 症状 | 原因 | 対処 |
|---|---|---|
| 429が返り続ける | 画像生成モデルの無料枠は0 | プロジェクトに請求先を紐づける |
| 404が返る | モデル名が違う | modelsで使える名前を確認する |
| 画像ではなく文章が返る | レスポンス形式を指定していない | responseModalitiesに画像を指定する |
| ロゴらしき模様が入る | プロンプトに指定が無い | 「無地のウェア」を明示する |
| 拡大したら眠い絵になる | 拡大のみで補正していない | LANCZOSで拡大しアンシャープマスクをかける |
| 文字が崩れて入る | 画像内テキストは苦手 | 文字は入れさせず、後からHTMLやCSSで重ねる |
費用の実感
案を3枚出して数十円という規模でした。ストックフォトの1枚あたりの単価や、月額のサブスクリプションと比べると、使う枚数が多くない制作会社にとっては大きな差になります。
金額そのものより効いたのは、作り直しをためらわなくなったことです。有料素材を買った後だと「せっかく買ったから」と妥協しがちですが、十円単位なら気に入るまで出し直せます。最新の単価は変動するので、導入前に公式の料金表を確認してください。
正直に書いておくこと
すべての素材を置き換えられるわけではありません。実在の場所、実在の商品、そして依頼主のスタッフや施設そのものを写す必要がある場面では、当然ながら撮影が必要です。生成が向くのは、イメージカットや抽象的な背景など「特定の誰か・どこかである必要がない」素材です。
人物のイメージカットを医療や美容の文脈で使う場合は、施術前後の効果を示すような使い方を避けるなど、表現上の配慮も必要です。生成した画像であっても、掲載の責任は使う側にあります。
また、この分野は変化が速く、記事に書いたモデル名やリクエストの書き方も、いずれ古くなります。実際、私が導入した時点から数日でドキュメントには新しいモデルと新しい指定方法が追加されていました。手順0で書いたモデル一覧の確認は、毎回やる価値があります。
最後に、無料枠が0であることは公式ドキュメントに明記されています。私はそれを読まずに叩き始めて時間を溶かしました。料金表を先に見ていれば避けられた回り道です。
要点
- 画像生成モデルに無料枠は無い。429は「使いすぎ」ではなく「上限が0」の意味
- 404はまずモデル名を疑う。使えるモデルは
modelsで毎回確認する - 「ロゴの無い無地のウェア」と指定できることが、無料素材に対する実質的な優位になる