mcpField
B
blog-audio

blog-audio

github.com/agricidanielクリエイティブ・メディア2.6k2.6k 回インストール2 週間前に更新
リポジトリ

blog-audio について

blog-audio は、ブログ記事を Gemini TTS で音声化するスキルです。短い要約、全文朗読、2人の対話形式に対応し、音声の選択と HTML5 埋め込み方法も扱います。

主な機能

  1. 01要約・全文・対話の各モード
  2. 02Gemini TTS による音声生成
  3. 03プリセット音声の選択
  4. 04長文の分割とチャンク数制限
  5. 05HTML5 音声埋め込みの案内

活用シーン

  1. 01記事の短い音声要約の作成
  2. 02全文を朗読音声として提供
  3. 032人のポッドキャスト風音声の制作
  4. 04ブログへの音声プレーヤー追加

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/agricidaniel/claude-blog --skill blog-audio

インストール後、Claude Code で/blog-audioを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
voices.md
scripts/
__init__.py
generate_audio.py
requirements.lock
requirements.txt
run.py
runtime_paths.py
setup_environment.py

詳細

ブログ音声:ブログ記事向け Gemini TTS ナレーション

以下のバンドルパスでは、ホスト側の Markdown 置換で ${CLAUDE_SKILL_DIR} を使用します。 これはエクスポートされたシェル変数ではありません。実行前にパスを解決し、パスを引用符で囲み、絶対パスでないオーバーライドは拒否してください。${CLAUDE_SKILL_DIR}/../blog/references から解決した blog_reference_root、${CLAUDE_SKILL_DIR}/../blog/templates から解決した blog_template_root、および必要な兄弟ルートをエージェントに渡してください。 プロジェクトのコンテキストを読み込む前に、メインリファレンスの orchestration-details.md を読み込んでください。下流のエージェントには、そのヘルパーで囲まれた出力のみを渡してください。

Google の Gemini TTS を使用して、ブログ記事のプロフェッショナルな音声ナレーションを生成します。 モードは3つあります。要約(200~300語の音声向け概要)、記事全文の読み上げ、2人の話者によるポッドキャスト形式の対話です。Gemini 3.8 Flash TTS では30種類の事前構築済み音声と130以上の言語に対応し、Flash-Lite では100以上の言語に対応しています(Google の音声生成ページ、2026-10-12確認)。HTML5 埋め込み形式で出力します。

コストと同意の確認(必須、最初に読む)

このスキルはユーザーの Google AI クレジットを消費し、音声ファイルを書き込みます。

  • 消費するもの: テキストチャンクごとに、有料の Gemini TTS 呼び出しを1回行います。長いテキストはチャンクに分割されるため、全文読み上げでは複数回の呼び出しが必要です。スクリプトの --max-chunks フラグで1回の実行あたりのチャンク数を制限できます(デフォルトは12)。ユーザーに新たな最悪ケースの費用を伝えずに、上限を引き上げてはいけません。
  • 費用の根拠: 音声出力トークンは音声1秒あたり25トークンです。2026-10-12時点で、https://ai.google.dev/gemini-api/docs/pricing には gemini-3.8-flash-tts が音声トークン100万個あたり$9.00(10秒あたり約$0.00225)、gemini-3.8-flash-lite-tts が$6.00(10秒あたり約$0.0015)と記載されており、いずれも2026-12-31までの価格です。2027-01-01からは記載価格が上がります。まず --dry-run --json を実行して、スクリプトによる見積もりを確認してください。
  • 書き込むもの: audio/(または --output)内の音声ファイル、およびセットアップ時のみ、管理対象の .venv を書き込みます。
  • 同意: セッション中に最初の有料呼び出しを行う前に、モード、モデル、チャンク数、推定費用を伝え、明示的な同意を待ってください。同意が有効なのはその実行に限られます。ブログ記事の執筆は音声生成への同意を意味しません。
  • 上限のない支出は禁止: 上限を超えて有料呼び出しを再試行したり、ループしたりしてはいけません。一時的なエラーの場合は1回だけ再試行し、その後は報告してください。
  • スキップ条件: ユーザーが同意しない場合、キーがない場合、またはセットアップが済んでいない場合はスキップし、オーケストレーターの「フォールバックとスキップ」サマリー用に「Audio: no API key set, skipped」のような1行のみを返してください。

クイックリファレンス

コマンド説明
/blog audio generate <file>ブログ記事の音声ナレーションを生成します
/blog audio voices利用可能な音声とその特徴を表示します
/blog audio setupGemini TTS の API キーを確認・設定します

前提条件

  • Python 3.11 以降。管理対象の venv は明示的なセットアップ操作で管理します
  • GOOGLE_AI_API_KEY または GEMINI_API_KEY 環境変数(GOOGLE_AI_API_KEY は blog-image が使用するキーです。音声スクリプトではどちらも使用できます)
  • FFmpeg(WAV から MP3 への変換に使用。不在の場合は WAV にフォールバックします)。暗黙にインストールしてはいけません。ユーザーに伝え、インストールはユーザーに任せてください

永続ランタイムディレクトリ

CLAUDE_BLOG_RUNTIME_DIR を指定すると、信頼できる絶対パスの永続ルートを任意で選択できます。この連携では <root>/blog-audio/.venv を使用します。NotebookLM もライブラリ、認証情報、ブラウザーの状態に <root>/blog-notebooklm/data を使用します。この設定がない場合は、既存のスキルローカルのデフォルトが引き続き使用されます。Google の共有認証情報設定/トークンのパスは変更されません。状態が自動的にコピーまたは移行されることはなく、通常の実行でセットアップが行われることもありません。

既存の検証済みのオペレーター設定は保持してください。設定がないプラグインでは、セットアップ時とその後のすべてのランナー呼び出し時に、ホストによって置換される ${CLAUDE_PLUGIN_DATA}/claude-blog-runtime のパスを明示的に渡してください。これは Markdown の置換であり、エクスポートされたシェル変数ではありません。解決済みの絶対パスになってからのみ実行してください。シングルクォートで囲むと、未解決のプレースホルダーが文字どおりに保持されるため、別のシェルパスに展開されず、検証で拒否されます。

CLAUDE_BLOG_RUNTIME_DIR='${CLAUDE_PLUGIN_DATA}/claude-blog-runtime' python3 "${CLAUDE_SKILL_DIR}/scripts/setup_environment.py" --check --json
CLAUDE_BLOG_RUNTIME_DIR='${CLAUDE_PLUGIN_DATA}/claude-blog-runtime' python3 "${CLAUDE_SKILL_DIR}/scripts/run.py" generate_audio.py --help

--check を付けずに明示的にセットアップした場合にのみ、依存関係がインストールされます。スタンドアロンユーザーは、絶対パスのランタイムルートを明示的に選択しない限り、デフォルトを引き続き使用します。相対パス、未解決のパス、またはリンクされた管理対象サブディレクトリは、フェイルクローズで拒否されます。ルートを変更すると別の状態が選択されますが、古いルートの移行やクリーンアップが許可されることはありません。プラグインの永続データには、ホストのアンインストール時の保持ルールが適用されます。引き続き必要な場合は、アンインストール時に明示的に保持してください。

インストール済みの run.py ラッパーを使用する

BLOG_SKILLS_DIR="${CLAUDE_BLOG_SKILLS_DIR:-${CLAUDE_SKILL_DIR}/..}"
case "$BLOG_SKILLS_DIR" in /*) ;; *) echo "ERROR: skills dir must be absolute" >&2; exit 1 ;; esac
AUDIO_RUN="$BLOG_SKILLS_DIR/blog-audio/scripts/run.py"
python3 "$AUDIO_RUN" generate_audio.py --text "..." --voice Charon --model flash38 --json

通常の generate コマンドと voices コマンドは、変更を加えずに機能を確認します。管理対象環境が存在しない場合は、セットアップが必要であることを示す結果を返します。.venv の作成や依存関係のインストールを行えるのは /blog audio setup だけです。現在のプロジェクトの scripts/ ディレクトリからラッパーを解決しないでください。

API キーの確認(ゲートパターン)

音声を生成する前に、API キーを確認します(スクリプトは最初に GOOGLE_AI_API_KEY、次に GEMINI_API_KEY を読み取ります)。

if [ -n "${GOOGLE_AI_API_KEY:-}" ] || [ -n "${GEMINI_API_KEY:-}" ]; then echo "API key is set"; else echo "API key is not set"; fi
  • いずれかが設定されている場合:同意ゲートに進み、その後生成します
  • どちらも設定されていない場合:ユーザーに次のように案内します: 「音声の生成には Google AI API キーが必要です。https://aistudio.google.com/apikey で取得してください。 その後、シェルでエクスポートします:export GOOGLE_AI_API_KEY=your-key(または GEMINI_API_KEY)。 /blog image で使用するキーと同じものを使用できます。」
  • 内部から呼び出された場合(blog-write から):キーが設定されていなければ、呼び出し元の最終サマリー用に、何を・なぜスキップしたかを示す1行のメモを返します。執筆ワークフローを妨げないでください。

セットアップ

/blog audio setup の場合:

  1. 環境内に GOOGLE_AI_API_KEY または GEMINI_API_KEY が設定されていることを確認します
  2. blog-image がプロジェクトの .mcp.json を使用している場合は、参照されている環境変数がエクスポートされていることを確認します
  3. 設定されていない場合は、https://aistudio.google.com/apikey をユーザーに案内します
  4. ユーザーの承諾を得て、管理対象環境を作成または更新します。依存関係をインストールするのはこの手順だけです: python3 "$BLOG_SKILLS_DIR/blog-audio/scripts/setup_environment.py" (インストールせずに確認するには --check --json を追加します)
  5. ドライラン(API 呼び出しなし)で検証します: python3 "$AUDIO_RUN" generate_audio.py --text "Test" --dry-run --json

音声の選択

/blog audio voices の場合:

${CLAUDE_SKILL_DIR}/references/voices.md を読み込み、音声カタログをユーザーに提示します。

ユーザーに希望する音声を尋ねるか、コンテンツの種類に基づいて推奨します:

  • 記事のナレーション:Charon(情報豊富)または Sadaltager(知識豊富)
  • チュートリアル/ハウツー:Achird(親しみやすい)または Sulafat(温かみのある)
  • ニュース/分析:Rasalgethi(情報豊富)または Schedar(落ち着いた)
  • ライフスタイル/ウェルネス:Aoede(軽やか)または Vindemiatrix(穏やか)
  • 対話のホスト:Puck(陽気)または Laomedeia(陽気)
  • 対話の専門家:Kore(毅然とした)または Charon(情報豊富)

生成ワークフロー

/blog audio generate <file> の場合:

ステップ 1:ブログ記事を読む

ファイルを読み、次の内容を抽出します:

  • タイトル(H1 またはフロントマターから)
  • 全文(Markdown の本文)
  • おおよその単語数
ステップ 2:モードを選択する

ユーザーに確認するか(または --mode が指定されている場合は自動で選択します):

モード使用する場面出力
Summary音声で手短に概要を伝える(1~2 分)200~300 語の読み上げ用要約
Full全文を読み上げる(5~15 分)記事全体を自然な話し言葉にしたもの
Dialogueポッドキャスト形式(3~8 分)記事についての 2 人の会話
ステップ 3:テキストを準備する

Claude がテキストを準備し、スクリプトは TTS のみを実行します。

Summary モード: 記事の 200~300 語の読み上げ用要約を書きます。ルール:

  • 書き言葉ではなく、自然な話し言葉にします
  • 記事の主要な発見や回答から始めます
  • 主なポイントを 3~5 個取り上げます
  • 実践的なアドバイスで締めくくります
  • Markdown、「この記事では……」などの前置き、メタ的なコメントは使いません
  • 「ここで重要なのは……」「重要な発見は……」など、会話調のつなぎ表現を使います

Full モード: Markdown の内容を、自然に読み上げられるテキストに整えます:

  • 見出しは自然なつなぎ表現にします(「次に、……を見てみましょう」など)
  • リンクは通常のテキストにします(URL を削除し、アンカーテキストは残します)
  • 画像やグラフは省略するか、簡単に説明します(「データが示すように……」など)
  • コードブロックは口頭で説明します(「コードでは for ループを使って……」など)
  • リストは自然な文章に直します
  • フロントマター、スキーママークアップ、HTML タグは削除します
  • 短い導入を追加します:「これは [タイトル] です。[日付] に公開されました。」

Dialogue モード: 記事についての 2 人の会話スクリプトを書きます:

  • Speaker1 = ホスト(好奇心があり、よい質問をします)
  • Speaker2 = 専門家(詳しく、わかりやすく回答します)
  • 各行を次の形式にします:Speaker1: ここで重要なポイントは何ですか?
  • 記事の主なポイントを会話調で取り上げます
  • 15~25 回のやり取りにします(約 3~8 分の音声になります)
  • 堅苦しくならないようにします(「まさにそのとおりですね」は、「研究が示すとおりです」より自然です)
ステップ 4:音声を選択する

ユーザーが音声を選択している場合は、それを使用します。選択していない場合は、モードに応じて推奨します:

  • Summary/Full:デフォルトで Charon(情報提供向け)を使用します
  • Dialogue:デフォルトで Puck(ホスト)+ Kore(専門家)を使用します
ステップ 5:音声を生成する

準備したテキストを作業ディレクトリ内のファイルに書き込み、次を呼び出します:

# Single voice (summary or full mode)
python3 "$AUDIO_RUN" generate_audio.py \
  --text-file blog_audio_prepared.txt \
  --voice Charon \
  --model flash38 \
  --output audio/post-slug.mp3 \
  --json

# Two voices (dialogue mode)
python3 "$AUDIO_RUN" generate_audio.py \
  --text-file blog_audio_dialogue.txt \
  --voice Puck \
  --voice2 Kore \
  --model flash38 \
  --output audio/post-slug-dialogue.mp3 \
  --json

モデルの選択(明示的な 3.8 ID を使用):

  • flash38:gemini-3.8-flash-tts。安定した汎用モデルで、上記の例でも使用されています。130 以上の言語に対応しています。
  • flash-lite38:gemini-3.8-flash-lite-tts。安定した低価格モデルです。100 以上の言語に対応していますが、フィンランド語やタイ語など、一部の言語は Flash のみで利用できます。
  • 従来のエイリアス flash、flash31、pro、legacy-flash25、legacy-pro25 は、gemini-3.1-flash-tts-preview、gemini-2.5-pro-preview-tts、gemini-2.5-flash-preview-tts に対応しています。Google の非推奨化ページ(2026-10-12 確認)では、最も早い提供終了日が 2026-11-17 と記載されています。そのため、新しい作業には使用しないでください。利用料金を発生させる前に、--dry-run --json の出力で解決後のモデル ID を確認してください。

3.8 のエイリアスには、オフラインでの SDK スキーマ検証と WAV 解析チェックがあります。認証後の利用可否と音声品質については、引き続きプロバイダーでのテストが必要です。3.8 では、読み上げの指示を埋め込まず、逐語的なトランスクリプトを渡してください。Dialogue では、明示的な Speaker1: と Speaker2: の行を使用してください。ヘルパーが話者を推測することはありません。費用の見積もりには、12 月 31 日までの確認済みの 2026 年料金と、1 月 1 日以降に適用される公表済みの 2027 年料金が使われます。あくまで見積もりであり、請求額を保証するものではありません。

ステップ 6:結果を提示する

ユーザーに次の内容を提示します:

  1. ファイルパス:音声の保存先
  2. 長さ:「3:42」など、人が読みやすい形式
  3. 埋め込みコード:そのまま貼り付けられる HTML5 音声タグ
  4. 費用:API 利用料金の見積もり
  5. 配置の提案:ブログ記事内で埋め込みを挿入する場所

埋め込みガイド

標準 HTML(Hugo、Jekyll、静的サイト)
<audio controls preload="metadata">
  <source src="audio/post-slug.mp3" type="audio/mpeg">
  Your browser does not support the audio element.
</audio>
MDX(Next.js、Gatsby)
<audio controls preload="metadata">
  <source src="/audio/post-slug.mp3" type="audio/mpeg" />
</audio>
WordPress
[audio src="audio/post-slug.mp3"]
配置

音声プレーヤーは、導入部の後(最初の H2 の下)、または記事の最上部に「この記事を聴く」や「音声版」というラベルを付けて挿入します。

内部 API(blog-write 用)

blog-write から内部的に呼び出される場合:

入力:

  • text:準備済みのテキスト(Claude によるクリーニング済み)
  • voice:音声名(デフォルト:Charon)
  • voice2:対話用の 2 つ目の音声(任意)
  • model:flash38(新しい作業でのデフォルト)または flash-lite38。レガシーエイリアス(flash、flash31、pro、legacy-*)は、早ければ 2026-11-17 に終了します
  • output_path:ファイルの保存先

出力:

### Audio Narration
- **Path:** /path/to/audio/post-slug.mp3
- **Duration:** 3:42
- **Voice:** Charon
- **Embed:** `<audio controls preload="metadata"><source src="audio/post-slug.mp3" type="audio/mpeg"></audio>`

適切なフォールバック: GOOGLE_AI_API_KEY と GEMINI_API_KEY のどちらも設定されていない場合、またはユーザーがコスト確認を拒否した場合は、エラーを返さず直ちに戻り、呼び出し元の最終サマリー用に 1 行のスキップ通知を返します。音声なしで執筆ワークフローを続行します。音声生成が利用できないために blog-write を停止してはなりません。

エラー処理

エラー解決方法
API キーが設定されていない(GOOGLE_AI_API_KEY または GEMINI_API_KEY)https://aistudio.google.com/apikey でキーを取得します
FFmpeg が見つからないWAV 出力にフォールバックします。ユーザーに伝え、代わりにインストールしてはなりません。
レート制限待ってから再試行します。https://aistudio.google.com/rate-limit で制限を確認します
テキストが長すぎる(入力トークン数が 8,192 超)約 7,800 トークンごとにセクションに分割します。スクリプトは準備済みテキストをチャンクに分割して結合し、1 回の実行につき --max-chunks(デフォルトは 12)まで処理します。上限を超えた場合は停止し、上限を引き上げる前にユーザーに確認します
不明な音声名/blog audio voices を実行して有効なオプションを確認します
API エラーキーの有効性とモデルの利用可否を確認します
API キーがない(内部呼び出し)1 行のスキップ通知を返します。執筆ワークフローは続行し、その旨を報告します

リファレンスドキュメント

必要に応じて読み込みます。起動時にすべて読み込まないでください:

  • ${CLAUDE_SKILL_DIR}/references/voices.md:全 30 種類の音声カタログ、コンテンツの種類ごとの推奨音声、対話向けの組み合わせ

コメント