CopilotKit LangGraph 语音演示 sample.wav 样本音频生成指南:免麦克风跑通语音转录流程
【免费下载链接】CopilotKitThe Frontend Stack for Agents & Generative UI. React, Angular, Mobile, Slack, and more. Makers of the AG-UI Protocol项目地址: https://gitcode.com/GitHub_Trending/co/CopilotKit
导读
/demos/voice是 CopilotKit 仓库中 langgraph-fastapi 集成示例(showcase/integrations/langgraph-fastapi)内置的语音输入演示页。为了让这一演示在无人声录制、无麦克风权限的环境下依然可以完整验证"语音 → 转录 → 对话"的端到端流程,仓库要求在 public/demo-audio/ 目录下放置一个特定规格的 WAV 音频文件sample.wav。读完本文,你将掌握该样本音频的规格要求、三大主流平台(macOS / Linux / Windows)的本地生成命令、内容约束背后的 QA 与 E2E 断言逻辑,以及它在前端渲染层与运行时转录服务中的实际调用位置。
一、样本音频在语音演示中的定位
语音演示页/demos/voice的核心思路是:在不申请麦克风权限的前提下,让整条"音频 → 转录文本 → 发送给 Agent"的链路可复现。sample.wav正是这条链路的确定性输入。
按照该目录下 README.md 的说明:
- 该文件被命名为
sample.wav,体积要求小于 100KB; - 演示页会在客户端获取这段音频,并将其 POST 到转录端点(transcription endpoint),从而避免依赖麦克风权限即可触发转录流程。
需要说明的是,从当前源码看,演示页的用户交互已经演进为双通道设计:默认由<CopilotChat />渲染的麦克风按钮走真实的MediaRecorder录音 +/transcribe转录路径;而页面底部的 "Try a sample audio" 按钮则是一个确定性的测试/演示辅助控件,点击后同步注入固定文案到输入框,不经过音频抓取与/transcribe往返(详见下文第四节)。因此sample.wav在当前实现中主要承担"规范样本音频"的角色——它定义了演示对外承诺的音频内容与格式基线,并为需要真实转录的路径(麦克风、手动 QA 清单 qa/voice.md 中提及的qa/voice.md)提供标准素材。
二、样本音频的硬性规格:16kHz 单声道、3–5 秒、<100KB
原文档对sample.wav的规格要求非常明确,这也是生成时必须满足的验收标准:
| 规格项 | 要求值 | 说明 |
|---|---|---|
| 采样率 | 16kHz(16000 Hz) | 与常见 ASR 引擎(如 Whisper)的输入采样率对齐,过低会损失语音特征,过高则徒增体积 |
| 声道 | 单声道(mono) | 转录场景通常只需单声道,双声道会成倍增大文件体积 |
| 时长 | 3–5 秒 | 覆盖完整一句话的发音,又不至于让文件超限 |
| 体积 | < 100KB | 客户端抓取与上传的硬性上限 |
| 文件格式 | WAV | 未压缩 PCM WAV 为佳,兼容性最广 |
体积约束是相互关联的:16kHz 单声道 PCM 编码下,每秒数据量约为 32000 字节(16000 样本/秒 × 16bit/样本 ≈ 31.25KB/s),3–5 秒的录音换算后恰好在 100KB 量级附近,这正是规格设计自洽之处。
三、三大平台生成命令(可直接复制运行)
原文档提供了 macOS、Linux、Windows 三条生成路径,均为系统自带或常见工具,无需额外安装重型依赖:
macOS
say -o sample.aiff "What is the weather in Tokyo?" && ffmpeg -i sample.aiff -ar 16000 -ac 1 sample.wav先用系统内置的say语音合成器生成 AIFF,再通过ffmpeg转码为 16kHz(-ar 16000)、单声道(-ac 1)的 WAV。若未安装ffmpeg,可先brew install ffmpeg。
Linux
espeak-ng -w sample.wav "What is the weather in Tokyo?"espeak-ng直接输出 WAV 文件,默认即单声道;如需显式指定采样率可追加-s(语速)与-a(振幅)参数微调。Debian/Ubuntu 系可用sudo apt install espeak-ng安装。
Windows
使用 PowerShell 调用 .NET 内置的System.Speech.Synthesis.SpeechSynthesizer,通过SetOutputToWaveFile输出 WAV:
$synth = New-Object System.Speech.Synthesis.SpeechSynthesizer $synth.SetOutputToWaveFile("sample.wav") $synth.Speak("What is the weather in Tokyo?") $synth.Dispose()生成后将文件命名为sample.wav,放入 public/demo-audio/ 目录即可。可先ls -la确认体积 < 100KB,若超出可适当缩短语音、降低振幅或压缩为更低位深。
四、内容约束:为何必须是 "What is the weather in Tokyo?"
样本音频的文案被硬性固定为"What is the weather in Tokyo?",这不是随意选择,而是由两处测试基建共同"锁定"的:
- 演示文案承诺:演示页顶部展示给用户的标语就是这句话,用户点击播放/试听时听到的音频必须与界面承诺一致,否则体验会前后矛盾。
- QA 清单与 E2E 断言:仓库内置的 Playwright 端到端测试 tests/e2e/voice.spec.ts 与打包的 QA 检查清单均会断言转录文本包含 "weather" 和/或 "Tokyo"。例如该测试中的断言:
await expect(textarea).toHaveValue(/weather|tokyo/i, { timeout: 1000 });这意味着:如果开发者用其他文案生成样本音频,即便转录链路完全正常,也可能因为关键词不匹配而导致 E2E 或 QA 检查失败。因此生成时请严格使用原句,不要自行替换句子内容。
从源码结构看,这条短语在前端被定义为常量SAMPLE_TEXT = "What is the weather in Tokyo?"(见 voice-chat.tsx),由 sample-audio-button.tsx 注入输入框,与音频内容形成了"所见即所听、所听即所测"的闭环。
五、源码级佐证:语音运行时与转录服务的真实调用链
要理解sample.wav最终流向哪里,需要看清语音演示专用的运行时入口 src/app/api/copilotkit-voice/[[...slug]]/route.ts。该文件是/demos/voice专属的 V2 运行时,承担三个职责:
- 在
/info上对外宣告audioFileTranscriptionEnabled: true,让聊天组件渲染出麦克风按钮; - 通过
POST /transcribe调用 OpenAI 支撑的TranscriptionServiceOpenAI(来自@copilotkit/voice),把录音转成文本并自动发送; - 在未配置
OPENAI_API_KEY时返回确定性的 4xx 错误,而非晦涩的 5xx。
其中转录服务的接入点与sample.wav直接相关——客户端把音频文件交给/transcribe,由GuardedOpenAITranscriptionService包装的transcribeFile(options: TranscribeFileOptions)完成转写。该守卫类会在缺少OPENAI_API_KEY时抛出包含 "api key missing" 的错误信息,利用 V2 运行时handleTranscribe对 "api key"/"unauthorized" 字样的映射,将缺失密钥的情况收敛到AUTH_FAILED → HTTP 401路径。这也解释了原文档"通过样本音频让流程在没有麦克风权限时也能工作"的设计意图:它把不确定性最高的麦克风录音环节替换成了确定性的文件转录。
此外,manifest.yaml 中对该 demo 的描述为 "Speech-to-text via @copilotkit/voice with a bundled sample audio button",路由为/demos/voice,涉及 page.tsx 与 sample-audio-button.tsx 两个前端文件,可视为该功能的目录索引。
六、端到端验证:E2E 如何消费这段样本音频
tests/e2e/voice.spec.ts 完整覆盖了样本音频相关的三条链路,可作为放置sample.wav后验收的参考:
- 页面装配:断言页面标题 "Voice input"、
voice-sample-audio-button与copilot-chat-input均可见,并等待copilot-start-transcribe-button(麦克风按钮)在/info往返完成后出现——该按钮是运行时正确宣告audioFileTranscriptionEnabled: true的权威信号; - 样本注入:点击 sample 按钮后,输入框在 1 秒内被填充匹配
/weather|tokyo/i的文案,且无瞬态 "Transcribing…" 状态、无/transcribe往返——这正是当前实现与"播放 WAV 再转录"路径的差异点,保证测试在 Whisper 或 aimock 不可用的环境依然稳定; - 完整对话:发送转录文本后,断言
weather-card、custom-catchall-card[data-tool-name="get_weather"]或copilot-assistant-message任一 Agent 输出出现,验证"转录文本 → Agent 响应"闭环,并为冷启动预留了 90 秒超时。
对需要验证真实转录的场合,麦克风路径(MediaRecorder+/transcribe)与手动 QA 清单是唯一真正经过转录服务的那条路——这也是sample.wav规格存在的根本意义:为这类需要真实音频的场景提供一个与测试断言完全对齐的标准样本。
七、快速核对清单
完成生成后,建议按以下顺序做最终确认:
- 文件名必须是
sample.wav,位于 public/demo-audio/ 下; - 用
file sample.wav确认编码为 16kHz 单声道 WAV,时长 3–5 秒; - 用
ls -la确认体积 < 100KB(16kHz 单声道 PCM 3–5 秒约 94–156KB,超限时优先缩短时长); - 试听确认内容为 "What is the weather in Tokyo?",且发音可被 ASR 清晰识别;
- 启动演示后访问
/demos/voice,确认页面文案、样本按钮、麦克风按钮均正常渲染,E2E 三组用例(页面装配 / 样本注入 / 完整对话)全部通过。
【免费下载链接】CopilotKitThe Frontend Stack for Agents & Generative UI. React, Angular, Mobile, Slack, and more. Makers of the AG-UI Protocol项目地址: https://gitcode.com/GitHub_Trending/co/CopilotKit
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考