mcpField
P
podcast-generation

podcast-generation

github.com/sickn33创意与媒体48.7k73 次安装1 天前更新
代码仓库

关于 podcast-generation

使用 Azure OpenAI's Realtime API 将文本生成旁白音频的 Skill。它介绍通过 WebSocket 收集音频和转录片段、将 PCM 转为 WAV,并准备可供播放的 Base64 音频。

主要功能

  1. 01Azure OpenAI Realtime 工作流
  2. 02通过 WebSocket 生成音频
  3. 03收集音频与转录片段
  4. 04将 PCM 转为 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 支持列表。在将字节解释为 24kHz 有符号 16 位单声道数据之前,请显式配置 PCM 输出;拒绝不完整或为空的输出。 示例未包含强制性的总生成超时(例如 60 秒)、单个事件及累计音频/文本限制(例如 32 MiB)、取消/关闭路径和费用配额;在处理请求前,请实现这些措施。单独收到 response.done 事件并不表示成功。不要将部分输出存储为完整叙述。

按租户授权源对象,以及音频生成、列表和流式传输的所有权;ID 不能作为访问控制。数据库方法/模型/路由、设置和前端 API 都是应用适配层,并非随附的实现。将源文本视为数据,保留来源归属,验证叙述准确性,并在将私人文本发送到 Azure 或发布合成语音前取得权利/同意。未经许可,绝不要冒充真人;在需要时披露语音为生成内容。密钥仅存储在后端;音频/转录文本应私密保存并设置保留期限。模型生成的文本不是 HTML。前端的播放/暂停功能需要实际的暂停处理、Promise 错误处理、通过 finally 重置加载状态、URL 撤销和资源清理;React 示例未包含这些控制。

PCM 辅助脚本用法:python3 <skill-dir>/scripts/pcm_to_wav.py input.pcm output.wav 会拒绝覆盖文件和不完整帧;它不会检测任意字节是否确实为所声明的 PCM 格式。

评论

支持 Markdown