本文へ移動
cccskills
無料GitHub で公開日本語紹介

storyboard-to-slides

ストーリーボードCSVと画像からPowerPoint資料を組み立てます。複数のレイアウトやテーマ、フォントを調整し、表紙を含むスライドデッキを作成できます。

原文原文の説明を見る

Assemble a PPTX slide deck from a storyboard CSV and images using python-pptx. Supports multiple slide layouts (full background, left-image-right-text, two-column, etc.), custom themes, fonts, and cover design. Use when the user wants to build a PowerPoint presentation from a structured plan, compose slides from images and text, or create a polished deck from a storyboard CSV. Triggers: "build slides", "create pptx", "assemble presentation", "make PowerPoint", "storyboard to slides", "generate deck".

dp-archive/archiveスター 1,107(GitHub 1,107 + cccskills 0)
連携ツールPowerPoint

実行スコア 未検証

インストール方法を見る

こんなときに便利

  • CSVの構成案から資料を作りたいとき
  • 画像と文章をスライドに配置したいとき
  • テーマやフォントをそろえたいとき
  • 表紙を含むPowerPointを作りたいとき

日本語での紹介

できること

ストーリーボードCSVと各スライドの画像をもとに、PowerPoint形式の資料を組み立てます。全面画像に文字を重ねる、左に画像・右にテキストを置く、画像の下に説明を添える、2列に分けるといったレイアウトを選べます。背景色や文字色、アクセントカラー、フォント、文字サイズなどのテーマ設定にも対応し、表紙や区切りのスライドも構成できます。CSVにはスライド番号、種類、タイトル、箇条書き、画像ファイルなどを用意します。

こんなときに便利

スライドの構成案と画像がすでにあり、それを編集可能なPowerPoint資料にまとめたいときに向いています。画像と文章を見やすく配置したい場合や、資料全体の色やフォントをそろえたい場合にも使えます。

使い方の例

  • 「このストーリーボードCSVと画像からPowerPointを作ってください」
  • 「各スライドに画像と箇条書きを配置して、資料にしてください」
  • 「指定した色とフォントでスライドデッキを組み立ててください」

注意点

storyboard.csvと、各行に対応するslide_{no}.pngが必要です。Pythonライブラリのpython-pptxとPillowを使用します。

この紹介文は、公開されている SKILL.md をもとに AI(OpenAI Codex)が作成しました。正確な仕様は下の原文を確認してください。

含まれるファイル(1)

  • SKILL.md9.9 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Storyboard to Slides

Assemble a polished PPTX from a storyboard CSV + image files using python-pptx.

Dependencies

# pip install python-pptx Pillow

Input Format

Expects storyboard.csv with columns: slide_no, slide_type, title, bullet_points, image_prompt, speaker_notes, layout

And image files named slide_{no}.png for each row.

Workflow

1. Read the Storyboard

import csv

with open("storyboard.csv", "r", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    slides = list(reader)

2. Initialize the Presentation

from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor

prs = Presentation()
prs.slide_width = Inches(13.333)   # 16:9
prs.slide_height = Inches(7.5)

For 4:3 slides: Inches(10) x Inches(7.5).

3. Define Theme Constants

# Customize per project
THEME = {
    "bg_color": RGBColor(0x1A, 0x1A, 0x2E),     # dark navy
    "title_color": RGBColor(0xFF, 0xFF, 0xFF),
    "text_color": RGBColor(0xE0, 0xE0, 0xE0),
    "accent_color": RGBColor(0x64, 0xB5, 0xF6),
    "title_font": "Arial",
    "body_font": "Arial",
    "title_size": Pt(36),
    "body_size": Pt(18),
}

Choose colors that contrast well with the generated images. For light images use dark text overlay with semi-transparent background; for dark images use white text.

4. Layout Implementations

full_bg — Full-screen background image + overlay text

from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR

def add_full_bg_slide(prs, img_path, title, subtitle="", theme=THEME):
    slide = prs.slides.add_slide(prs.slide_layouts[6])  # blank
    # Background image
    slide.shapes.add_picture(img_path, 0, 0, prs.slide_width, prs.slide_height)
    # Semi-transparent overlay
    overlay = slide.shapes.add_shape(
        1, 0, 0, prs.slide_width, prs.slide_height  # MSO_SHAPE.RECTANGLE = 1
    )
    overlay.fill.solid()
    overlay.fill.fore_color.rgb = RGBColor(0, 0, 0)
    overlay.shadow.inherit = False
    overlay.line.fill.background()
    # Set overlay transparency via XML (access the shape's XML element, not the fill object)
    from pptx.oxml.ns import qn
    solid = overlay._element.find(f'.//{qn("a:solidFill")}')
    if solid is not None:
        srgb = solid.find(qn("a:srgbClr"))
        if srgb is not None:
            alpha = srgb.makeelement(qn("a:alpha"), {"val": "40000"})  # 40% opacity
            srgb.append(alpha)
    # Title
    txBox = slide.shapes.add_textbox(Inches(1), Inches(2.5), Inches(11), Inches(2))
    tf = txBox.text_frame
    tf.word_wrap = True
    p = tf.paragraphs[0]
    p.text = title
    p.font.size = Pt(44)
    p.font.bold = True
    p.font.color.rgb = theme["title_color"]
    p.alignment = PP_ALIGN.CENTER
    if subtitle:
        p2 = tf.add_paragraph()
        p2.text = subtitle
        p2.font.size = Pt(24)
        p2.font.color.rgb = theme["text_color"]
        p2.alignment = PP_ALIGN.CENTER
    return slide

left_img_right_text — Image left, text right

def add_left_img_right_text(prs, img_path, title, bullets, theme=THEME):
    slide = prs.slides.add_slide(prs.slide_layouts[6])
    # Solid background
    bg = slide.background
    fill = bg.fill
    fill.solid()
    fill.fore_color.rgb = theme["bg_color"]
    # Image on left (half width)
    slide.shapes.add_picture(img_path, 0, 0, Inches(6.5), prs.slide_height)
    # Title
    txBox = slide.shapes.add_textbox(Inches(7), Inches(0.5), Inches(5.8), Inches(1.2))
    tf = txBox.text_frame
    tf.word_wrap = True
    p = tf.paragraphs[0]
    p.text = title
    p.font.size = theme["title_size"]
    p.font.bold = True
    p.font.color.rgb = theme["title_color"]
    # Bullets
    txBox2 = slide.shapes.add_textbox(Inches(7), Inches(2), Inches(5.8), Inches(4.5))
    tf2 = txBox2.text_frame
    tf2.word_wrap = True
    for i, line in enumerate(bullets.split("\n")):
        line = line.strip().lstrip("•-").strip()
        if not line:
            continue
        p = tf2.paragraphs[0] if i == 0 else tf2.add_paragraph()
        p.text = f"  {line}"
        p.font.size = theme["body_size"]
        p.font.color.rgb = theme["text_color"]
        p.space_after = Pt(12)
    return slide

top_img_bottom_text — Image top, text bottom

def add_top_img_bottom_text(prs, img_path, title, bullets, theme=THEME):
    slide = prs.slides.add_slide(prs.slide_layouts[6])
    bg = slide.background
    bg.fill.solid()
    bg.fill.fore_color.rgb = theme["bg_color"]
    # Image on top (60% height)
    slide.shapes.add_picture(img_path, 0, 0, prs.slide_width, Inches(4.5))
    # Title
    txBox = slide.shapes.add_textbox(Inches(0.8), Inches(4.8), Inches(11.5), Inches(0.8))
    tf = txBox.text_frame
    tf.word_wrap = True
    p = tf.paragraphs[0]
    p.text = title
    p.font.size = Pt(28)
    p.font.bold = True
    p.font.color.rgb = theme["title_color"]
    # Bullets
    txBox2 = slide.shapes.add_textbox(Inches(0.8), Inches(5.7), Inches(11.5), Inches(1.5))
    tf2 = txBox2.text_frame
    tf2.word_wrap = True
    for i, line in enumerate(bullets.split("\n")):
        line = line.strip().lstrip("•-").strip()
        if not line:
            continue
        p = tf2.paragraphs[0] if i == 0 else tf2.add_paragraph()
        p.text = f"  {line}"
        p.font.size = Pt(16)
        p.font.color.rgb = theme["text_color"]
    return slide

center_text — Section divider / title-only

def add_center_text_slide(prs, img_path, title, subtitle="", theme=THEME):
    slide = prs.slides.add_slide(prs.slide_layouts[6])
    if img_path and os.path.exists(img_path):
        slide.shapes.add_picture(img_path, 0, 0, prs.slide_width, prs.slide_height)
        # Add overlay same as full_bg
    else:
        bg = slide.background
        bg.fill.solid()
        bg.fill.fore_color.rgb = theme["bg_color"]
    txBox = slide.shapes.add_textbox(Inches(2), Inches(2.8), Inches(9), Inches(2))
    tf = txBox.text_frame
    tf.word_wrap = True
    p = tf.paragraphs[0]
    p.text = title
    p.font.size = Pt(40)
    p.font.bold = True
    p.font.color.rgb = theme["title_color"]
    p.alignment = PP_ALIGN.CENTER
    if subtitle:
        p2 = tf.add_paragraph()
        p2.text = subtitle
        p2.font.size = Pt(20)
        p2.font.color.rgb = theme["text_color"]
        p2.alignment = PP_ALIGN.CENTER
    return slide

two_column — Two-column text (for data slides)

def add_two_column_slide(prs, img_path, title, bullets, theme=THEME):
    slide = prs.slides.add_slide(prs.slide_layouts[6])
    bg = slide.background
    bg.fill.solid()
    bg.fill.fore_color.rgb = theme["bg_color"]
    # Title
    txBox = slide.shapes.add_textbox(Inches(0.8), Inches(0.5), Inches(11.5), Inches(1))
    tf = txBox.text_frame
    p = tf.paragraphs[0]
    p.text = title
    p.font.size = theme["title_size"]
    p.font.bold = True
    p.font.color.rgb = theme["title_color"]
    # Split bullets into two columns
    lines = [l.strip().lstrip("•-").strip() for l in bullets.split("\n") if l.strip()]
    mid = len(lines) // 2
    left_lines, right_lines = lines[:mid], lines[mid:]
    for col_idx, (col_lines, left_pos) in enumerate([(left_lines, 0.8), (right_lines, 7.0)]):
        txBox = slide.shapes.add_textbox(Inches(left_pos), Inches(1.8), Inches(5.5), Inches(5))
        tf = txBox.text_frame
        tf.word_wrap = True
        for i, line in enumerate(col_lines):
            p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
            p.text = f"  {line}"
            p.font.size = theme["body_size"]
            p.font.color.rgb = theme["text_color"]
            p.space_after = Pt(10)
    if img_path and os.path.exists(img_path):
        slide.shapes.add_picture(img_path, Inches(9.5), Inches(4.5), Inches(3.5), Inches(2.5))
    return slide

5. Assembly Loop

import os

LAYOUT_MAP = {
    "full_bg": add_full_bg_slide,
    "left_img_right_text": add_left_img_right_text,
    "top_img_bottom_text": add_top_img_bottom_text,
    "center_text": add_center_text_slide,
    "two_column": add_two_column_slide,
}

for row in slides:
    no = row["slide_no"]
    layout = row.get("layout", "left_img_right_text")
    img_path = f"slide_{no}.png"
    title = row.get("title", "")
    bullets = row.get("bullet_points", "")

    fn = LAYOUT_MAP.get(layout, add_left_img_right_text)

    if layout in ("full_bg", "center_text"):
        fn(prs, img_path, title, subtitle=bullets, theme=THEME)
    else:
        fn(prs, img_path, title, bullets, theme=THEME)

prs.save("presentation.pptx")

6. Post-Assembly Checks

After saving, verify:

  • File size is reasonable (images embedded increase size)
  • Slide count matches storyboard row count
  • Report the output filename and size to the user

Font Notes

  • python-pptx embeds font name references, not font files
  • Safe cross-platform fonts: Arial, Calibri, Helvetica
  • For CJK content: specify "Microsoft YaHei", "Noto Sans CJK SC", or "PingFang SC"
  • If the user specifies a custom font, check availability first

Tips

  • Always use prs.slide_layouts[6] (blank layout) for full control
  • Images should match the slide aspect ratio to avoid stretching
  • For dark themes, use light text; for light themes, use dark text
  • Keep the overlay opacity between 30%–50% for readability over images
  • Speaker notes: slide.notes_slide.notes_text_frame.text = notes

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

ai-writing-detection

無料概要あり

文章に含まれる語彙や文の構成、書式、引用の特徴を複数の観点から調べ、AI生成の可能性と根拠を整理します。誤判定を避けるための注意点も示します。

  • 文章のAI生成らしさを複数の観点で調べたいとき
  • 判定の根拠と反証材料を整理したいとき
  • AI文章検出の特徴や限界を知りたいとき
dp-archive/archive1,1072026年3月4日 更新

audio-extractor

無料概要あり

動画や対応サイトの音声を抽出し、MP3やFLACなどに変換して保存します。ポッドキャストやプレイリストの一括取得、曲情報やカバー画像の埋め込みにも使えます。

  • 動画から音声だけを保存したいとき
  • ポッドキャストを音声ファイルにしたいとき
  • プレイリストをまとめてダウンロードしたいとき
dp-archive/archive1,1072026年3月4日 更新

biopython

無料概要あり

DNA・RNA・タンパク質の配列や生物学ファイルをPythonで扱い、配列解析、BLAST、NCBI検索、系統樹作成などの処理を組み立てます。

  • 配列ファイルを読み書き・変換したいとき
  • 配列の統計やアラインメントを調べたいとき
  • NCBIやPubMedの情報をまとめて取得したいとき
dp-archive/archive1,1072026年3月4日 更新

brand-identity

無料概要あり

プロジェクトの説明をもとに、ロゴや配色、書体、名刺、SNSカバー、ブランド仕様書を一貫したビジュアルアイデンティティとしてまとめます。

  • 新しいブランドのロゴを作りたいとき
  • 色と書体のルールを決めたいとき
  • 名刺とSNSカバーをそろえたいとき
dp-archive/archive1,1072026年3月4日 更新

canvas-design

無料概要あり

ポスターや静的なアートを、色・形・余白の方針づくりから制作するスキル。デザイン思想をまとめたMarkdownと、文字を抑えたPNG・PDFの作品を作ります。

  • オリジナルのポスター制作
  • テーマを抽象アートで表現したいとき
  • デザイン方針と作品をそろえたいとき
dp-archive/archive1,1072026年3月4日 更新

code-to-diagram

無料概要あり

ソースコードを読み解き、構成やデータの関係、処理の流れをMermaid.jsの図にしてSVG・PNGで出力するスキルです。

  • コード構成を図で共有したいとき
  • データベースモデルからER図を作りたいとき
  • APIの処理順を可視化したいとき
dp-archive/archive1,1072026年3月4日 更新

dp-archive のスキルをすべて見る

このスキルの問題を報告する