動く構成図(MP4 / GIF)
成果物は MP4(1920×1080 / 30fps / H.264)と GIF(15MB 以下)とポスター PNG。継ぎ目なくループする。X に貼る構成図は 1本 15〜25 秒、仕組みを説明する運搬型は 45〜70 秒が目安。
型は 2 つある。依頼を読んで、どちらかを選ぶ(下の「0. 依頼を読む」)。
| 型 | 見せるもの | 主役 | 中身のファイル / 描く部品 |
|---|
| 構成図型 | 誰が誰を呼ぶか、全体の構成 | 箱(ノード)と線 | spec.js / engine.js(index.html) |
| 運搬型 | 1 つのデータ(質問・注文・ファイル)が手順を通って、どう変わるか。ループ | 運ばれる札 | carry-spec.js / carry.js(carry.html) |
手法の核
動く構成図は「図」ではなく 出来事の連続 として作る。静止画の構成図は全部を同時に見せるので読む順番が分からないが、動かすと「誰が・いつ・誰に・何を渡すか」が順番に伝わる。
- 登場: ノードが1つずつポップして現れ、両端が出たら線が引かれる(並び順 = 登場順 = 重要な順)
- ステップ: 1ステップ = 1つの出来事。関係するノードだけ明るく光らせ、他は暗くする(どこを見ればいいか迷わせない)
- 流れ: 光の粒(尾つき)が線の上を from → to に流れ、届いた瞬間に相手のノードが波紋で反応する(方向は矢印ではなく粒で見せる)
- 条件: 「〜のときだけ」はバッジ(ピル型ラベル)でノードの上に出す。常時ではない線は点線
- 字幕: 画面下に1ステップ1文をタイプライターで出す。上に小さく
05 ARCHITECT のような見出し、その下に進み具合の点
- 締め: 全部の線に同時に粒を流して「全体が回っている」絵で決め台詞 → フェードアウト。最後のコマ = 最初のコマ(空)なのでループが継ぎ目なし
仕組みは「時刻 t を入れると必ず同じ絵が出る関数」(engine.js の ARCH.render(t))。乱数や実時間を使わないので、Playwright で t = 0, 1/30, 2/30… と1コマずつ撮れば、PCの速さに関係なくカクつかない動画になる。
spec.js(図の中身=主体) → engine.js(t の絵を SVG で描く) → tools/render.mjs(1コマずつ撮影 → ffmpeg)→ MP4 → GIF
0. 依頼を読む(作る前に必ず)
0-1. 相手と、伝えたい 1 文を決める
- 誰が見るか:技術者か、専門外の人(お客様・経営層)か。専門外なら運搬型が合うことが多い。
- 伝えたいことを 1 文にする(例:「AI は判断して答えるだけで、処理はプログラムがする」)。字幕の締めの一言になる。
- その 1 文が今の実物と合っているかを、作る前に確かめる。コード・設定・実行結果を見る。仕組みが最近変わっていて、依頼の 1 文が古いことがある。合わなければ、作る前に「今の実物はこう動いている。どちらで作るか」を聞く。
- 実データで作る。説明用に作った例ではなく、実物を 1 回流した記録(ログ、トレース、実際の入出力)から中身を取る。取れないときは止まって聞く。
0-2. 型を選ぶ
| 依頼に出てくること | 型 |
|---|
| 構成、アーキテクチャ、エージェントのツリー、どこが何を呼ぶか | 構成図型 |
| 仕組みの説明、1 つの例を最初から最後まで、ループ、役割分担(AI とプログラム、人とシステム)、データがどう変わるか | 運搬型 |
0-3. 依頼の言葉と、その奥のニーズ
依頼や指摘の言葉は、次のニーズの表れであることが多い。言葉どおりに部品を足すのではなく、ニーズに合う形に作り替える。
| 依頼・指摘の言葉 | 奥にあるニーズ | すること |
|---|
| 「仕組みを説明して」(相手が専門外) | 1 つの具体例を、最初から最後まで目で追いたい | 運搬型。実物を 1 回流した記録で作る |
| 「〜は〜するだけで、〜が決める」 | 役割の分担を伝えたい | 役割ごとに色を分け、駅の sub に役割を書く。締めの一言にする |
| 「抽象的すぎる」「中身が分からない」 | 各段で、実際に何を受け取り、何をして、何を渡したかを見たい | 駅ごとに、実データ(実際の答え、件数、処理の名前)を短く書く。名前だけの箱にしない |
| 「文章だらけ」「わかりにくい」 | 流れを目で追いたい。文は補足でよい | 文をまとめた大きな枠をやめる。吹き出しは 2〜4 行、字幕は 1 文。流れは札の移動で見せる |
| 「何かを運んでいくイメージ」 | 動いているデータを主役にしたい | 札の名前を、駅を通るたびに変える(質問 → 指示 → 答え → 資料 → 返事) |
| 「四角じゃなくて、左から右に」 | 読む順(左→右)に並べたい | 手順は左から右へ一列。ループの戻りは下を回る線にする。輪(四角)に並べない |
| 「〜が分かりにくい、目的を書いて」 | 名前ではなく、何のためのものかを知りたい | 「名前:何のためか」の形で書く |
| 「固定の部分と、後から足す部分を分けて」 | 構造(変わらないもの / 増えていくもの)を知りたい | 囲み(groups)を分ける。実線 = 毎回同じ、点線 = 増えていく。前の周で増えた行だけ光らせる |
0-4. 一回で伝わる頼み方(ユーザーに案内するときの見本)
依頼があいまいなときは、次の項目を聞く。ユーザーに頼み方を聞かれたら、この形を示す。
〈見る人〉に〈仕組み〉を説明する動画を作って。
伝えたいのは「〈1 文〉」。
〈具体例〉を実際に流して、その記録で作って。
〈段 1〉→〈段 2〉→…と、データが運ばれて変わっていく様子を、左から右のループで見せて。
各段では、受け取ったもの・したこと・渡したものを短く書いて。
毎回同じものと、あとから増えるものは分けて見せて。
ファイル名や JSON の形は出さず、日常の言葉で書いて。
手順(小さく作って、毎回画像で確かめる)
0. 環境
ffmpeg -version / node --version
- Playwright のブラウザは先にキャッシュを見る(Windows:
%LOCALAPPDATA%\ms-playwright)。テンプレートの playwright-core@1.59.1 は chromium-1217 に合う。別の版しかなければ package.json の版を合わせる(各版の browsers.json に revision がある)。render.mjs はキャッシュの新しい Chromium → インストール済み Chrome の順に自動で探す。
1. テンプレートを作業フォルダにコピー
New-Item -ItemType Directory -Force "<作業フォルダ>" | Out-Null
Copy-Item -Recurse "<このスキルのフォルダ>\assets\template\*" "<作業フォルダ>"
cd "<作業フォルダ>"; npm install
node tools/render.mjs info # 尺とステップの時刻表が出れば動いている
書き換えるのは、構成図型なら spec.js だけ、運搬型なら carry-spec.js だけ。どちらも完成例が入っているので、上書きする前に書き方の見本として読む。
- spec.js:Codex のメイン+サブエージェント+建築家の構成
- carry-spec.js:問い合わせチャットが返事を作るまで(架空の例、2 周のループ)
運搬型のコマンドには、すべて --page carry.html を付ける(例: node tools/render.mjs info --page carry.html)。運搬型の作り方は下の「運搬型の作り方」、書式は references/carry-spec.md。
2. 元ネタを spec に落とす
入力(投稿文のツリー、説明文、コード)から、次の対応で spec.js を書く。書式の全項目は references/spec.md。
| 元ネタにあるもの | spec での表し方 |
|---|
| 役割・コンポーネント(explorer, API, DB…) | nodes の1つ。label = 名前、sub = 使うモデルや技術 |
| 使うモデル・種類 | 同じ種類は同じ色(凡例なしで「Luna 組」「Sol 組」が分かる) |
| 強さ・設定(high / medium、v2 など) | tag(カード右上の小さなピル) |
| 呼び出し関係・データの通り道 | edges。常時ではない呼び出しは dashed: true |
| 「A が B に頼んで、B が返す」 | steps[].flow: [['A','B'], ['B','A']] |
| 「〜の前」「〜のとき」だけ動く | 同じステップの badges に時刻をずらして並べる |
| 投稿のキャッチコピー・結論 | outro.caption(締めの一言) |
- ノードは 4〜8 個。それ以上は読めないので、まとめるか2本に分ける。
- 配置は
grid の升目(col, row、小数可)。中心となるノードを上段中央に置き、子を下段に並べるのが一番読みやすい。行が違う線は S字、同じ行の線は直線になるので、線が他のノードを横切らない並びにする。
- 字幕は 1文 20 字前後(36px で横幅に収まる上限は約 40 字)。説明ではなく「何が起きたか」を書く。
- 尺の目安: 登場 約2.5秒 + ステップ 2.4秒 × 数 + 締め 2秒。X では 15〜25 秒が見られやすい。
2'. 運搬型の作り方
1 つのデータが駅を順に通り、駅を通るたびに中身が変わる様子を見せる。
| 実物にあるもの | carry-spec での表し方 |
|---|
| 処理の段(まとめる、判断する、処理する、次へ回す…) | stations。左から右へ処理の順に並べる。sub に役割(AI / プログラム / 人) |
| 流れていくデータ(質問、指示、答え、検索結果、返事) | beats[].out の札。中身が変わるたびに名前を変える |
| 段で起きたこと | bubble。だれが・何をしたかを見出しに、実データを 2〜4 行 |
| ループの戻り(結果を持って最初の段へ) | paths の under。何を持って戻るかを、札の名前と線のラベルで見せる |
| 前の周の結果が次の周の入力に入る | 次の周の最初の駅の吹き出しで、増えた行だけ mark で光らせ、ほかは dim |
| 毎回同じものと、増えていくもの(決まりと会話の記録など) | groups で囲みを分ける(実線 / 点線)。fly で囲みが札になって駅に入る |
| 外部に出る結果(お客様への返事など) | 外側の under の線で、最初の駅(お客様など)へ運ぶ。最後に結果の全文を吹き出しで見せる |
- 駅は 4〜6 個。1 周を 4 段程度にまとめる。
- 吹き出しの中身は、実データの要点だけ。全文を見せるのは最後の結果(返事など)1 か所にする。
- 2 周以上あるときは、2 周目で「前の周の結果が入った」ことが分かる絵を必ず入れる。
3. 確かめる(書き出す前に必ず画像で見る)
node tools/render.mjs sheet 16 # out/sheet.png(全体を16コマ、各コマに時刻入り)
node tools/render.mjs stills 12.6,19.4 # out/still-<秒>.png(原寸)
Read ツールで画像を開いて見る。見るところ:
- 線がノードを横切っていないか、ノード同士・バッジ・タグが重なっていないか
- 字幕がはみ出していないか、フォント(Noto Sans JP)が効いているか(豆腐や明朝になっていないか)
- 各ステップで「光っているノード」と「粒の流れる線」が字幕の内容と合っているか
- コンソールに
edge not found が出ていないか(flow に書いた組が edges にない)
- 運搬型では、吹き出しが副題やとなりの吹き出しと重なっていないか、1 文字だけ次の行に落ちていないか。各滞在の終わり近く(全部の行が出そろった時刻)を撮る。いちばん中身が多い吹き出しのコマは必ず見る
- 中身が実データと合っているか(数・答え・処理の名前)。言い換えた文を「」に入れていないか
ブラウザで index.html を開くとループ再生、index.html?t=12.6 でその時刻に止まる(時刻表示つき)。
4. 書き出し → 検証 → 納品
node tools/render.mjs video diagram # out/diagram.mp4 + diagram.gif + diagram-poster.png
node tools/render.mjs video carry --page carry.html # 運搬型
ffprobe -v error -show_entries stream=width,height,r_frame_rate,nb_frames -show_entries format=duration,size -of compact out/diagram.mp4
# ループ確認: 最初と最後のコマがどちらも空(背景だけ)なら継ぎ目なし
ffmpeg -v error -i out/diagram.mp4 -vf "select='eq(n\,0)+eq(n\,<最後のコマ番号>)',scale=480:-1,tile=2x1" -frames:v 1 -y out/loop-check.png
- GIF は X の上限 15MB を超えたら自動で幅と fps を落として作り直す(960px/15fps → 800px/12fps → 640px/10fps)。20秒前後で 12MB 程度。
- X には MP4 を推奨(GIF より軽くて綺麗)。GIF は Slack・README・社内資料向け。ポスター PNG はサムネイルやブログのアイキャッチに使える。
- ファイルを渡すツール(SendUserFile など)があれば MP4 と GIF を渡す。スクラッチの作業フォルダは消えるので、残すなら保存先を聞く。
専門外の人に見せる中身の書き方
- ファイル名・関数名・JSON の形は出さない。「〜を書いた文章」「〜の一覧」のように、中身で呼ぶ。
- 名前を並べるときは、何のためのものかを添える(「目次:困りごとごとに、先に聞くこと」)。
- 判定は「〜か:はい/なし」のように、問いと答えの形で書く。
- 実物の文を引くときだけ「」に入れる。短く言い換えたものは「」に入れない(「決まりの文章:〜」のように書く)。
- 記録に残っていないこと(AI がどう考えたか、など)は推測で書かない。実際の答えと、それに合う指示の文を並べる。
- 文は吹き出し 2〜4 行と、字幕 1 文まで。説明を足したくなったら、文を足すのではなく、札の名前や囲みや色で見せられないかを先に考える。
見た目を変えたいとき
- 色・フォント:
spec.js に theme: { bg, card, fg, dim, edge, dot, font, mono } を足す(既定は暗い背景のターミナル風)。明るい背景にするなら bg/card/fg/edge/dot をまとめて変える。
- 動きの速さ: ステップごとの
dur(滞在秒)と hop(粒が1区間を流れる秒)。軽い処理は hop: 0.5、重い処理は hop: 1.0 にすると「速さ」まで伝わる。
- 演出を足すときは
engine.js の render(t) に「t から決まる値」として書く(Math.random() や Date.now() は使わない。使うと録画がガタつく)。
実際に踏んだ落とし穴
| 症状 | 原因 | 対処 |
|---|
| ループの継ぎ目で一瞬図がチラつく | フェードの終わり = 尺の終わりだと、最後のコマ(t = 尺 − 1/30)がまだ少し見える | フェードを尺より少し前(−0.12秒)に終わらせる(対処済み) |
| バッジやタグの枠が文字幅と合わない | フォント読み込み前に文字幅を測った | 全部の文字を透明で一度置き、document.fonts.ready を待ってから測る(対処済み) |
| 点線が「引かれる」演出にならない | 線を引く演出も stroke-dasharray を使うので点線と両立しない | 点線はフェードインで出し、流れる点線(dashoffset を t で動かす)にする(対処済み) |
| 依頼の 1 文と、今の実物の動きが違っていた | 仕組みが最近変わっていて、依頼が古い理解のままだった | 作る前に実物を見て確かめ、違えば聞く(0-1) |
| 「抽象的すぎる」と言われた | 箱の名前と線だけで、各段で何が起きたかの中身が無かった | 駅ごとに実データを短く書く(運搬型の吹き出し) |
| 中身を足したら「文章だらけでわかりにくい」と言われた | 中身を、図の下の大きな文章の枠にまとめた。流れを追う図が、読む文書になった | 文の枠をやめ、運ばれる札と、駅の上の短い吹き出しにする |
| 輪(四角)に並べたら、流れの向きが追いにくかった | 時計回りは、左から右に読む順と合わない | 左から右へ一列に並べ、戻りは下を回る線にする |
| 「〜の文章」「会話」「選べること」が分かりにくいと言われた | 名前だけを並べ、目的と構造(固定 / 追加)が無かった | 「名前:目的」で書き、固定と追加を囲みで分ける |
| 吹き出しが副題やとなりの吹き出しと重なる | 中身が増えて背が高く・幅が広くなった | 文を縮める、dx でずらす、keep: 'next' で前の吹き出しを消す |
| 1 文字だけ次の行に落ちる | 幅ぎりぎりの文 | 文を縮めるか、その行の size を 1〜2 下げる |