サムネイルクリエイタースキル(Gemini搭載)
Claude Code内で画像生成エージェントとして機能し、記事やニュースレターのサムネイル候補を生成します。GeminiのWeb UIを行ったり来たりしながら1枚ずつ生成する代わりに、このスキルを使えばClaudeがフルループを実行します。すなわち、コピーを読み込み、構図を提案し、調整済みのプロンプトを作成し、Gemini APIを呼び出し、出力を評価し、ランク付けされた結果と短い根拠を返します。
出力はプロダクション対応のサムネイル候補で、そのままCMS、ニュースレターツール、ソーシャルスケジューラにドロップできます。
前提条件
このスキルが画像を生成するには、以下の両方が整っている必要があります。
1. Gemini APIキー
Google AI Studioから無料のキーを取得してください。
環境変数として設定します:
export GEMINI_API_KEY=<your-key>
セッションをまたいで永続化するには、シェルプロファイル(~/.zshrc または ~/.bashrc)に追加します:
echo 'export GEMINI_API_KEY=<your-key>' >> ~/.zshrc
source ~/.zshrc
設定を確認します:
echo $GEMINI_API_KEY
2. generate_image.py スクリプト
このスクリプトは、プロジェクトルートの ./generate_image.py に存在する必要があります。完全なテンプレートは以下の「スクリプトテンプレート」セクションに記載されています。Claudeはその存在を確認し、不足している場合は作成するよう提案します。
Pythonの依存関係:
pip install google-generativeai Pillow requests
またはuvを使用:
uv pip install google-generativeai Pillow requests
必要な入力
入力がない場合、Claudeがこれらを尋ねます:
| 入力 | 必須 | 備考 |
|---|---|---|
| 記事のコピーまたはURL | はい | 記事の全文を貼り付けるか、URLを提供します。構図のテーマ、フック、主要な主張を抽出するために使用されます。 |
| ブランドカラー | 推奨 | 16進カラーコードまたは説明的な名前。例:#1A1A2E(ネイビー)、#E94560(コーラル)。提供されない場合、Claudeはクリーンなニュートラルデフォルト色を使用します。 |
| フォント/タイプスタイル | 推奨 | 例:「太字サンセリフ」、「エディトリアルセリフ」、「Neue Haas Grotesk」。プロンプト内でテキストの扱いをガイドするために使用します。 |
| スタイルリファレンスの説明 | 推奨 | 例:「フラットイラスト、ミニマル、Stripeのマーケティングサイトのように」または「フォトリアリスティック、暗い背景、高コントラスト」。スタイル画像のURLも提供可能です。 |
| 出力寸法 | いいえ | デフォルトは1792x1024(ランドスケープ、標準記事サムネイル)。オプション:1024x1024(正方形)、1024x1792(縦長/モバイル)。 |
| 候補数 | いいえ | デフォルトは4。最小1、最大8(APIの制限とコストによる)。 |
| 記事タイトル(H1と異なる場合) | いいえ | 画像プロンプトの主要テキスト要素として使用されます。 |
| 候補選択 | いいえ | 構図提案後、Claudeはどの構図を生成するか尋ねます。「すべて」と答えるか、番号を指定します。 |
出力構造
フェーズ1 — 構図提案(テキスト、API呼び出し前)
Claudeは、ユーザーの承認を得るために3~4つの構図コンセプトを提示します。フォーマット:
「[記事タイトル]」の構図コンセプト
1. 大胆な主張
レイアウト: 全面ベタの暗い背景、中央に大きな白の見出し、
その下にブランドカラーのアクセントデータポイント(例:「3倍高速」)
ムード: 高い権威性、ニュースレター風
最適な用途: LinkedIn、Substackのヘッダー
根拠: この記事の中心的な主張(「XはYより3倍優れている」)は、
データに裏付けられたビジュアルのアンカーとして十分に具体的です — 読者はデータで立ち止まります。
2. 概念的なオブジェクト
レイアウト: 中央にオブジェクトのイラスト(例:時間の無駄に関する記事には壊れた時計)、
上部3分の1にタイトル、ミニマルなテクスチャ背景
ムード: エディトリアル、Medium風
最適な用途: ブログヘッダー、Mediumカバー、メールのプレヘッダー
根拠: アートディレクターに視覚的メタファーの柔軟性を提供;様々なサイズで機能します。
3. コントラスト分割
レイアウト: 左半分がブランドカラー、右半分が白または画像、
タイトルはカラー側、補足テキストは白側
ムード: クリーン、プロフェッショナル、スタートアップブランド風
最適な用途: ニュースレター、LinkedInカルーセルの最初のスライド
根拠: 分割レイアウトはニュースレターのA/Bテストで一貫したパフォーマンスを示しています;
テキストは小さなサイズでも読みやすいです。
4. タイポグラフィのみ
レイアウト: イラストなし、特大タイトル処理、
下部にスモールキャップスの著者名、細い区切り線
ムード: プレミアム、自信に満ちた、エディトリアル
最適な用途: Substack、Ghost、高密度メールリスト
根拠: ブランドが強いタイプアイデンティティを持っている場合に機能します。最も早く制作できます。
どの構図を生成しますか?(番号で答えてください。例:「1, 3」または「すべて」)
フェーズ2 — 生成された画像ファイル
生成後、Claudeはファイルを ./thumbnails/[記事スラッグ]/ に保存します:
thumbnails/
└── title-from-title/
├── candidate_01_bold_claim.png
├── candidate_02_conceptual_object.png
├── candidate_03_contrast_split.png
├── candidate_04_typographic.png
└── evaluation_report.md
フェーズ3 — 評価サマリーテーブル
Claudeは、コンピュータビジョンを介して返された各画像を評価し、以下を作成します:
サムネイル評価 —「[記事タイトル]」
生成日: 2026-05-27 | モデル: Gemini Imagen | 寸法: 1792x1024
| # | 候補 | 構図 | ブランド適合 /10 | テキスト可読性 /10 | 推奨 |
|---|---|---|---|---|---|
| 1 | candidate_01_bold_claim.png | 大胆な主張 | 9 | 8 | ★ トップピック — 強力なデータアンカー、ブランドカラーが正しい、200px幅でタイトルが読める |
| 2 | candidate_02_conceptual_object.png | 概念的なオブジェクト | 7 | 9 | 良い代替案 — 読みやすく、クリーンだが、イラストスタイルがブランドから若干ずれた |
| 3 | candidate_03_contrast_split.png | コントラスト分割 | 8 | 7 | フルサイズではうまく機能する;公開前にサムネイルサイズでテスト — 右側のテキストがきつくなる |
| 4 | candidate_04_typographic.png | タイポグラフィ | 9 | 10 | メールに最強 — ブランドドリフトのリスクがゼロ、完全にテキストベース |
Web推奨: candidate_01_bold_claim.png
メール/モバイル推奨: candidate_04_typographic.png
ソーシャル推奨: candidate_03_contrast_split.png
ファイル保存先: ./thumbnails/title-from-title/
Claudeがこのスキルを実行する方法
ステップ1 — 記事を取り込み、分析する
記事のコピーを、貼り付けられたテキストまたはURLとして受け入れます。
URLが提供された場合、ページを取得し、以下を抽出します:
- H1タイトル
- 最初の3~5段落(フック、中心的な主張、主要ポイント)
- 言及されている注目すべき統計や名前付きフレームワーク
- 著者名(タイポグラフィ構図用)
テキストが貼り付けられた場合、直接読み込みます。以下に焦点を当てます:
- フック: 冒頭の主張や緊張感は何か?
- 中心テーゼ: この記事が主張または教えている唯一のことは何か?
- 重要な詳細: ビジュアルのアンカーとなる可能性のある数字、名前付きフレームワーク、具体的な例
- トーン: これはフォーマル/権威的か、会話的/親しみやすいか、挑発的/挑戦ベースか?
構図を提案する前に、これらの発見事項を内部的に要約します — 提案は、この特定の記事に合わせたものであり、一般的なものであってはなりません。
ステップ2 — ブランド仕様を収集する
ブランド仕様が提供されていない場合は、ユーザーに尋ねます:
ブランドに合ったサムネイルを生成するには、いくつかの詳細が必要です:
1. ブランドカラー(16進コードまたは説明) — 例:#1A1A2E, #E94560
2. フォントスタイルの好み — 例:「太字サンセリフ」、「エディトリアルセリフ」、「幾何学的」
3. ビジュアルスタイル — 例:「フラットミニマル」、「フォトリアリスティック」、「イラスト」、「タイポグラフィのみ」
4. スタイルリファレンス — 美学を合わせたいブランドや出版物を説明するか、画像URLを共有してください
まだブランド仕様がない場合は、「クリーンデフォルトを使用」と言ってください。プロフェッショナルな、暗い背景に白い文字のエディトリアルスタイルを使用します。
ユーザーが「クリーンデフォルトを使用」と言った場合、以下を適用します:
- 背景:
#FFFFFFまたは#0F0F0F(ダークモードデフォルト) - アクセント:
#2563EB(青) - フォントスタイル: 太字幾何学サンセリフ
- スタイル: ミニマルフラット、テクスチャなし、高コントラスト
ステップ3 — 構図コンセプトを提案する
記事のトーンと内容に合わせた3~4の構図コンセプトを書きます。各コンセプトは以下を含みます:
- 名前(短く、記憶に残るラベル)
- レイアウトの正確な説明(タイトルの位置、ビジュアル要素のアンカー、背景処理)
- ムードと最適なユースケース
- この構図がこの特定の記事に適合する理由を説明する根拠の文
コンセプトを提示した後、どの構図を生成するか尋ねます。API呼び出しを行う前に、ユーザーの確認を待ちます。
ステップ4 — Gemini画像生成プロンプトを作成する
選択された各構図について、詳細な画像生成プロンプトを作成します。画像生成プロンプトはテキストプロンプトとは異なる文法に従います — 指示的ではなく、説明的です。
プロンプト構造:
[主題/構図] + [スタイル] + [カラーパレット] + [ムード/照明] +
[テキスト処理(ある場合)] + [避けるべきこと]
大胆な主張の構図のプロンプト例:
記事のサムネイル画像。濃いネイビーブルーの背景(#1A1A2E)の中央に、「従来の方法より3倍高速」と読める大きな白の太字サンセリフの見出しテキスト。その下に、サブタイトルとして小さなコーラルカラーのアクセントテキスト(#E94560)。ミニマルなフラットデザイン、グラデーションなし、ストックフォト要素なし、人物なし。クリーンなプロフェッショナルエディトリアルスタイル、高コントラスト、ニュースレターヘッダーフォーマット、16:9の横向き。構図はタイポグラフィベース — テキストが主役であり、イラストは不要。避けること:クリップアート、ドロップシャドウ、低コントラスト、混雑したレイアウト。
プロンプトルール:
- ブランドカラーが提供された場合は、正確な16進カラーを含める
- 画像に表示する正確な見出しテキストを指定する
- スタイルを明示的に指定する(「フラットデザイン」、「エディトリアル」、「フォトリアリスティック」 — Geminiはスタイルカテゴリ名によく反応します)
- 最後にネガティブプロンプト(「避けること:...」)を追加して、ブランドスタイルからの逸脱を減らす
- プロンプトは300語未満に保つ — プロンプトが長くても、必ずしも良い出力が得られるわけではない
ステップ5 — 前提条件を確認し、生成スクリプトを実行する
APIを呼び出す前に、以下を確認します:
# APIキーが設定されていることを確認
echo $GEMINI_API_KEY
# スクリプトが存在することを確認
ls -la ./generate_image.py
# 依存関係を確認
python3 -c "import google.generativeai, PIL, requests; print('依存関係 OK')"
スクリプトがない場合は、以下の「スクリプトテンプレート」セクションのテンプレートを使用して作成することを提案します。
各プロンプトに対して生成スクリプトを実行します:
python3 generate_image.py \
--prompt "完全なプロンプト" \
--output "./thumbnails/article-slug/candidate_01_bold_claim.png" \
--width 1792 \
--height 1024
または、すべてのプロンプトをバッチ設定ファイルで渡します:
python3 generate_image.py --config ./thumbnails/article-slug/prompts.json
ステップ6 — 生成された画像を評価する
各画像が保存された後、コンピュータビジョンを使用して評価します。2つの軸で評価します:
ブランド適合(スコア/10):
- ブランドカラーは正しいか?(各1~2点)
- スタイルはリクエストされた美学と一致しているか?(2点)
- レイアウトは構図の概要と一致しているか?(2点)
- AIアーティファクト、歪んだテキスト、意図しない要素はないか?(問題ごとに-1点)
テキスト可読性(スコア/10):
- 見出しテキストはフル解像度で読めるか?(3点)
- 画像が300px幅(サムネイルサイズ)に縮小されたときに、見出しテキストは読めるか?(3点)
- テキストと背景の間に十分なコントラストがあるか?(2点)
- テキストの配置は安全ゾーン内か(端で切れていないか)?(2点)
注意:Gemini Imagenは時々、テキストをスペルミスや歪んだ文字でレンダリングすることがあります。このような場合は、評価にその旨を記載し、ユーザーにCanvaやFigmaでテキストオーバーレイを手動で追加するよう提案します。
ステップ7 — 評価レポートを作成する
評価サマリーテーブル(「出力構造」セクションに示されているフォーマット)を作成し、evaluation_report.mdとして出力フォルダに保存します。
含めるもの:
- 各スコアの1行の根拠
- ユースケース(Web、メール/モバイル、ソーシャル)ごとのトップピックの推奨
- 制作上の注意(例:「candidate_02のテキストレンダリングが不完全 — テキストオーバーレイを手動で行う」)
- 使用した完全なプロンプト(ユーザーが必要に応じてAI Studioで直接反復できるように)
ステップ8 — 反復を提案する
候補を提供した後、1回の反復パスを提案します:
これらを反復処理しますか?
オプション:
- 特定の候補の色やスタイルを調整
- 別の構図コンセプトを試す
- 見出しテキストを変更
- 異なるGeminiパラメータで再実行(異なる温度/シード)
- トップピックの追加バリエーションを生成
変更内容を教えてください。
スクリプトテンプレート
generate_image.pyが存在しない場合、Claudeはこのファイルを作成することを提案する必要があります。これが使用する正規テンプレートです。
#!/usr/bin/env python3
"""
generate_image.py — サムネイルクリエイタースキル用のGemini Imagenラッパー。
使用方法:
python3 generate_image.py --prompt "..." --output "./out.png" [--width 1792] [--height 1024]
python3 generate_image.py --config ./prompts.json
設定JSONフォーマット:
[
{
"prompt": "...",
"output": "./thumbnails/slug/candidate_01.png",
"width": 1792,
"height": 1024
}
]
必要条件:
pip install google-generativeai Pillow
"""
import os
import sys
import json
import argparse
import base64
from pathlib import Path
try:
import google.generativeai as genai
from google.generativeai import types as genai_types
except ImportError:
print("エラー: google-generativeaiがインストールされていません。実行: pip install google-generativeai")
sys.exit(1)
try:
from PIL import Image
import io
except ImportError:
print("エラー: Pillowがインストールされていません。実行: pip install Pillow")
sys.exit(1)
def get_api_key() -> str:
"""環境変数からGemini APIキーを取得します。"""
key = os.environ.get("GEMINI_API_KEY", "")
if not key:
print("エラー: GEMINI_API_KEY環境変数が設定されていません。")
print("キーを取得: https://aistudio.google.com/app/apikey")
print("次に実行: export GEMINI_API_KEY=<your-key>")
sys.exit(1)
return key
def generate_image(
prompt: str,
output_path: str,
width: int = 1792,
height: int = 1024,
) -> bool:
"""
Gemini Imagenを呼び出して単一の画像を生成し、output_pathに保存します。
成功した場合はTrueを返し、失敗した場合はFalseを返します。
"""
try:
genai.configure(api_key=get_api_key())
model = genai.GenerativeModel("gemini-2.0-flash-exp-image-generation")
response = model.generate_content(
prompt,
generation_config=genai_types.GenerationConfig(
temperature=1.0,
top_p=0.95,
candidate_count=1,
),
safety_settings=[
{"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_MEDIUM_AND_ABOVE"},
{"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_MEDIUM_AND_ABOVE"},
{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_MEDIUM_AND_ABOVE"},
{"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_MEDIUM_AND_ABOVE"},
],
)
# レスポンスから画像データを抽出
if not response.candidates:
print(f"警告: プロンプト「{prompt[:50]}...」に対して候補が返されませんでした")
print(f"応答テキスト: {response.text if hasattr(response, 'text') else 'N/A'}")
return False
for candidate in response.candidates:
if candidate.content.parts:
for part in candidate.content.parts:
if hasattr(part, "inline_data") and part.inline_data:
image_data = part.inline_data.data
image = Image.open(io.BytesIO(image_data))
# 必要に応じてリサイズ
if image.size != (width, height):
image = image.resize((width, height), Image.LANCZOS)
os.makedirs(os.path.dirname(output_path), exist_ok=True)
image.save(output_path, "PNG")
print(f"画像を保存: {output_path} ({image.size[0]}x{image.size[1]})")
return True
print(f"警告: プロンプト「{prompt[:50]}...」の応答に画像データが見つかりませんでした")
return False
except Exception as e:
print(f"エラー: プロンプト「{prompt[:50]}...」の画像生成中にエラー: {e}")
return False
def generate_batch(config_path: str) -> int:
"""
設定ファイルから画像のバッチを生成します。
成功した生成の数を返します。
"""
with open(config_path, "r") as f:
configs = json.load(f)
print(f"\n{len(configs)}個の画像の生成を開始...")
successful = 0
for i, cfg in enumerate(configs):
print(f"\n[{i+1}/{len(configs)}] {cfg['output']}")
success = generate_image(
prompt=cfg["prompt"],
output_path=cfg["output"],
width=cfg.get("width", 1792),
height=cfg.get("height", 1024),
)
if success:
successful += 1
print(f"\n完了: {successful}/{len(configs)}個の画像が正常に生成されました")
return successful
def main():
parser = argparse.ArgumentParser(description="Gemini Imagenを使用してサムネイル画像を生成")
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("--prompt", type=str, help="画像を説明するテキストプロンプト")
group.add_argument("--config", type=str, help="プロンプト設定のJSONファイルへのパス")
parser.add_argument("--output", type=str, help="出力画像ファイルへのパス(--promptと一緒に使用)")
parser.add_argument("--width", type=int, default=1792, help="画像の幅(ピクセル)")
parser.add_argument("--height", type=int, default=1024, help="画像の高さ(ピクセル)")
args = parser.parse_args()
if args.config:
generate_batch(args.config)
elif args.prompt:
if not args.output:
print("エラー: --promptを使用する場合は--outputが必要です")
sys.exit(1)
generate_image(args.prompt, args.output, args.width, args.height)
if __name__ == "__main__":
main()
注意: このスキルは、画像生成にGemini Imagen APIを使用します。2025年現在、Imagenは無料枠(1分あたり1画像など)を提供していますが、詳細はGoogle AI Studioの料金ページで最新情報を確認してください。 このスキルはClaude Code用に設計されていますが、画像生成パイプライン(フェーズ4~6)は、このREADMEをガイドとして使用すれば、任意のターミナルベースのAIエージェントに適応できます。