mcpField
P
podcast-generation

podcast-generation

github.com/sickn33クリエイティブ・メディア48.7k73 回インストール1 日前に更新
リポジトリ

podcast-generation について

Azure OpenAI's Realtime APIでテキストからナレーション音声を生成するスキルです。WebSocketで音声と文字起こしを受信し、PCMをWAVに変換して、再生用のBase64音声を準備する手順を示します。

主な機能

  1. 01Azure OpenAI Realtimeのワークフロー
  2. 02WebSocketによる音声生成
  3. 03音声と文字起こしの収集
  4. 04PCMからWAVへの変換
  5. 05再生用Base64音声の準備

活用シーン

  1. 01テキストをナレーション音声に変換
  2. 02生成音声をフロントエンドに返す
  3. 03生成PCMデータをWAVに変換

インストール

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

$npx skills add https://github.com/sickn33/agentic-awesome-skills --skill podcast-generation

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

同梱ファイル

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

UPSTREAM-NOTICE.md
UPSTREAM-LICENSE.txt
references/
architecture.md
code-examples.md
scripts/
pcm_to_wav.py

詳細

同梱された上流サポートファイル

サポートファイルはスキル相対パスに含まれています。固定されたソース、ライセンス、ハッシュ、インポート時の変更については、UPSTREAM-NOTICE.md を参照してください。

GPT Realtime Mini でポッドキャストを生成する

Azure OpenAI の Realtime API を使用して、テキストコンテンツから実際の音声ナレーションを生成します。

クイックスタート

  1. Realtime API 用の環境変数を設定します
  2. WebSocket 経由で Azure OpenAI Realtime エンドポイントに接続します
  3. テキストプロンプトを送信し、PCM 音声チャンクと文字起こしを収集します
  4. PCM を WAV 形式に変換します
  5. 再生用に、Base64 エンコードされた音声をフロントエンドに返します

環境設定

AZURE_OPENAI_AUDIO_API_KEY=your_realtime_api_key
AZURE_OPENAI_AUDIO_ENDPOINT=https://your-resource.cognitiveservices.azure.com
AZURE_OPENAI_AUDIO_DEPLOYMENT=gpt-realtime-mini

注:エンドポイントに /openai/v1/ を含めないでください。ベース URL のみを指定します。

主なワークフロー

バックエンドでの音声生成
from openai import AsyncOpenAI
import base64

# Convert HTTPS endpoint to WebSocket URL
ws_url = endpoint.rstrip("/").replace("https://", "wss://", 1) + "/openai/v1"

client = AsyncOpenAI(
    websocket_base_url=ws_url,
    api_key=api_key
)

audio_chunks = []
transcript_parts = []

async with client.realtime.connect(model=deployment_name) as conn:
    # Configure for audio-only output
    await conn.session.update(session={
        "type": "realtime",
        "audio": {"output": {"voice": voice_name, "format": {"type": "audio/pcm", "rate": 24000}}},
        "output_modalities": ["audio"],
        "instructions": "You are a narrator. Speak naturally."
    })
    
    # Send text to narrate
    await conn.conversation.item.create(item={
        "type": "message",
        "role": "user",
        "content": [{"type": "input_text", "text": prompt}]
    })
    
    await conn.response.create()
    
    # Collect streaming events
    async for event in conn:
        if event.type == "response.output_audio.delta":
            audio_chunks.append(base64.b64decode(event.delta))
        elif event.type == "response.output_audio_transcript.delta":
            transcript_parts.append(event.delta)
        elif event.type == "error":
            raise RuntimeError("Realtime service error; inspect redacted private diagnostics")
        elif event.type == "response.done":
            if event.response.status != "completed":
                raise RuntimeError("Incomplete audio response")
            break

# Convert PCM to WAV (see scripts/pcm_to_wav.py)
pcm_audio = b''.join(audio_chunks)
wav_audio = pcm_to_wav(pcm_audio, sample_rate=24000)
フロントエンドでの音声再生
// Convert base64 WAV to playable blob
const base64ToBlob = (base64, mimeType) => {
  const bytes = atob(base64);
  const arr = new Uint8Array(bytes.length);
  for (let i = 0; i < bytes.length; i++) arr[i] = bytes.charCodeAt(i);
  return new Blob([arr], { type: mimeType });
};

const audioBlob = base64ToBlob(response.audio_data, 'audio/wav');
const audioUrl = URL.createObjectURL(audioBlob);
const player = new Audio(audioUrl);
player.onended = () => URL.revokeObjectURL(audioUrl);
player.onerror = () => URL.revokeObjectURL(audioUrl);
// Invoke from a user gesture and handle autoplay rejection/teardown.
player.play().catch(() => URL.revokeObjectURL(audioUrl));

過去の音声の例(デプロイ環境でのサポートを確認してください)

音声特徴
alloyニュートラル
echo温かみがある
fable表現豊か
onyx深みがある
nova親しみやすい
shimmer明瞭

Realtime API イベント

  • response.output_audio.delta - Base64 音声チャンク
  • response.output_audio_transcript.delta - 文字起こしテキスト
  • response.done - 生成完了
  • error - event.error.message を使って処理します

音声形式

  • 入力:テキストプロンプト
  • 出力:PCM 音声(24kHz、16 ビット、モノラル)
  • 保存形式:Base64 エンコードされた WAV

参考資料

  • アーキテクチャ全体:スタック設計の詳細は references/architecture.md を参照してください
  • コード例:連携方法の概要は references/code-examples.md を参照してください
  • PCM 変換:音声形式の変換には scripts/pcm_to_wav.py を使用してください

使用する場合

このスキルは、概要に記載されたワークフローまたは操作を実行する場合に適用できます。

制限事項

  • 上記の範囲に明確に一致するタスクに限り、このスキルを使用してください。
  • 出力を、環境固有の検証、テスト、または専門家によるレビューの代わりとして扱わないでください。
  • 必要な入力、権限、安全上の境界、または成功条件が不足している場合は、作業を止めて確認してください。

生成に関する制約

未実行の SDK/サービスの例では、デプロイ名、利用可能な音声、GA とプレビューの別、 セッション/認証形式、SDK のバージョンを、実際の Azure リソースに合わせる必要があります。音声の表は、現在の Realtime サポート一覧ではありません。明示的に PCM 出力を設定してから、バイト列を 24kHz、符号付き 16 ビット、モノラルとして解釈してください。不完全または空の出力は拒否してください。 例では、必須の生成全体のタイムアウト(例:60 秒)、イベントごとおよび累積した音声/テキストの上限(例:32 MiB)、キャンセル/クローズ処理、利用料金の上限を省略しています。リクエストを処理する前に、これらを実装してください。response.done イベントだけでは成功を意味しません。不完全な出力を、完成したナレーションとして保存しないでください。

テナントごとに、ソースオブジェクトと、音声生成/一覧表示/ストリーミングの所有権の両方を認可してください。ID はアクセス制御ではありません。DB のメソッド/モデル/ルート、設定、フロントエンド API はアプリケーション側のアダプターであり、同梱された実装ではありません。ソーステキストはデータとして扱い、出典を維持し、ナレーションの正確さを確認してください。また、非公開のテキストを Azure に送信したり合成音声を公開したりする前に、権利と同意を取得してください。許可なく実在の人物になりすましてはいけません。必要な場合は、生成音声であることを開示してください。キーはバックエンドのみで保管し、音声と文字起こしは保持期間の上限を設けて非公開で保管してください。モデルが生成したテキストは HTML ではありません。フロントエンドの再生/一時停止には、実際の一時停止処理、Promise のエラー処理、finally による読み込み状態のリセット、URL の解放、ティアダウンが必要です。React の例ではこれらの制御を省略しています。

PCM ヘルパーの使用方法:python3 <skill-dir>/scripts/pcm_to_wav.py input.pcm output.wav は、上書きと不完全なフレームを拒否します。ただし、任意のバイト列が宣言された PCM 形式であるかどうかは検出しません。

コメント