Communitygithub.com

Orinkle/ideaform

「構成主義解説動画」を制作する4段階パイプライン:原稿 → TTS解説音声(時間軸)→ LMMS BGM(変奏で論述の階層をマーキング)→ Remotionでレンダリング&サムネイル生成。解説動画・知識動画・ナレーションビデオ、または「解説音声を時間軸とし、BGMが論述階層に応じて変化する」作品を作りたいときに使用。前提:ideaform-setupで環境設定とtoolchain.jsonのパス契約が完了していること。

ideaform とは?

**Orinkle/ideaform** は、解説動画を構造主義的なアプローチで制作するための4段階ワークフローを提供するAIエージェントスキルです。中心となるコンセプトは「解説音声を時間軸とする」ことで、TTS(テキスト読み上げ)の自然な話速がビデオ全体のフレーム数を決定します。BGMは論述の階層(プレゼンテーション、展開、対比、解決など)が切り替わるタイミングで変奏し、単なる背景音楽ではなくナラティブ構造を強調します。対応プラットフォームはClaude Code、Cursor、Codexなどの開発者向けAIエージェントで、環境設定は`ideaform-setup`スキルによって事前に行われ、パスやツールの情報は `toolchain.json` という契約ファイルで一元管理されます。このスキルは、原稿作成、TTS音声生成、LMMSによる音楽制作、Remotionによる映像レンダリングの4つのフェーズを順次実行し、最終的に音声・BGM・映像・サムネイルが統合された完成品を出力します。各フェーズには数値チェッカーが組み込まれており、音声の音量やクリッピング、フレーム数、サムネイルの品質などを自動検証することで、品質を保証します。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Orinkle/ideaform/tree/HEAD/skills/ideaform

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

構成主義解説動画 · ワークフロー

1本の時間軸、3つの下流工程がすべてそこから派生する。

① 原稿            ② TTSで軸を固定                ③ BGM変奏            ④ 完成品
   文章    ──→   解説音声(時間軸)──→    LMMS音楽(階層)──→   Remotion映像 + 音声統合 + サムネイル
                          │                        ▲
                          └──── 階層境界の時間ポイント ─────┘
  • 映像のフレーム数はTTSの自然な話速から生成される(逆に話速を圧縮するのではない)
  • BGMの変奏ポイントは解説の階層切り替えポイントに合わせる
  • 完成品は解説音声を基準に同期し、BGMはあくまで背景として機能する

0. はじめに:まずパス契約を読む(このステップは必須)

このスキルはツールを自ら探しません。すべてのパスは環境設定スキルが書き出した契約から取得します。

$VW_CONTRACT  (デフォルト ~/.config/ideaform/toolchain.json)
CONTRACT="${VW_CONTRACT:-$HOME/.config/ideaform/toolchain.json}"
source "$(dirname "$CONTRACT")/env.sh"     # VW_NODE / VW_VENV / VW_FFMPEG / … をエクスポート

作業開始前に必ず3つ確認すること:

  1. 契約ファイルは存在するか?存在しない → ユーザーに ideaform-setup スキルを先に実行してもらう。
  2. schema_version はこのスキルが認識するバージョンか?一致しない → 環境設定スキルの再実行を要求する。
  3. verified_at が null か?はい → 「環境がスモークテストを通過していません」 と警告し、先に修正してから作業を進める。 さらに tools.lmms.stkdir_ok が true である必要がある。そうでないとBGMは無音でエラーも出ない。

主要フィールドの早見表:

用途契約フィールド
TTSスクリプトの実行(edge-ttsはvenv内)tools.venv.python
音声・映像の合成tools.ffmpeg.path / tools.ffprobe.path
映像のレンダリングtools.remotion.project / tools.remotion.browser.resolved
BGMのレンダリングtools.lmms.apprun
一時ファイルの置き場所(大容量ディスク必須)tmpdir

⚠️ 契約内の tmpdir はオプションではありません。 ローカルの /tmp は10MBしかなく、Remotionのパッケージングやpipのインストールでそこに書き込むと ENOSPC エラーになります。すべてのRemotionコマンドには TMPDIR を指定してください。

⚠️ パスは一切 resolve(シンボリックリンク解決)しないでください。 管理されたツールチェーンのパスにはシンボリックリンクが含まれており、venvのインタプリタを解決するとvenvコンテキストが失われ、すべてのパッケージがimportできなくなります。詳細はリポジトリルートの docs/03-パス契約.md を参照。


1. 4段階の概要

段階何をする入力出力(すべてワークスペースに格納)参考
① 原稿ユーザーの入力を階層化された解説原稿に変換ユーザー入力script.md + 台词.txt(階層がマークされている)references/stage1-script.md
② TTSで軸を固定自然な話速を計測 → タイムラインを作成 → ナレーション音声を生成台词.txtplan.json / timeline.ts / voice.wavreferences/stage2-tts.md
③ BGM変奏階層境界 → 変奏計画 → LMMSで音声出力plan.json + 階層マークbgm-plan.json / bgm.wavreferences/stage3-bgm.md
④ 完成品Remotionで映像配置 + 音声統合 + レンダリング + サムネイルtimeline.ts + 音声 + bgm-plan.jsonfinal.mp4 + cover.pngreferences/stage4-render.md · references/cover.md

スタイルの統一は references/constructivist-style.md が管理し、 映像とサムネイルで同じカラーパレット・フォント・グリッドを共有するため、自然に統一感が生まれます。


2. フェーズ1 · 原稿(階層化は必須)

ユーザーが与えるのは入力(テーマ / 資料 / 口頭でのアイデア)です。出力は以下:

  • script.md —— 完全な原稿で、論述階層を明示的にマーク
  • 台词.txt —— 1行1文のナレーション台本。TTSが使用

階層化は見た目のためではなく、フェーズ3への入力です。 階層マークがなければ、BGM変奏の基点がありません。

## 階層1 · 導入
これは「原稿=時間軸」の第一層です。
解説音声こそが、このパイプライン全体の時間軸です。
## 階層2 · 展開
映像のフレーム数は、音声によって決まります。その逆ではありません。
...
  • 1文 = 1つの意味単位。1文に2つのことを詰め込まない(TTSは文単位でタイムラインを組むため、詰め込むとスロットが長くなる)
  • 1文は8~30文字を推奨。長すぎる場合は分割、短すぎる場合は結合
  • 句読点は「。」「?」で文を区切り、TTSの区切りを助ける

詳細は references/stage1-script.md を参照。


3. フェーズ2 · TTSで軸を固定(順序は絶対)

"$VW_VENV/bin/python" skills/ideaform/scripts/make-tts-track.py \
    --lines 台词.txt --fps 30 --audio \
    --plan-out out/plan.json --ts-out out/timeline.ts

まず音声、その後に軸を固定。 タイムラインはTTSの実際の話速から生成されます:

① 台本を書く
② make-tts-track.py --lines 台词.txt --fps 30 --audio   ← 自然な話速を計測し、タイムラインを出力
③ 出力された TOTAL_FRAMES を使ってRemotionのcompositionを記述 ← フレーム数はここで確定
④ レンダリング

逆順の代償(実測):先に絵コンテで43本のタイムコードを固定し、TTSの自然な話速の合計が212.90秒だったのに対し、動画は174.80秒しかなかった → 1.218倍に強制圧縮。この妥協は完全に回避できたはずです。

同じスクリプトで逆のことも可能(既存のSRTやタイムコードが固定されている場合、2段階の速度調整で対応)ですが、 それは救済措置であり、第一選択肢ではありません。詳細は references/stage2-tts.md を参照。

⚠️ 「完成品は何分ですか」とユーザーに尋ねることを禁止します。 尺 = 話速 × 台詞量 であり、出力であって入力ではありません。 作業開始時に「標準版X分」などの選択肢を尋ねたり提示したりしてはいけません。報告するのは「この原稿では、実測でX分Y秒です」のみ。 ユーザーが長く/短くしたい場合 → 変更するのは原稿であり、時間ではありません。(2026-10-15 桂花編で経験、E16に記録)

出力:plan.json 内の各エントリに start/end/dur/frameStart/frameEnd が含まれます。 timeline.ts はそのまま cp でRemotionプロジェクトの src/timeline.ts として使用可能。


4. フェーズ3 · BGM変奏(このワークフローの肝)

要点:論述が新しい階層に入るたびに、音楽の形態が変わる —— ただし曲は変わらない。

# ① 原稿の階層をCUE番号に変換し、各階層のナラティブ機能をマーク
"$VW_VENV/bin/python" skills/ideaform/scripts/bgm-plan.py \
    --plan out/plan.json \
    --layers "1:present,4:develop,6:resolve" \
    --key "A minor" --out out/bgm-plan.json

# ② bgm-plan.json に従ってLMMSプロジェクトを生成しレンダリング(electronic-music-production の composer.py を使用)
#    契約内の tools.lmms.apprun でレンダリング。bpm と timeline lp1pos は mmp_hints に従って記述すること

6つのナラティブ機能(各階層から1つ選択):

機能意図変更内容
present提示・導入モチーフのみ、単声部、余白を残す
develop展開・深化+ベース +グルーブ、モチーフの模倣進行
intensify強調・対立全声部、1オクターブ上げ、借用和音、強度を上げる
contrast対照・転換音量を上げずに質感を変える:声部削除、音色変更、旋法転換
resolve収束・回帰声部削減、主調に戻る、モチーフの拡大
sustain継続・遷移変更なし(階層が変わっていないのに無闇に変奏すると、コントラストが希薄になる)

鉄則:

  • アイデンティティ要素は変えてはいけない —— モチーフの核、調の中心、基本テンポ。変えると「変奏」ではなく「曲替わり」になる。
  • 各セクションで少なくとも1つの形態要素を変更すること。bgm-plan.md には各セクションの「変奏の証拠」を列挙し、 隣接する2セクションで証拠が空なら、階層マークが漏れていることを示す。
  • 変奏ポイントは必ず解説の階層境界に合わせる(--lead-in で音楽を少し早めに開始することも可能)。

完全な方法とLMMS側での実装は references/stage3-bgm.md を参照。


5. フェーズ4 · 完成品

5.1 映像:解説音声を時間軸として

cp out/timeline.ts <remotionプロジェクト>/src/timeline.ts     # フレーム数/シーン境界はすべてCUESから導出
cd <remotionプロジェクト>
export TMPDIR="$VW_TMPDIR"                             # ★ 必須
npx remotion studio                                    # まずユーザーにプレビューを見せる

映像側のシーン境界はフレーム番号を手書きせず、CUES から導出:

export const SCENES = {
  s1: { from: 0,            dur: CUES[2].start },
  s2: { from: CUES[2].start, dur: CUES[4].start - CUES[2].start },
} as const;

構造式・シグナル伝達経路・メカニズム図 → すべて決定論的に生成し、絶対にAIで画像を生成しない。 AIが化学構造を描画すると、幻覚で結合を誤作し、しかもエラーが見つけにくい——こうした素材は再現可能で検証可能でなければなりません。 scripts/gen-structures.py を使用:SMILES → RDKitで決定論的な描写 → フレーム駆動のRemotionコンポーネント。

python3 scripts/gen-structures.py --tsv structures.tsv --out structures
#   → svg/*.svg  +  components/*.tsx(アニメーション付き)  +  manifest.json
#   → 分子式のオフライン検証(RDKit CalcMolFormula)、不一致なら非ゼロ終了、直接 `&&` で連結可能
  • 配色は RDKit公式オプション(useBWAtomPalette / singleColourBonds / setSymbolColour)を使用し、 SVGの色を正規表現で後処理しない——それは車輪の再発明であり、RDKitのバージョンアップで壊れます(エラー集E20参照)。
  • 生成されたコンポーネントはCSS変数 --mol-dash / --mol-text を使用して線のアニメーションを駆動するため、外側で必ず color を設定すること。
  • グリッド図・骨格ハイライト・3D配座・タンパク質-リガンド相互作用図など、より広範な分子可視化が必要な場合は、 既存のスキルを探す(§7参照)。ビデオパイプライン内に無理に詰め込まないこと。

5.2 音声統合(2つの方法、デフォルトはA)

A. Remotion統合(推奨) —— composition内で <Audio> を使用。レンダリングされたmp4には音声が含まれます:

<Audio src={staticFile("voice.wav")} />
<Audio src={staticFile("bgm.wav")} volume={0.1694} />

volume の値は感覚で決めず、実測RMSから逆算:

bash scripts/mix-av.sh --plan-only --voice voice.wav --bgm bgm.wav --drop 9
# ナレーション RMS = -23.46 dBFS   BGM RMS = -17.04 dBFS
# → BGMに -15.42 dB の減衰が必要 →  volume = 0.1694

B. 後合成(動画はすでにレンダリング済 / ナレーションを再録したい場合):

bash scripts/mix-av.sh --video silent.mp4 --voice voice.wav --bgm bgm.wav --out final.mp4

⚠️ 方法Bでは明示的に -map 0:v:0 -map 1:a:0 を使用すること。 Remotionが出力するmp4には1本の無音AACトラックが含まれています。 -map を追加しないと、ffmpegは自動的にそのトラックを選択し、結果として終了コード0、尺は正しい、再生できるが、音声がない状態になります。 mix-av.sh にはすでにこの -map が組み込まれています。

5.3 レンダリングとサムネイル

export TMPDIR="$VW_TMPDIR"
npx remotion render <CompositionId> out/video.mp4 --concurrency=3
npx remotion still Cover out/cover.png --props='{...}'    # サムネイル:静的なcompositionを使用。アニメーションは避けること
  • 長尺動画は分割レンダリング:7分の動画を1回でレンダリングすると、メモリ不足でタイムアウトする可能性があります。--frames=A-B で分割 → concat -c copy でロスレス結合。
  • サムネイルは durationInFrames={1} の静的なcompositionを使用。コンポーネント内では** useCurrentFrame を使用しないこと**(still時は常に0で、アニメーションの初期値により要素が非表示になります)。
  • サムネイルのレイアウトは references/cover.md を、スタイル仕様は references/constructivist-style.md を参照。

6. 目視なしでの納品:各フェーズでチェッカーを通過すること

モデルは画像を見られず、音声を聞けません。 したがって「レンダリング成功」≠「映像が正しい、音声が正しい」。 各ステップで数値による実測検証を行い、基準を満たさなければ納品を拒否します:

# 音声セルフチェック(TTS音声、BGM):ピーク/RMS/クリッピング/長さのずれ
# 映像セルフチェック:ピクセルカラー / 背景の純粋度 / テキストピクセル数
#   --layout は正しく選択すること:cover=サムネイルレイアウト;scene=動画シーン(デフォルト)。
#   サンプリングストリップはレイアウトに応じて決まるため、間違えると正しいサムネイルでも不合格になる(05-トラブルシューティング D2参照)。
python3 scripts/verify-video.py cover out/cover.png --layout cover

# 完成品セルフチェック:フレーム数 / 尺 / 音声ビットレート(無音トラックを防止)
# ffprobeの優先順位:VW_FFPROBE → パス契約 toolchain.json → システム
VW_FFPROBE="$VW_FFPROBE" python3 scripts/verify-video.py video out/final.mp4 --frames 732 --fps 30

スクリプトは非ゼロ終了コードで失敗を示すため、&& でパイプラインに直接組み込めます。

よく使う判定基準の早見表:

対象判定基準しきい値
音声無音でないピーク > 1000 かつ RMS > 100
音声クリッピングなしフルスケールサンプル < 0.01%
音声尺の一致計画とのずれ < 50 ms
サムネイルサイズ1920×1080
サムネイルテキストレンダリングテキスト領域のインクピクセル > 300
サムネイル軸線上にテキストがないタイトル領域内の赤ピクセル < 60
完成品フレーム数計画値と完全一致
完成品音声が無音でないビットレート > 64000 bps
BGM背景レベルナレーションより8–12 dB低い

7. このスキルと連携する他の機能

必要なもの使用するもの
環境検出 / 補完インストール / 契約ideaform-setup(1回限り)
新しいオープンソースツールの既成スキル(取ってくる:GitHubから収穫 → セキュリティチェック → 保存)ideaform-setup の scripts/harvest-skills.py <ツール名>
化学構造式・経路図の決定論的なグラフィックこのスキルの scripts/gen-structures.py(RDKit → SVG → Remotionコンポーネント)
より広範な分子可視化(グリッド図 / 骨格ハイライト / 3D配座 / タンパク質-リガンド)外部の既成スキル:synthetic-sciences/openscience の molecule-visualization(Apache-2.0)、ghutchis/chem-skill(MIT)
LMMSプロジェクトのフォーマット、プラグインパラメータ、eldata エンベロープelectronic-music-production + その references/05
作曲法(和声、モチーフ、非聴覚作曲、創発)electronic-music-production の references/06–10
Remotionの文法とレンダリングの詳細remotion-best-practices
ピクセルレベルの目視なし検証の完全な方法headless-visual-verify
WSL環境の落とし穴(/mnt、ghの取得、音声パス)wsl-pitfalls

8. 納品チェックリスト

1本の動画が完成したら、ワークスペースに以下が存在する必要があります:

<ワークスペース>/
├── script.md            階層化された原稿
├── 台词.txt             ナレーション台本
├── out/
│   ├── plan.json        時間軸(各CUEの秒/フレーム)
│   ├── timeline.ts      Remotionにそのまま取り込めるタイムライン
│   ├── voice.wav        ナレーション音声マスター
│   ├── bgm-plan.json    変奏計画 + bgm-plan.md(変奏の証拠)
│   ├── bgm.wav          BGM音声
│   ├── video.mp4        無音映像(または音声統合済みの完成品)
│   ├── final.mp4        ★ 最終完成品
│   └── cover.png        ★ サムネイル
└── .tts/                TTSキャッシュ(保持。再実行は数秒で完了)

納品前に必ずセクション6のすべてのチェックを実行し、どの項目が合格し、どの項目が未テストかを正直に報告すること。


9. 自己進化:問題が起きたら記録する

このワークフローは変更可能な複合スキルです——使ううちに、あなたの制作リズムに合うように進化していきます:

  • 問題が発生し、修正が完了したら → リポジトリルートの docs/06-エラー集.md に記録(6カラム形式、連番)。 ⚠️ skills/ideaform/ の下に新たに docs/ を作成しない——それは2冊目の台帳となり、本家の連番と衝突します(2026-10-15に経験、E19に記録)。
  • ある問題がスクリプトやドキュメントで恒久的に修正された(回避策ではなく)場合 → 該当エントリのステータスを 根治済み に変更し、修正方法を明記する。
  • 同じ種類の問題が2回目に発生した場合 → 3つ目のエントリを追加するのではなく、防御策(チェッカー / デフォルト値 / 契約)を直接スクリプトに組み込む。
  • 新しいオープンソースツールを導入する場合 → まず収穫してから作業を開始:harvest-skills.py <ツール名> でコミュニティの成熟したスキルを探す (フォーク保護あり、ローカルで変更したものを上書きしない)。適切なものが見つからなければ、自分で作成する。収穫したスキルで問題が発生した場合も、同様に記録する。
  • セッション終了前に確認:「修正したが記録していない」ものがないか?

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

関連スキル