mcpField
P
paperbanana-slide-deck

paperbanana-slide-deck

github.com/plutoleiドキュメント5836 回インストール4 週間前に更新
リポジトリ

paperbanana-slide-deck について

PaperBanana のスライドデッキを一貫して作成・変更するスキルで、画像モードと編集可能モードを明示的に選べます。画像モードはスライド全体の画像を生成して PPTX にまとめ、編集可能モードは構造化仕様からテキスト、表、グラフ、図形を作成します。

主な機能

  1. 01画像または編集可能モードの明示的な選択
  2. 02スタイル調査とアウトライン、プロンプトの作成
  3. 03画像生成と途中バッチからの再開
  4. 04スライド画像の PPTX への統合
  5. 05編集可能な PPTX の構築、プレビュー、レビュー

活用シーン

  1. 01テーマと内容から新しいデッキを作成
  2. 02プロンプト編集後に既存デッキを再生成
  3. 03PowerPoint で編集できる要素を含む PPTX の作成
  4. 04プレビューを確認してスライドデザインを反復改善

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/plutolei/paperbanana-skill --skill paperbanana-slide-deck

インストール後、Claude Code で/paperbanana-slide-deckを入力して読み込まれたか確認します。

詳細

PaperBanana スライドデッキ

スライドデッキの作成と変更をエンドツーエンドで行います。デッキのモードは image と editable の2種類があり、フェーズ M で明示的に選択します。image モードには、新しいデッキを一から作成するワークフローと、プロンプトを編集した後に既存のデッキを再生成するワークフローがあります。

画像パイプライン: コンテンツ → スタイル選択 → アウトライン → プロンプト → 画像生成 → PPTX の結合 編集可能パイプライン: コンテンツ → slide-spec.json(ネイティブのテキスト/表/グラフ/図形/線/グループ)→ 検証 → PPTX の構築 → プレビューのレンダリング → Critic によるレビュー → 仕様の修正 → 再構築

フェーズ M:デッキモードの選択

deck-mode.txt に image または editable のいずれかを、行に1つだけ記録します。

  • PowerPoint でテキスト/表/グラフ/コネクタを編集したい、または編集可能な PPTX を明示的に希望している場合は、editable を使用します。
  • 生成したスライド全体のアートワークを希望している場合、または既存の PaperBanana の画像ワークフローを維持する場合は、image を使用します。
  • どちらも適切な可能性がある場合は、生成前に確認してください。ファイルの有無から推測してはいけません。
  • editable には slide-spec.json が必要です。仕様がない、または無効な場合はエラーです。編集可能だと主張しながら、image モードにフォールバックしてはいけません。

モードの判定(image モード)

image モードでは、対象ディレクトリを確認してワークフローを判定します。

条件モード開始フェーズ
対象ディレクトリが存在しない、または outline.md がない新規作成フェーズ R(RDIV 全体)
対象ディレクトリに outline.md と prompts/ がある変更フェーズ I(生成と結合)

変更モードでは、ユーザーがすでに外部でプロンプトまたはアウトラインを編集しています。フェーズ I に直接進みます。

依存関係

コンポーネント役割場所
google-genai SDKパス B の画像生成pip install google-genai
PaperBanana CLIパス A の画像生成python -m paperbanana.cli slide-batch
merge-to-pptx.tsPPTX の結合(image モード)plugins/paperbanana-slide-deck/scripts/merge-to-pptx.ts
build-deck.ts明示的な --mode image|editable ルーターplugins/paperbanana-slide-deck/scripts/build-deck.ts
編集可能レンダラーslide-spec.json → ネイティブ PPTXplugins/paperbanana-slide-deck/scripts/editable/
スタイルライブラリスタイルプリセット(4つのソース、150以上)検出パスは R1 を参照
Bunビルド/結合スクリプトの実行bun

編集可能モードのワークフロー

deck-mode.txt が editable の場合は、以下のループに従い、フェーズ R/D/I はスキップします(仕様の詳細と完全な例については、references/editable-slide-spec.md を参照してください)。

  1. テキストを含まないアセットのみを生成します(写真、イラストパネルなど。レンダリング済みテキストは含めません)。PaperBanana を使用し、各アセットの SHA-256 を記録します。
  2. slide-deck/{topic-slug}/slide-spec.json を作成します。13.333×7.5 インチのキャンバスにネイティブの text、shape、line、table、chart、image、group 要素を配置し、各スライドのスピーカーノートに [Sources] を含めます。
  3. 検証してビルドします(フェイルクローズ方式。仕様がない、または無効な場合はエラーとし、image モードへ暗黙にフォールバックしません)。
bun "${SKILL_DIR}/scripts/build-deck.ts" --mode editable "slide-deck/{topic-slug}"
  1. LibreOffice と Poppler を使って PPTX のプレビューをレンダリングします(soffice --headless --convert-to pdf を実行し、続けて pdftoppm -png -r 150 … slide を実行して slide-NN.png を生成します)。
  2. プレビューに対して Critic を実行します(プレビューのみを対象とし、PPTX は編集しません)。
python3 "${SKILL_DIR}/scripts/editable/review-editable.py" \
  --spec "slide-deck/{topic-slug}/slide-spec.json" \
  --rendered-dir "slide-deck/{topic-slug}/rendered" \
  --output "slide-deck/{topic-slug}/critic-review.json"
  1. 検出結果を要素 ID に対応付けます(提案は slide-id/element-id: … の形式で返されます)。slide-spec.json を修正して再ビルドします。問題がなくなるまで繰り返します。

Phase R:リサーチ(新規モードのみ)

Modify モードではこのフェーズを完全にスキップします。

R1:スタイルライブラリを見つける — 4 つのソースすべてをスキャンし、統合リストにまとめます。

# Source 0 (PRIMARY): Local extended library (123 styles from Fooocus/ComfyUI, structured)
LOCAL_STYLES="$(find ~/.claude/skills .claude/skills -maxdepth 1 -name 'paperbanana-slide-deck' -type d 2>/dev/null | head -1)/references/styles"

# Source 1: baoyu-slide-deck styles (16 slide-optimized)
BAOYU_SLIDE=$(ls -td ~/.claude/plugins/cache/baoyu-skills/content-skills/*/skills/baoyu-slide-deck/references/styles 2>/dev/null | head -1)

# Source 2: baoyu-infographic styles (20 visual-rich)
BAOYU_INFOG=$(ls -td ~/.claude/plugins/cache/baoyu-skills/content-skills/*/skills/baoyu-infographic/references/styles 2>/dev/null | head -1)

# Source 3: theme-factory themes (10 color/typography presets)
THEME_FACTORY=$(ls -td ~/.claude/plugins/cache/anthropic-agent-skills/document-skills/*/skills/theme-factory/themes 2>/dev/null | head -1)

統合:4 つのディレクトリすべてで *.md を Glob し、ファイル名で重複を除外します(優先順位:baoyu-slide-deck > local > baoyu-infographic > theme-factory)。R3 で統合リスト全体をユーザーに提示します。

見つからない場合:PaperBanana の組み込みプリセット 23 種を使用します。

R2:コンテンツを分析する — トピック、対象読者、トーン、推奨スライド枚数。

R3:スタイルを提案する — コンテンツの特徴に基づいて 2~3 種のスタイルを提案します。スタイルとコンテンツの対応表全体は references/style-guide.md を参照してください。

R4:対話形式で選択する — AskUserQuestion を使用して、スタイル、対象読者、スライド枚数を確認します。

R5:分析結果を保存する — slide-deck/{topic-slug}/analysis.md を作成します。

Phase D:デザイン(新規モードのみ)

Modify モードでは、ユーザーがプロンプトを直接編集します。

D1:スタイル仕様を読み込む — baoyu のスタイル、または PaperBanana の組み込みスタイルから読み込みます。

D2:アウトラインを生成する — スライド構成を記載した outline.md を作成します。references/outline-format.md を参照してください。

D3:任意のアウトラインレビュー — 続行前にレビューするかどうかをユーザーに確認します。

D4:プロンプトを生成する — 各スライドについて、prompts/NN-slide-{slug}.md を作成します。各プロンプトファイルには、スタイル指示ブロック、続いて ---、その後にスライド固有の内容とデザイン要件を記述します。

Phase I:実装(両モード)

Step I1:画像生成(2 つの経路)

Path A — PaperBanana CLI(推奨、critic による品質レビューあり):

cd <project_root>
python -m paperbanana.cli slide-batch \
  --prompts-dir "slide-deck/{topic-slug}/prompts" \
  --output-dir "slide-deck/{topic-slug}" \
  --resolution 4k \
  --iterations 2

自動切り替えの条件: いずれかのスライド(最初のスライドだけではありません)で以下のいずれかが発生した場合、Path B に切り替えます。Path A の再試行を続けないでください。

  • RetryError / ResourceExhausted / HTTP 429(レート制限)
  • ServerError(5xx)または 429 以外の ClientError(4xx)
  • いずれか 1 枚のスライドで Critic の処理に 3 分以上かかる
  • ユーザーから「一直 429」/レート制限が続いているとの報告があった場合 → 直ちに切り替え、Path A の再試行をスキップします

2 種類の 429 の発生元を見分ける:

発生元症状対応
Critic 429(VLM のレート制限)Critic のループ内でエラーが発生。Path A 固有Path B に自動切り替え(Critic を使わないため、問題を回避できます)
画像生成 429(gemini-3-pro-image-preview)Path B でも同じエラーが発生指数バックオフ:time.sleep(30 * 2**retry) を最大 5 分まで行い、その後ユーザーに通知します

一部バッチの復旧: 429 が発生する前に生成済みのスライドがある場合は、既存の PNG を保持し、次に不足しているスライドから再開します(prompts/*.md と既存の NN-slide-*.png を照合します)。

注(上流との同期待ち): 上流の paperbanana CLI(≥ #129)では、Path A の slide-batch にネイティブな batch_checkpoint.json があり、再開は自動で行われます。上記のスキップ処理は、上流のチェックポイント形式をまだ使用していない Path B のフォールバックコード向けです。

Path B — Gemini API を直接使用(フォールバック、Critic なし、安定):

from google import genai
from google.genai import types
from PIL import Image
from io import BytesIO
import base64, os, time

# Read API key from paperbanana/.env
client = genai.Client(api_key=GOOGLE_API_KEY)

config = types.GenerateContentConfig(
    response_modalities=['IMAGE'],
    image_config=types.ImageConfig(
        aspect_ratio='16:9',
        image_size='4K',
    ),
)

MAX_RETRIES = 5   # after which surface to user
BASE_SLEEP = 30   # seconds

for prompt_file in sorted(os.listdir(prompts_dir)):
    name = prompt_file.replace('.md', '')
    out_path = os.path.join(output_dir, f'{name}.png')

    # Partial-batch resume: skip slides already generated
    if os.path.exists(out_path):
        continue

    with open(os.path.join(prompts_dir, prompt_file), 'r', encoding='utf-8') as f:
        prompt_text = f.read()

    # Exponential backoff on 429 / transient errors
    for retry in range(MAX_RETRIES):
        try:
            response = client.models.generate_content(
                model='gemini-3-pro-image-preview',
                contents=prompt_text,
                config=config,
            )
            break
        except Exception as e:
            msg = str(e).lower()
            if '429' in msg or 'resource' in msg or 'rate' in msg:
                wait = min(BASE_SLEEP * (2 ** retry), 300)  # cap at 5 min
                time.sleep(wait)
                continue
            raise  # non-429 error → surface immediately
    else:
        raise RuntimeError(f'{name}: 429 after {MAX_RETRIES} retries, surface to user')

    for part in response.candidates[0].content.parts:
        inline = getattr(part, 'inline_data', None)
        if inline and getattr(inline, 'data', None):
            data = inline.data
            img_bytes = base64.b64decode(data) if isinstance(data, str) else data
            img = Image.open(BytesIO(img_bytes))
            img.save(out_path, 'PNG')
            break

    time.sleep(BASE_SLEEP)  # baseline cooldown between slides

API キーは <project_root>/paperbanana/.env に GOOGLE_API_KEY として保存されています。dotenv を使用するか、手動で読み取ってください。

Step I2:スマートクリーンアップ(マージ前)

I1 の生成後に実行し、前には実行しないでください。 I1 は一部バッチの再開に対応しており、生成済みのスライドをスキップします。クリーンアップの役割は、前回の実行後にプロンプトが削除または名前変更された PNG のみを削除することです。I1 の前にクリーンアップを実行すると、再開するバッチの有効な WIP スライドが削除されます。

実行順序:I1 (generate + resume) → I2 (cleanup orphans) → I3 (merge)。

  1. prompts/*.md をスキャン → 期待される PNG のセットを作成します(例:01-slide-hook.md → 01-slide-hook.png)
  2. 対象ディレクトリをスキャンし、パターン NN-slide-*.png に一致する *.png ファイルを探します
  3. 期待されるセットに含まれないスライド PNG を削除します(名前変更または削除されたプロンプトに由来する孤立ファイル)
  4. スライド以外の PNG(例:logo.png、background.png)と、期待されるセット内のすべての PNG は保持します
Step I3:PPTX にマージする
# Locate skill directory dynamically (works on any platform)
SKILL_DIR="$(find ~/.claude/skills .claude/skills -maxdepth 1 -name 'paperbanana-slide-deck' -type d 2>/dev/null | head -1)"
bun "${SKILL_DIR}/scripts/merge-to-pptx.ts" "slide-deck/{topic-slug}"

マージスクリプトを利用できない場合:PNG 画像は用意できていますが、PPTX へのマージには bun とローカルの merge-to-pptx.ts スクリプトが必要であることをユーザーに伝えます。

フェーズ V:検証(両方のモード)

V1:結果の表示 — 生成された各スライド画像を読み込み、表示します。スライドの合計数、出力ディレクトリ、PPTX ファイルのパスを報告します。

V2:ユーザーからのフィードバック — 次のいずれかを尋ねます。

  • 「いい感じです。完了です!」
  • 「再生成してください。プロンプトで修正する内容を伝えます」

V3:再生成 — ユーザーが変更を希望する場合:

  1. ユーザーが該当するプロンプトファイルを編集します
  2. 変更したものだけでなく、すべてのスライドを再生成します(ビジュアルの一貫性を保つため)
  3. スマートクリーンアップを実行し、PPTX を再結合します
  4. V1 に戻ります

フォールバックの動作

状況フォールバック
スタイルライブラリがすべて見つからないPaperBanana の組み込みプリセットを使用
ローカルの結合スクリプトが見つからないPNG のみを出力し、PPTX はスキップ
Bun/npx が見つからないPPTX の結合をスキップし、ユーザーに知らせる
Critic 429 / RetryError自動的に Path B(critic なし)に切り替える
Path B で画像生成が 429 になった場合最大 5 分まで指数バックオフし、その後ユーザーに知らせる
バッチの一部がすでに生成されている次に不足しているスライドから再開し、既存の PNG を保持する

出力構造

slide-deck/{topic-slug}/
  analysis.md            ← R phase (New mode only)
  outline.md             ← D phase
  prompts/               ← D phase
    01-slide-hook.md
    02-slide-cover.md
    ...
  01-slide-hook.png      ← I phase
  02-slide-cover.png
  ...
  {topic-slug}.pptx      ← I phase

クイックリファレンス

# Path A: PaperBanana CLI batch
python -m paperbanana.cli slide-batch --prompts-dir prompts/ --resolution 4k --iterations 2

# Path A: single slide (supports --vlm-model)
python -m paperbanana.cli slide --input prompt.md --resolution 4k

# List available styles
python -m paperbanana.cli slide --list-styles

コメント