mit einem Klick
release-script
// リリースノートとX投稿ドラフトからMulmoScript(リリースノート動画用)を生成する。/release-xpost 完了後に実行。
// リリースノートとX投稿ドラフトからMulmoScript(リリースノート動画用)を生成する。/release-xpost 完了後に実行。
X投稿ドラフトから Discord 向けメッセージを生成し webhook で投稿する。/release-xpost 完了後に実行。
リリースノート作成。前回リリース以降の全PRを調査し、PR要約とリリースノートを生成する。
リリースワークフロー全体をガイド。ドラフト一括作成 → リリース PR マージ → 公開アクション一括実行 → 後処理の順に進行。
MulmoScript から Zenn 記事を生成する。/release-script 完了後に実行。
QA テストスイートを作成する。Playbook の知見を活用して CDP 経由の Playwright テストを生成。
YouTube アップロード用のメタデータ(タイトル・説明文)を生成する。/release-script 完了後に実行。
| 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/ にスクリーンショットが保存されていること以下を読み込む:
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/ — スクリーンショット一覧過去のスクリプトをテンプレートとして参照する:
ls docs/release_notes/v*/release_v*_script.json
最新のスクリプトを読み込み、パラメータ部分($mulmocast 〜 audioParams)をテンプレートとして使用する。
xpost draft の構成に沿って beats を作成する:
バージョン番号にドットが含まれるため、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"
}
}
xpost draft の各ポスト(メインポスト + 連投ポスト)から:
images/ 内のスクリーンショットを kind: path で参照画像マッピングルール:
画像ファイル名のプレフィックス {ポスト番号}-{画像番号}_ でビートに自動対応:
01-* → メインポストのビート02-* → 連投1のビート03-* → 連投2のビート(以降同様)プレフィックスがない旧形式の画像は、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 のデリミタ(.、,)を含む文字列がある場合、その部分でキャプションが意図せず分割される。これを回避するため、デリミタを含む部分を独立ビートに分離する:
// ビート1: 導入文(デフォルトの captionParams)
{
"speaker": "Presenter",
"text": "1:TTS読み上げ速度オプションを追加しました",
"id": "tts-speed",
"image": { "type": "image", "source": { "kind": "path", "path": "images/01-01_speed.png" } }
}
// ビート2: 数値を含む部分(caption分割を無効化、同じ画像を参照)
{
"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" }
}
// ビート3: 続きの文(デフォルトの captionParams、同じ画像を参照)
{
"speaker": "Presenter",
"text": "読み上げ速度は設定画面から変更できます",
"id": "tts-speed-usage",
"image": { "type": "beat", "id": "tts-speed" }
}
ポイント:
captionParams で captionSplit: "none" + textSplit: { type: "none" } を設定image: { type: "beat", id: "..." } で同じ画像を参照タイトルスライドと同様に、バージョン番号を含む文を分離する。
ビート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"
}
}
機能紹介・告知用 Markdown スライドを設計する際の指針。
textSplit の区切り文字のため使わない)\n で字幕の表示行を制御する。1行あたり約25〜30文字を目安に、意味の切れ目で \n を入れる。\n は textSplit の区切り文字なので字幕分割ポイントになる以下は固定値(テンプレート):
{
"$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
}
}
テンプレートパラメータ + title + description + lang + beats を組み立て、以下に保存:
docs/release_notes/v<version>/release_v<version>_script.json
ファイル名ルール: バージョンのドットをアンダースコアに変換(例: 1.0.11 → release_v1_0_11_script.json)
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)
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
日本語版が 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 を生成すること。
英語版動画生成後、output/release_v<version>_script_lang.json を確認する。
MulmoCast の翻訳機能は「マルモキャスト」を誤訳することがある(例: 「MarmoCast」「MarmCast」)。以下を実行:
_lang.json を読み込むMarmoCast、MarmCast、MarumoCast 等)を検索_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 8 で抽出した JA タイムスタンプと Step 10 で抽出した EN タイムスタンプを、まずビート単位で書き出す。
タイムスタンプ抽出ルール:
_studio.json の beats 配列から各ビートの startAt(秒)を取得beats 配列と1対1対応startAt を使用して1項目にまとめるM:SS 形式に変換(例: 69.192s → 1:09)この段階では各ビートが 1 項目として残っている状態(粒度が細かい)。
ビート単位のタイムスタンプを、X 投稿の構成(メインポスト + 各連投ポスト)に合わせて機能単位で集約する。docs/release_notes/v<version>/xpost_v<version>_draft.md を参照して、X 投稿の 1 ポスト = タイムスタンプ 1 項目になるように統合する。
集約ルール:
startAt を使用して 1 項目にまとめる集約後の最終結果を 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 スキルが参照する。
生成した MulmoScript のファイルパス、ビート数、PDF・動画(日本語版・英語版)の出力先を報告する。
kind: path で参照 — ローカルスクリーンショットを使用(X の URL は使わない)