スクリプト+音声 → アニメーションスライド動画 (slidegen)
ユーザー (Michał) からの入力:
- script.txt — 完全なナレーションテキスト (メッセージ内に直接貼り付けられる場合もあります)。 角括弧トークン:
[1],[2]… — スライドフレーム: スライド n は[n]から[n+1]まで実行されます。 ユーザーが選択したハードな区切りです。 スクリプトに区切りがない場合は、トピックごとに分割します (1 スライドにつき 1 つの考え、約 10~40 秒)。[boss.mp4],[mapa.png]— ユーザーが添付するメディアファイル。 ナレーションのその時点から表示します。[その他のテキスト]、例:[obrazek z WoW pokazujący Lich Kinga]— 説明文: 一致する実際のコンテンツを検索し (「アセット」を参照)、その時点から表示します。
- ゲーム名 — 外観はこのゲームを直接的または間接的に参照する必要があります。 アイコン/アートはそのゲームから取得する必要があります (ファイル名
ds_bronieは Dark Souls を示唆します。スクリプトから確認してください)。 - 音声録音 (任意のオーディオ/ビデオ) — スクリプトの前後に届く場合があります。 届き次第、文字起こしを行います。
ハードルール: 動画をレンダリングする前に、ユーザーのコンテンツに基づいた 6 つのゲーム風ビジュアル方向性を表示し、ユーザーの選択を待ちます (ステップ 4)。 ボードにはスクリプトのみ必要です。
コード: GitHub v01d3tr/claude-skills、フォルダ slidegen/ (README にファイル一覧があります)。 script.py トークン → セクション → 時間 · align.py Parakeet TDT v3 → words.json · spec.json は Claude が作成 · render.mjs Playwright Chromium + ffmpeg (移動するウィンドウのみキャプチャ、それ以外はホールド、キャッシュされたセグメント、ボード) · template.html テーマ + レイアウト · icons.py 公式 WoW アイコン · assets.py GitHub からのゲームアート。 このスキル自体のソースは、同じリポジトリ内の skills/slidegen-video/SKILL.md です。
1. セットアップ (セッションごとに 1 回。 /home/claude/slidegen/render.mjs が存在する場合はスキップ)
- add_repo ツールでリポジトリを添付します (owner
v01d3tr、repoclaude-skills;access: "push"はコード変更をプッシュする場合のみ)。ツールの指示に従って、/home/claude/claude-skillsにクローンします。 - インストール:
cp -r /home/claude/claude-skills/slidegen /home/claude/slidegen && cd /home/claude/slidegen && npm install
pip install -q --break-system-packages sherpa-onnx soundfile numpy
mkdir -p /home/claude/models && cd /home/claude/models && curl -sSL https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-nemo-parakeet-tdt-0.6b-v3-int8.tar.bz2 | tar xj
リポジトリにアクセスできず、ユーザーが slidegen.zip を添付した場合は、代わりに /home/claude/ に解凍します。 Playwright + Chromium はプリインストールされています。 シェルから、HuggingFace、Wowhead、wiki、Fandom、ゲーム CDN はブロックされています。 GitHub (git、API search、releases)、npm/PyPI は機能します。
2. スクリプトを読む
mkdir -p /home/claude/proj && cd /home/claude/proj && cp "<script upload>" script.txt # または貼り付けられたテキストを書き込みます。ユーザーが添付したメディアファイルも含みます。
python3 /home/claude/slidegen/script.py split script.txt # セクション、単語数、おおよその時間、メディア/説明トークン、MISSING ファイル
不足しているメディアファイル → ユーザーに添付を依頼します (その間も処理は続行します)。 録音がすでにある場合は、ステップ 5 の align.py + script.py align を今すぐ実行します。スクリプトのどの部分が実際に話されたかが表示されます。話されていないコンテンツをスライドに配置しないでください。
3. スライドを計画し、アセットを見つけ、spec.json を書く
ユーザーは事前の計画を好みます。磨きをかける前に、短いアウトライン (スライド n → タイトル、レイアウト、主要項目、メディア) を送信します。ただし、ユーザーが「そのまま進んで」と言った場合は除きます。 アウトラインはスタイルボード (ステップ 4) と一緒に送信できます。
[n]フレームごとに 1 つのスライド。 フレーム内の[file]/[description]トークンは、その単語から始まる メディアスライド になります。 フレームがクリップ終了後も約 8 秒以上続く場合は、その後にコンテンツスライドを追加します ("at": "<phrase>")。- スライド開始:
[3]の場合は"mark": "3"、 ファイルの場合は"mark": "m:boss.mp4"、説明の場合は"mark": "d:1"… (script.pyによって出力されたキー)。[n]マークがない場合は"at": "<トピックの最初の単語>"を使用します。 - アイテムは、ナレーターがそれらを名前で呼ぶ単語でキューイングされます:
"at": "<1~3の特徴的な単語>"(ファジーマッチングされ、スライドの開始位置から検索されます)。 ASR が正しく取得できる単語を選択し (transcript.txt を確認)、誤った固有名詞は避けます。 - タイトルは約 26 文字以内 (自動短縮)、キャプションは約 35 文字以内、行あたり最大 5 アイコン、最大 4 カード (フィギュアがある場合は 3)。 ポーランド語の正しいダイアクリティカルマークを使用します。スライドは要約であり、書き写しではありません。 名前はスクリプトからスペルを取得し、ASR からは取得しないでください。
- スライドごとに 1 つのエンティティ (武器、クラス、ボス、ビルド) →
featureレイアウト。 ナレーションがキャラクター/敵/NPC を名前で呼んだ場合、そのキューイング時に全身のfigureを追加します (ユーザーはこれを気に入りました)。 - ルックフィールド (
theme、vars、bgImage、fonts) は、ユーザーがステップ 4 で選択した方向性から取得されます。
スペック形式 (完全な動作例: slidegen/examples/dark-souls-bronie/spec.json):
{
"series": "Dark Souls · najlepsze bronie PvE",
"theme": "parchment", "vars": { "--accent": "#8c2a17" }, "bgImage": "art/Mapa_Lordran.webp", "fonts": ["marcellus-sc/400.css"],
"boardThemes": [ /* 6 つの方向性、ステップ 4 */ ],
"audio": "voice.wav", "words": "words.json", "marks": "marks.json", "output": "out.mp4", "lead": 0.12,
"slides": [
{ "mark": "1", "section": "1/4 Wstęp", "kicker": "Dark Souls · PvE", "title": "Najlepsze bronie", "layout": "icons",
"items": [ { "icon": "icons/Zweihander.png", "tone": "fire", "label": "Zweihander", "caption": "siła" } ],
"note": { "at": "według stylu", "text": "podział według stylu gry" } },
{ "mark": "3", "kicker": "Ulubieniec speedrunnerów", "title": "Black Knight Halberd", "layout": "feature",
"feature": { "icon": "icons/Black Knight Halberd.png", "tone": "danger", "label": "BK Halberd", "caption": "quality / siła" },
"figure": { "src": "art/black-knight-figure.jpg", "label": "Czarny Rycerz", "caption": "Darkroot Basin", "at": "czarnego rycerza" },
"items": [ { "at": "czarnego rycerza", "icon": "icons/Black Knight Helm.png", "tone": "shadow", "label": "Drop z Czarnego Rycerza", "caption": "rzadki drop" } ] },
{ "mark": "m:boss.mp4", "layout": "media", "src": "boss.mp4", "caption": "Walka z bossem", "audio": true, "volume": 0.3, "clip": [12, 30] },
{ "mark": "d:1", "layout": "media", "src": "art/icc_raid.jpg", "kicker": "Raid", "title": "Icecrown Citadel", "kenburns": true },
{ "mark": "4", "layout": "meter", "items": [ { "at": "levelowanie", "value": 0.14, "tone": "nature", "label": "Levelowanie", "caption": "prosty i bezpieczny" } ] },
{ "at": "talenty", "layout": "stats", "items": [ { "at": "dziesiątym", "label": "10", "caption": "pierwszy punkt" } ] },
{ "at": "podsumowując", "layout": "hero", "kicker": "Podsumowanie", "title": "Szukamy magów", "subtitle": "serwer PvP, Horda" }
]
}
- キュー形式:
"at": "phrase"、"at": 12.5、{"at": "phrase", "offset": -0.3};"mark"(+"markLead"、デフォルト 0.25 秒)。 キューイングされていないアイテムは、ヘッダーの後にスタガリングして表示されます。 画面上の順序 = リストの順序を維持します (後のアイテムが先にキューイングされる場合はoffsetを使用します)。 - レイアウト:
hero(大きなタイトル + サブタイトル) ·icons(タイルの行、ラベル + キャプション;off: trueはグレーアウト + 取り消し線) ·cards(アイコンはオプション、キャプション、バッジ) ·feature(feature: {icon,label,caption,tone,at}大きなタイルが左側 + 右側にカード; オプションでfigure: {src,label,caption,at}背の高い額入りのポートレートが、右端のキューイング時に出現し、--fig-pos= object-position) ·meter(マーカーが各カードのvalue0~1 に移動し、以前のカードは暗くなります。2 番目のメータースライドは続行できます) ·stats(大きな数字) ·media(画像またはクリップ; オプションで title/kicker;"fit": "full"、"contain": true、"kenburns": true; クリップ:"clip": [s,e]、"audio": true+volume(デフォルト 0.35) はクリップ音声をボイスの下にミックスし、それ以外はミュート;"mediaAt"で遅延します)。 tone: arcane, fire, frost, nature, holy, shadow, danger, neutral。
アセット — 指定されたゲームからの実際のコンテンツ
- WoW アイコン:
python3 /home/claude/slidegen/icons.py find frostbolt lichking;icons.py get /home/claude/proj/icons <name>…(64×64、WeakThorr/wowinterfaceiconsからの約 14k の公式アイコン、非営利ファン使用)。 メイジスペック: arcanespell_holy_magicalsentry、firespell_fire_firebolt02、frostspell_frost_frostbolt02; ボスはachievement_boss_*であることが多い。 名前が不明な場合 → WebSearch " wowhead"。 - 他のゲーム / より大きなアート:
python3 /home/claude/slidegen/assets.py search "<game> icons" "<game> item icons" "<game> assets" "<game> wiki" "<game> fan site" "<game> landing page" "<game> loading screens";assets.py readme owner/repo(公式ダンプ vs ファンメイド);assets.py ls owner/repo <regex>;assets.py get owner/repo /home/claude/proj/art <path>…。 ファン Wiki / ファンサイト / ランディングページリポジトリは、スクリーンショット、エリアアート、キャラクターレンダリングの最良の情報源です。複数の言語で件名を grep します (black|knight|caballero|rycerz)。 また npm (curl -s "https://registry.npmjs.org/-/v1/search?text=<game>%20icons&size=20") も使用します。 - 既知のソース — WoW:
Jestokyzz/mod-loading-screen-16x9(88 のクラシック/TBC/WotLK ローディング画面 1920×1080、ファンリマスター、フレーム + ロゴ付き)、Zogmaw/encounter-journal-images。 Dark Souls 1:SlendyMawn/DarkSoulsItemIcons(すべての DSR アイテムアイコン、透明 PNG 約 185 px、Weapons/、Armor/、Consumables/…)、ozankasikci/dark-souls-wiki(assets/images/{areas,armor,bosses,npcs,weapons,shields,rings,items};armor/*-set.jpg= セット内の全身フィギュア、例:black-knight-set.jpg= Black Knight、180×342 → 3 倍 Lanczos + 軽いアンシャープでアップスケール)、LeaGaj04/dark-souls-hub(public/: 焚き火 4K44.jpg、Mapa_Lordran.webp、gwyn.jpg、artorias.jpg、solaire.jpg、OrnsteinSmough.jpg)、ABDUSSALAM0005/dark-souls-ui(src/background.png暗い羊皮紙、クラスレンダリング)。 - 透明アイテムアイコン (Souls スタイル): ゲーム全体の
vars"--icon-crop": "0%"、"--icon-pad": "7%"、"--icon-fit": "contain"、"--tile-bg": "radial-gradient(circle at 50% 42%、#2e2a25 0%、#141210 70%、#0a0908 100%)"、"--tile-border": "#4d463c"。 WoW アイコンはデフォルトを維持します (8% の境界線クロップ)。 - ゲームフレーム/ロゴのある画像 をメディアスライドとして使用する場合: PIL でアートバンドに事前クロップします (1920×1080 WotLK 画面:
crop((437,340,1482,928))→ 1152×648);bgImageとして--bgart-size: 200% auto; --bgart-pos: 50% 70%を使用します。 ロゴを表示してはいけません。 - 取得したすべての画像を常に読み取り、被写体が表示されていることを確認します。 ゲームアートとして提示する代用画像を生成/描画したり、ゲームキャラクターの画像検索を行ったりしないでください。
- 見つからない場合 → 最善の実際の代替 (エリアアート、防具セットフィギュア、カード上のアイコン) + ギャップをリンク付きでリストアップし (WebSearch)、ユーザーがファイルを添付できるようにします。
- アートの出典 (リポジトリ名。ファンサイト/リマスターの場合はその旨を伝える) と、それがファンコンテンツ利用規約に基づく出版社の IP であることをユーザーに一度伝えます。 game-icons.net (
gi:<name>、CC BY 3.0、クレジット表記) は汎用的な概念にのみ使用します。
4. スタイルボード — 6 つのゲーム風方向性、レンダリング前に必須
spec.boardThemes (最大 6) {name, base, bgImage, fonts, vars} を構築します。ゲーム全体の vars は spec.vars に残します。 実績のあるセット: Dark Souls (例のスペック内 — ユーザーは 2 · Mapa Lordranu: parchment + --bgart-op .17 の Lordran マップ + Marcellus SC を選択) および WoW (WoW ローディング画面上の Karazhan / Questlog / Nexus / Arena / Kirin Tor / Icecrown)。 ゲームとトピックごとに新しいセットを構築します。 ルール:
- 方向性 = base 構造 + ゲーム由来のパレット (
vars) + オプションの実際の 背景アート (bgImage、--bgart-op/-blur/-bright/-sat/-size/-posで調整) + オプションのフォント。 ゲームの場所、派閥、要素、UI パーツにちなんで名前を付けます。 - 6 つのうち ≥ 4 つは、実際のゲームアートを背景として使用するか、認識可能なゲーム UI パーツ (クエストログ、インベントリ、マップ、ローディング画面フレーム) を模倣します。 6 つすべてが明確に異なります (中央揃え/左揃え、明るい/暗い、異なるアート)。
- 込み入ったアートの明るいベース:
--bgart-op≈ .17、より暗い--muted;--fcap-color(フィーチャーキャプション) を暗いアクセントカラーに設定 — トーンカラーは暗いカード用に作られています。 - フォントは
latin-ext(ポーランド語) を持つもののみ:ls /home/claude/slidegen/node_modules/@fontsource/<f>/files | grep -c latin-ext> 0。 OK: Cinzel、Marcellus SC、Pirata One、Cormorant Garamond、Oswald、Rajdhani、Inter。 NG: IM Fell English SC、Orbitron。 その他:npm i -s @fontsource/<f>、"fonts": ["<f>/400.css"]、--title-font/--label-fontを設定します。 - ベース (
template.html内のbody[data-theme=…]):grimoireダークウォームゴールド Cinzel 中央揃え ·parchment明るい紙、濃い赤のタイトル、ダークカード ·arcaneインディゴ/ティールグロー、Rajdhani ·esportsチャコール、Oswald、左揃え、タグキッカー ·codex明るいエディトリアル Cormorant、左揃え ·frostforgeコールドスチールブルー、ホワイトアイス Cinzel。 ゲームが必要とする場合はベースを追加します。
最も代表的な 2 つのスライド (異なるレイアウト。スクリプトがメディアスライドに依存している場合は、メディアスライドを追加) で実行:
cd /home/claude/slidegen && node render.mjs /home/claude/proj/spec.json --board 1,3 # 録音なしで動作
最初に proj/build/board_*.jpg を読み (オーバーフロー、アート上のテキスト、ロゴの漏れ、間違ったアイコン、低コントラストを確認)、修正し、SendUserFile で両方の画像 + アウトラインを送信し、番号または組み合わせを尋ねます。 停止して待ちます。 次に、選択された方向性をスペックのトップレベルにコピーします: theme = base、vars = {...spec.vars, ...direction.vars}、bgImage、fonts。
5. 録音をアライメントし、レンダリングする
cd /home/claude/proj
ffmpeg -v error -y -i "<recording upload>" -vn -ac 1 -ar 44100 voice.wav
python3 /home/claude/slidegen/align.py voice.wav words.json # ~実時間の 0.1 倍; transcript.txt を書き込みます
python3 /home/claude/slidegen/script.py align script.txt words.json # marks.json; "low confidence" / "NOT FOUND" を確認
cd /home/claude/slidegen
node render.mjs /home/claude/proj/spec.json --cues # すべての時間; "Cue not found" / 奇妙なファジーマッチを修正
node render.mjs /home/claude/proj/spec.json --preview 12.4,95.2 # 各スライドの最も充実した瞬間 → build/preview_*.jpg、Read する
node render.mjs /home/claude/proj/spec.json --budget 540 # フォアグラウンド、タイムアウト 600000; exit 3 = PARTIAL → 完了するまで再実行
アドリブは問題ありません (アライメントは一致しない単語をスキップします)。 NOT FOUND マークは、transcript.txt のフレーズを持つ "at" を取得します。 混雑した 1 分間の動画は約 40 秒でレンダリングされます。 長いトークはほとんどホールドです (40 分あたり約 25~35 分)。 スペックの編集は変更されたスライドのみを再レンダリングします。