ブログ記事のサムネイル画像を毎回手作業で作るのが面倒だった。Google AI StudioのGemini APIに画像生成機能があることを知り、自動化のパイプラインを組んでみた。
Gemini APIの画像生成モデル
Geminiの画像生成は、テキスト生成とは別のモデルを使う。通常のgemini-2.5-flashでは画像は生成できない。画像生成に対応したモデル名を明示的に指定する必要がある。
最初、通常のflashモデルに画像生成を依頼して何も返ってこなかった。ドキュメントを読み直して、画像生成用のモデルが別に用意されていることに気づいた。
import google.generativeai as genai
import os
genai.configure(api_key=os.environ['GOOGLE_API_KEY'])
model = genai.GenerativeModel(
'gemini-2.0-flash-exp-image-generation'
)
response = model.generate_content(
"テクノロジーブログのサムネイル画像を生成してください。"
"フラットデザイン、青と白基調、テキストは含めない、"
"ミニマルなイラストスタイル",
generation_config=genai.GenerationConfig(
response_modalities=['IMAGE', 'TEXT']
)
)
response_modalitiesにIMAGEを含めるのがポイントで、これがないと画像が返ってこない。テキストの説明だけが返される。
プロンプト設計のコツ
サムネイル画像のプロンプトは試行錯誤した。いくつか分かったことがある。
「テキストを含めない」と明示しないと、画像内に文字が描画されることがある。AIが描く文字は大抵読めないので、テキストなしを指定するのが無難だった。
色調やスタイルは具体的に指定した方がいい。「かっこいい画像」のような曖昧なプロンプトだと、毎回違うテイストの画像が生成されてブログ全体の統一感がなくなる。「フラットデザイン、青と白基調、ミニマル」のように固定した。
記事のテーマに合わせたモチーフを入れると、サムネイルとしての情報量が上がる。「サーバーのアイコン」「スマートフォンとコードの図」など、具体的なオブジェクトを指定する。
WordPress REST APIで画像を設定する
生成された画像をブログに反映するまでの流れはこうなっている。
# 1. Geminiで画像生成
image_data = response.candidates[0].content.parts[0].inline_data.data
# 2. ファイルに保存
with open('thumbnail.png', 'wb') as f:
f.write(image_data)
# 3. WordPress REST APIでアップロード
with open('thumbnail.png', 'rb') as f:
img_bytes = f.read()
req = urllib.request.Request(
'https://example.com/wp-json/wp/v2/media',
data=img_bytes,
headers={
'Authorization': f'Basic {auth}',
'Content-Type': 'image/png',
'Content-Disposition': 'attachment; filename="thumbnail.png"'
}
)
resp = urllib.request.urlopen(req)
media_id = json.loads(resp.read())['id']
# 4. 記事のアイキャッチに設定
update = json.dumps({'featured_media': media_id}).encode()
urllib.request.urlopen(urllib.request.Request(
f'https://example.com/wp-json/wp/v2/posts/{post_id}',
data=update, method='POST',
headers={'Authorization': f'Basic {auth}',
'Content-Type': 'application/json'}
))
コスト感
Geminiの画像生成は、1回あたりのAPIコストが約0.04ドル程度だった。1日に数枚生成しても月額数ドルで済む。有料のストックフォトサービスを契約するよりずっと安い。
ただし、品質はストックフォトには及ばない。あくまで「それっぽいサムネイル」を自動で量産するための手段として割り切っている。
ハマったところ
画像生成モデルの名前が分かりにくかった。通常のgemini-flashとは別のモデル名を使う必要があり、ドキュメントにも分散して書かれている。APIのエラーメッセージも「モデルが見つかりません」としか出ないため、原因の特定に時間がかかった。
また、レスポンスの構造がテキスト生成の時とは微妙に違う。candidatesの中にテキストと画像が混在する形で返ってくるので、画像データだけを取り出すにはpartsをループしてinline_dataを持つものを探す必要がある。