| name | release-script |
| description | リリースノートとX投稿ドラフトからMulmoScript(リリースノート動画用)を生成する。/release-xpost 完了後に実行。 |
| allowed-tools | Read, Write, Glob, Grep, Bash, AskUserQuestion |
| argument-hint | <version> (例: 1.0.11) |
バージョン $ARGUMENTS のリリースノート動画用 MulmoScript を生成する。
前提条件
docs/release_notes/v$ARGUMENTS/release_notes_v$ARGUMENTS.md が作成済みであること
docs/release_notes/v$ARGUMENTS/xpost_v$ARGUMENTS_draft.md が作成済みであること
docs/release_notes/v$ARGUMENTS/images/ にスクリーンショットが保存されていること
手順
Step 1: 入力ファイルの読み込み
以下を読み込む:
docs/release_notes/v<version>/release_notes_v<version>.md — 機能の詳細
docs/release_notes/v<version>/xpost_v<version>_draft.md — 構成と画像参照
docs/release_notes/v<version>/images/ — スクリーンショット一覧
Step 2: 既存スクリプトの参照
過去のスクリプトをテンプレートとして参照する:
ls docs/release_notes/v*/release_v*_script.json
最新のスクリプトを読み込み、パラメータ部分($mulmocast 〜 audioParams)をテンプレートとして使用する。
Step 3: Beats の構成
xpost draft の構成に沿って beats を作成する:
3a. タイトルスライド(2ビート構成)
バージョン番号にドットが含まれるため、textSplit の . 区切りで v1.0.11 が分割されてしまう。これを回避するため、タイトルスライドは2ビートに分ける:
ビート1: バージョン番号を含む挨拶(caption分割を無効化)
{
"speaker": "Presenter",
"text": "マルモキャスト バージョン<version読み>をリリースしました!",
"captionParams": {
"captionSplit": "none",
"textSplit": { "type": "none" }
},
"id": "title-slide",
"image": {
"type": "markdown",
"markdown": [
"<div style='display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100vh; text-align: center;'>",
"",
"# 🎉 MulmoCast v<version> Released!",
"## <日付>",
"",
"</div>"
]
}
}
ビート2: サマリー(デフォルトのcaptionParamsを使用、タイトルスライドの画像を参照)
単なる機能列挙ではなく、リリースの背景・価値・ユーザーへの影響を1〜2文で伝える。動画では視聴者に文脈を与え、mulmo markdown で生成する記事の冒頭も充実する。
避けるパターン: 「このバージョンでは、○○、△△などの更新があります。」(機能名の羅列)
良いパターン: 変更の背景や、ユーザーにとっての意味を伝える文にする
{
"speaker": "Presenter",
"text": "<リリースの背景・価値を伝えるサマリー>",
"id": "title-overview",
"image": {
"type": "beat",
"id": "title-slide"
}
}
3b. 機能紹介ビート
xpost draft の各ポスト(メインポスト + 連投ポスト)から:
- 画像:
images/ 内のスクリーンショットを kind: path で参照
- ナレーション: release notes の詳細を元に日本語で作成
- 構成: 1機能につき1〜複数ビート(スクショの数に応じて)
画像マッピングルール:
画像ファイル名のプレフィックス {ポスト番号}-{画像番号}_ でビートに自動対応:
01-* → メインポストのビート
02-* → 連投1のビート
03-* → 連投2のビート(以降同様)
- 1ポストに複数画像がある場合、画像ごとに別ビートを作成
プレフィックスがない旧形式の画像は、xpost draft の添付メディア記述から対応を判断する。
{
"speaker": "Presenter",
"text": "<日本語ナレーション>",
"id": "<機能を表すID>",
"image": {
"type": "image",
"source": {
"kind": "path",
"path": "images/<filename>.png"
}
}
}
mp4(動画)を参照する場合:
動画ファイルを使うビートは "type": "movie" を使う。"type": "image" では動画は再生されない:
{
"speaker": "Presenter",
"text": "<日本語ナレーション>",
"id": "<機能を表すID>",
"image": {
"type": "movie",
"source": {
"kind": "path",
"path": "images/<filename>.mp4"
}
}
}
重要: type: movie ビートではナレーションの TTS 長さが mp4 の duration を超えないようテキストを調整する。超えると次ビートに音声がはみ出して、映像・字幕・次ビートの開始タイミングがズレる。mp4 が短い場合はナレーションを 1 文程度に絞るか、補足説明を後続ビートに分ける。
デリミタ文字を含むテキストの分割ルール:
ナレーション中にバージョン番号(0.25、4.0)、モデル名(gemini-3.1-flash-image-preview)など、textSplit のデリミタ(.、,)を含む文字列がある場合、その部分でキャプションが意図せず分割される。これを回避するため、デリミタを含む部分を独立ビートに分離する:
{
"speaker": "Presenter",
"text": "1:TTS読み上げ速度オプションを追加しました",
"id": "tts-speed",
"image": { "type": "image", "source": { "kind": "path", "path": "images/01-01_speed.png" } }
}
{
"speaker": "Presenter",
"text": "OpenAI TTSでは0.25倍速から4.0倍速まで設定できます",
"captionParams": { "captionSplit": "none", "textSplit": { "type": "none" } },
"id": "tts-speed-detail",
"image": { "type": "beat", "id": "tts-speed" }
}
{
"speaker": "Presenter",
"text": "読み上げ速度は設定画面から変更できます",
"id": "tts-speed-usage",
"image": { "type": "beat", "id": "tts-speed" }
}
ポイント:
- デリミタを含むビートのみ
captionParams で captionSplit: "none" + textSplit: { type: "none" } を設定
- 前後のビートは
image: { type: "beat", id: "..." } で同じ画像を参照
- 1機能が2〜3ビートに分かれるのは正常
3c. クロージングスライド(2ビート構成)
タイトルスライドと同様に、バージョン番号を含む文を分離する。
ビート1: その他の改善・案内
{
"speaker": "Presenter",
"text": "その他、軽微な改善を行いました。\n起動中のアプリに更新通知が届きます。\nダウンロードは公式サイトから行えます。",
"id": "thank-you-slide",
"image": {
"type": "markdown",
"markdown": [
"<div style='display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100vh; text-align: center;'>",
"",
"# Thank You!",
"",
"## MulmoCast v<version>",
"",
"### Happy Creating!",
"</div>"
]
}
}
ビート2: バージョン番号を含む締め(caption分割を無効化、Thank Youスライドの画像を参照)
{
"speaker": "Presenter",
"text": "マルモキャスト バージョン<version読み>をお楽しみください!",
"captionParams": {
"captionSplit": "none",
"textSplit": { "type": "none" }
},
"id": "thank-you-closing",
"image": {
"type": "beat",
"id": "thank-you-slide"
}
}
3d. Markdown スライドの設計原則
機能紹介・告知用 Markdown スライドを設計する際の指針。
- スタイル統一: 同じ役割のスライド(機能紹介系・変更告知系など)はレイアウト・揃え方・見出しレベルを揃える。タイトル / クロージング等の「ブックエンド系」と本編系で雰囲気を分ける程度に留め、本編内で混在させない(揃っていないと「なぜ違うのか」という認知ノイズになる)
- 抽象まとめより具体列挙: 「N 件追加」のような数や抽象表現だけで終わらせず、主要な要素名(モデル名・機能名等)を bullet で列挙する。ユーザーは「いくつ」ではなく「何が」を見たい
- テキストとスライドの役割分担: ナレーションテキスト(TTS)はスライドの読み上げではなく、内容の補足・文脈付けに使う
Step 4: ナレーションテキストのルール
- 言語: 日本語
- 読み方: バージョン番号は「バージョン1.0.11」→「バージョン いってん ぜろ てん いちいち」のように自然な読みに
- トーン: ニュースキャスターのような明瞭でプロフェッショナルな読み上げ
- 長さ: 1ビートあたり1〜2文(長すぎない)
- 番号付け: 機能ごとに「1:」「2:」と番号を振る(「。」は
textSplit の区切り文字のため使わない)
- 字幕改行:
\n で字幕の表示行を制御する。1行あたり約25〜30文字を目安に、意味の切れ目で \n を入れる。\n は textSplit の区切り文字なので字幕分割ポイントになる
- 内容: release notes の詳細情報を元に、要約しつつわかりやすく
Step 5: テンプレートパラメータ
以下は固定値(テンプレート):
{
"$mulmocast": { "version": "1.1", "credit": "closing" },
"canvasSize": { "width": 1280, "height": 720 },
"speechParams": {
"speakers": {
"Presenter": {
"displayName": { "ja": "ナレーター" },
"voiceId": "shimmer",
"speechOptions": {
"instruction": "Speak clearly and professionally like a news announcer reading release notes. Use a neutral, informative tone with clear enunciation."
},
"provider": "openai"
}
}
},
"imageParams": { "provider": "openai", "images": {} },
"movieParams": { "provider": "mock", "model": "", "transition": { "type": "fade", "duration": 1 } },
"soundEffectParams": { "provider": "replicate" },
"textSlideParams": { "cssStyles": ["h3 {margin-left: 20px; margin-top: 20px}"] },
"captionParams": {
"lang": "ja",
"captionSplit": "estimate",
"textSplit": {
"type": "delimiters",
"delimiters": ["。", ".", ".", "!", "!", "?", "?", ";", ";", "、", ",", "\n"]
}
},
"audioParams": {
"padding": 0.3,
"introPadding": 1,
"closingPadding": 0.8,
"outroPadding": 1,
"bgm": { "kind": "path", "path": "../bgm/20251217031931-8c55b232.mp3" },
"bgmVolume": 0.1,
"audioVolume": 1,
"suppressSpeech": false
}
}
Step 6: JSON の組み立てと保存
テンプレートパラメータ + title + description + lang + beats を組み立て、以下に保存:
docs/release_notes/v<version>/release_v<version>_script.json
ファイル名ルール: バージョンのドットをアンダースコアに変換(例: 1.0.11 → release_v1_0_11_script.json)
Step 7: PDF ハンドアウトの生成
MulmoScript から PDF ハンドアウトを生成する。出力ディレクトリは -o オプションで指定すれば mulmo が自動作成するため、mkdir は不要。
npm install -g mulmocast@latest
mulmo pdf --pdf_mode handout docs/release_notes/v<version>/release_v<version>_script.json -o docs/release_notes/v<version>/output
ファイル名ルール: スクリプトのファイル名に合わせる(例: release_v1_0_11_script.json)
Step 8: PDF の確認後、日本語版動画の生成
PDF ハンドアウトの生成結果をユーザーに報告し、PDF が OK であれば動画を生成する。
mulmo movie docs/release_notes/v<version>/release_v<version>_script.json -o docs/release_notes/v<version>/output -l ja -c ja
生成後、JA タイムスタンプを抽出する(Step 11 で使用):
npx tsx .claude/skills/release-script/extract-timestamps.ts docs/release_notes/v<version>/output/release_v<version>_script_studio.json
Step 9: 英語版動画の生成
日本語版が OK であれば、英語版も生成する(MulmoCast の翻訳機能で自動翻訳される)。
mulmo movie docs/release_notes/v<version>/release_v<version>_script.json -o docs/release_notes/v<version>/output -l en -c en
注意: _studio.json は mulmo movie 実行ごとに上書きされる。そのため JA 生成後に JA タイムスタンプを読み取ってから EN を生成すること。
Step 10: 翻訳テキストの確認
英語版動画生成後、output/release_v<version>_script_lang.json を確認する。
MulmoCast の翻訳機能は「マルモキャスト」を誤訳することがある(例: 「MarmoCast」「MarmCast」)。以下を実行:
_lang.json を読み込む
- 「MulmoCast」以外の表記(
MarmoCast、MarmCast、MarumoCast 等)を検索
- すべて「MulmoCast」に置換する
- 置換した場合は英語版動画を再生成する
- 確定した EN 動画の
_studio.json から EN タイムスタンプを抽出する(再生成した場合はタイムスタンプが変わるため、必ず最終版から抽出すること):
npx tsx .claude/skills/release-script/extract-timestamps.ts docs/release_notes/v<version>/output/release_v<version>_script_studio.json
Step 11: タイムスタンプの作成(ビート単位)
Step 8 で抽出した JA タイムスタンプと Step 10 で抽出した EN タイムスタンプを、まずビート単位で書き出す。
タイムスタンプ抽出ルール:
_studio.json の beats 配列から各ビートの startAt(秒)を取得
- ビートのインデックスはスクリプトの
beats 配列と1対1対応
- タイトルスライド(2ビート構成)とクロージングスライド(2ビート構成)は最初のビートの
startAt を使用して1項目にまとめる
- 秒を
M:SS 形式に変換(例: 69.192s → 1:09)
- 各ビートに言語に応じたラベルを付ける(JA: 日本語、EN: 英語)
この段階では各ビートが 1 項目として残っている状態(粒度が細かい)。
Step 12: X 投稿構成に合わせた機能単位の集約
ビート単位のタイムスタンプを、X 投稿の構成(メインポスト + 各連投ポスト)に合わせて機能単位で集約する。docs/release_notes/v<version>/xpost_v<version>_draft.md を参照して、X 投稿の 1 ポスト = タイムスタンプ 1 項目になるように統合する。
集約ルール:
- X 投稿の 1 ポスト内で複数ビートに分かれている機能(例: モデル一覧が OpenAI/Replicate Image/Replicate Video の 3 ビートに分かれている場合)は、最初のビートの
startAt を使用して 1 項目にまとめる
- 機能名は X 投稿のセクションタイトルに合わせる(例: 「Now available / 新しいAIモデル」→ JA: 「新しいAIモデル」 / EN: 「New AI models」)
- 細かい補足ビート(生成サンプル、プロジェクト上書き等)は親機能の項目に吸収する
- 結果として X 投稿のポスト数とほぼ同数のタイムスタンプ行になる
集約後の最終結果を docs/release_notes/v<version>/timestamps_v<version>.md に保存する。
フォーマット例(X 投稿が 4 ポスト構成のリリースの場合):
## JA Timestamps
0:00 はじめに
0:16 Azure OpenAIサービス対応
0:42 Vertex AI 設定
1:08 おわりに
## EN Timestamps
0:00 Introduction
0:14 Azure OpenAI Service
0:38 Vertex AI Settings
1:02 Thank you
このファイルは /release-youtube スキルが参照する。
Step 13: 完了報告
生成した MulmoScript のファイルパス、ビート数、PDF・動画(日本語版・英語版)の出力先を報告する。
重要なルール
- 画像は
kind: path で参照 — ローカルスクリーンショットを使用(X の URL は使わない)
- ナレーションは日本語 — TTS 用のテキストとして自然な日本語で記述
- テンプレートパラメータは原則固定 — 変更が必要な場合はユーザーに確認
- BGM パスが動作しない場合は調整 — MulmoCast のパス解決に依存するため
- ユーザー確認は不要 — アプリ上でブラッシュアップする前提のため、生成後そのまま保存する
- ビート構成の変更時は全体を通して確認 — 部分修正の積み重ねは image / text / id の不整合を生みやすい。構成変更が入ったら beats 配列全体を読み直し、画像参照・ナレーション内容・id の整合性を一括で確認すること