news 2026/9/11 19:54:35

CopilotKit Agno 集成语音示例音频 sample.wav 配置与生成完全指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CopilotKit Agno 集成语音示例音频 sample.wav 配置与生成完全指南

CopilotKit Agno 集成语音示例音频 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

本指南围绕 CopilotKit 仓库中 Agno 集成(showcase/integrations/agno)的语音演示(Voice Demo)展开,核心目标是教会你如何正确放置并生成驱动该演示的示例音频文件sample.wav。读完本文,你将掌握该音频文件的目录位置、格式规格(16kHz 单声道、3–5 秒、小于 100KB)、内容要求(必须包含 "What is the weather in Tokyo?" 这句台词),以及 macOS / Linux / Windows 三平台的标准生成命令,并理解该文件在语音转写链路(/transcribe端点、E2E 断言)中的真实作用。

一、这份 README 说明文档的用途:语音演示的"固定台词"音频

在仓库路径 showcase/integrations/agno/public/demo-audio/README.md 下,存放着一份专门解释语音演示音频文件的说明文档。它对应的是 Agno 集成中的Voice Input(语音输入)演示,在 manifest.yaml 中被登记为id: voice,路由为/demos/voice,其功能描述为:

Microphone + sample-audio button → /transcribe endpoint → text injected into the chat composer(麦克风 + 示例音频按钮 →/transcribe端点 → 文本注入聊天输入框)

该演示页面同时提供两条输入通道(详见 voice-chat.tsx 的注释):

  1. 麦克风按钮:由<CopilotChat />在运行时(runtime)通告audioFileTranscriptionEnabled: true时渲染,点击后录音并调用真正的转写端点;
  2. 示例音频按钮(Sample Audio Button):同步将一段预设台词注入聊天输入框,不依赖麦克风权限,也不走/transcribe往返,是确定性的测试/演示手段。

本 README 说明文档所管理的sample.wav,正是为了让上述"示例音频"路径在不需要麦克风权限的前提下完整复现"语音 → 文本 → Agent 应答"的链路:演示页面会在客户端取用该音频文件,并将其 POST 到转写端点。

二、文件放置位置与命名约定

说明文档明确规定:

  • 将一个小体积(小于 100KB)的 WAV 文件放在本目录:showcase/integrations/agno/public/demo-audio/
  • 文件必须命名为sample.wav

当前仓库中该目录实际已存在 sample.wav,与 README 约定的命名一致。该目录位于 Agno 集成的 Next.jspublic/静态资源目录下,因此客户端可以直接通过 URL 访问并获取该音频文件。

为什么放在public/demo-audio/从 manifest.yaml 中可以看到,public/目录还包含demo-files/(用于 Multimodal 附件演示),说明public/承担着为各演示提供静态样例资源(音频、文件附件等)的统一职责。sample.wav作为语音演示的客户端样例音频,被归类于此。

三、音频内容要求:一句"固定台词"为什么这么关键

说明文档明确要求音频内容必须是一段朗读"What is the weather in Tokyo?"的语音片段。这个要求并非随意,而是由演示的端到端验证链决定的:

  1. 演示页面会向用户展示这句台词:在 voice-chat.tsx 中定义了const SAMPLE_TEXT = "What is the weather in Tokyo?";,并作为示例音频按钮的 tooltip 提示(见 sample-audio-button.tsx)。用户看到页面后按图索骥,理应能听到同一句话。

  2. E2E 测试会断言转写文本包含关键词:在 voice.spec.ts 中,Playwright 测试断言textarea的值匹配正则/weather|tokyo/i。也就是说,只要转写结果(或示例按钮注入的固定文本)中包含 "weather" 或 "Tokyo",测试即通过。

  3. QA 检查清单与测试套件共用同一台词:说明文档指出"bundled QA checklist + E2E spec"都依赖这段台词来断言转写结果。因此,如果音频内容与页面广告的台词不一致,即使音频本身能正常转写,验证流程也无法通过。

四、三平台生成命令:从朗读到 16kHz 单声道 WAV

说明文档为三种主流开发平台分别给出了生成命令。下面逐条展开,并补充参数说明。

macOS:say + ffmpeg 两步转换

say -o sample.aiff "What is the weather in Tokyo?" && ffmpeg -i sample.aiff -ar 16000 -ac 1 sample.wav
  • say -o sample.aiff:调用 macOS 系统自带文本朗读引擎,将文本合成为 AIFF 格式音频;
  • ffmpeg -i sample.aiff -ar 16000 -ac 1 sample.wav:将 AIFF 转码为 WAV,同时完成两项关键规格转换:
    • -ar 16000:采样率设为 16kHz(转写服务的标准输入采样率);
    • -ac 1:强制单声道。

Linux:espeak-ng 一步直达

espeak-ng -w sample.wav "What is the weather in Tokyo?"
  • espeak-ng是 Linux 上常用的开源文本转语音(TTS)工具,-w参数直接输出 WAV 文件。若系统未安装,可通过发行版包管理器安装(如apt install espeak-ng)。
  • 注意:espeak-ng 生成的默认 WAV 通常已是 16kHz 单声道,但为保险起见,可以同样通过ffmpeg校验或强制转换规格(见下文规格自查)。

Windows:PowerShell 系统语音合成

Add-Type -AssemblyName System.Speech $synth = New-Object System.Speech.Synthesis.SpeechSynthesizer $synth.SetOutputToWaveFile("sample.wav") $synth.Speak("What is the weather in Tokyo?") $synth.Dispose()

说明文档给出的核心 API 是 .NET 的System.Speech.Synthesis.SpeechSynthesizer配合SetOutputToWaveFile,上述 PowerShell 脚本即为该 API 的完整落地写法。

五、目标规格:为什么是 16kHz 单声道 + 3–5 秒 + <100KB

说明文档给出的最终规格目标:

规格项目标值原因分析
采样率16kHz语音识别模型的标准输入采样率,与转写服务兼容
声道单声道(mono)语音识别通常只需要单声道,减小体积
时长3–5 秒"What is the weather in Tokyo?" 正常语速朗读的时长区间;过短会截断内容,过长会撑大文件体积
文件大小小于 100KB保证客户端快速获取、转写接口请求体轻量

为什么是 <100KB?这与该演示"无需麦克风权限"的定位直接相关:音频需要在客户端被取用并 POST 到转写端点(见说明文档与 route.ts 注释中提到的/transcribe端点)。过大的文件会让该链路变得缓慢甚至不可用,因此 README 明确将 100KB 作为硬性上限。

自查建议:生成后可用ffprobe(ffmpeg 套件自带)验证规格:

ffprobe -v error -show_entries stream=sample_rate,channels -of default=noprint_wrappers=1 sample.wav

以及查看文件大小:

ls -la sample.wav

若采样率/声道不符或超过 100KB,按需用ffmpeg -i in.wav -ar 16000 -ac 1 out.wav重新转换。

六、源码级佐证:sample.wav 在转写链路中的真实角色

将说明文档与仓库源码对照,可以还原这条完整的链路:

1. 转写端点(服务端)

语音演示使用了一个专门的 CopilotRuntime 路由:showcase/integrations/agno/src/app/api/copilotkit-voice/[[...slug]]/route.ts。该路由的实现目标(见文件头注释)包括:

  • /info上通告audioFileTranscriptionEnabled: true,让聊天输入框渲染出麦克风按钮;
  • 处理POST /transcribe,调用 OpenAI 支持的TranscriptionServiceOpenAI(来自@copilotkit/voice包);
  • OPENAI_API_KEY未配置时,返回类型化的 401 错误,而不是 5xx。

其中GuardedOpenAITranscriptionService类(第 33–54 行)封装了密钥守卫逻辑:若未设置OPENAI_API_KEYtranscribeFile会抛出包含 "api key" 子串的错误,该错误会被映射为AUTH_FAILED→ 401。也就是说,要真正跑通"上传 WAV → 转写为文本",必须为部署环境配置OPENAI_API_KEY;否则音频文件即使放置正确,转写也会返回 401。

2. 客户端取用与按钮注入(前端)

  • 演示页面 page.tsx 通过<CopilotKit runtimeUrl="/api/copilotkit-voice" agent="voice-demo" useSingleEndpoint={false} enableInspector={false}>挂载语音专用运行时;
  • voice-chat.tsx 中的handleTranscribed通过 DOM 操作(原生 value setter + 触发input事件)将文本注入data-testid="copilot-chat-textarea",这是绕过CopilotChat内部受控状态的 React 兼容做法;
  • sample-audio-button.tsx 提供data-testid="voice-sample-audio-button"的按钮,点击后同步调用onTranscribed(sampleText)。其注释明确指出:该按钮是纯粹的测试/演示辅助手段,不涉及麦克风权限、不获取音频、不经过/transcribe往返

3. E2E 测试验证(端到端)

voice.spec.ts 中的三个测试分别覆盖:

  • 页面加载(第 23–44 行):断言标题 "Voice input"、示例音频按钮、聊天输入框可见,并断言麦克风按钮(copilot-start-transcribe-button)最终出现——该按钮的出现证明运行时通告了audioFileTranscriptionEnabled: true
  • 示例按钮注入(第 46–63 行):点击按钮后,textarea 在 1 秒内匹配/weather|tokyo/i,且无瞬态 "Transcribing…" 状态、无/transcribe往返;
  • 发送后产生 Agent 响应(第 65–98 行):发送文本后,等待天气卡片(weather-card)或通用 catchall 卡片(custom-catchall-card[data-tool-name="get_weather"])或 assistant 消息出现,断言"某种 agent 响应面"已呈现。

测试头部注释还说明了设计取舍:麦克风路径(真实的转写)不在 E2E 范围内,因为MediaRecorder在无头环境中难以稳定驱动,真实的转写路径改由qa/目录下的人工 QA 清单覆盖;示例音频按钮路径则保证 Playwright 测试不依赖转写端点健康状态或特定 aimock fixture。这也解释了为什么说明文档要把sample.wav的内容限定为固定台词——它是整个确定性验证体系的一部分。

七、常见问题排查

现象可能原因处理方式
目录中缺少sample.wav或命名不符未放置或命名错误严格命名为sample.wav并放入showcase/integrations/agno/public/demo-audio/
音频内容不是 "What is the weather in Tokyo?"使用了自定义文本按文档生成标准台词,否则 E2E/QA 断言无法通过
文件超过 100KB采样率过高、立体声或时长过长ffmpeg -ar 16000 -ac 1重编码并缩短时长
点击麦克风后转写报错/返回 401未配置OPENAI_API_KEY在部署环境设置OPENAI_API_KEY,参见 route.ts 的守卫逻辑
E2E 测试无法点击示例按钮本地开发时 web-inspector 覆盖层拦截点击演示页面已显式enableInspector={false}以保持两环境行为一致(见 page.tsx)

八、小结

showcase/integrations/agno/public/demo-audio/README.md看似只是一段简短的资源放置说明,但在 CopilotKit Agno 集成的语音演示体系中,它承载着"确定性验证"的关键职责:固定的文件名、固定的台词、固定的音频规格,与voice-demo专用运行时(/api/copilotkit-voice)、示例音频按钮组件以及 Playwright E2E 测试共同构成了一条不依赖麦克风权限即可端到端演示语音输入 → 转写 → Agent 应答的稳定链路。按本文提供的三平台命令生成合规的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

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 19:53:15

网络赌博治安治理难点解析

一部手机、一条私信、一个小程序&#xff0c;就可能把普通人拖进网络赌博的泥潭。2026年&#xff0c;网络赌博跨境化、伪装化、私域化特征愈发突出&#xff0c;呈现出 “反复性强、治后反弹” 的局面。从网安行业技术观测视角来看&#xff0c;当下网络赌博之所以难以有效治理&a…

作者头像 李华
网站建设 2026/9/11 19:52:48

Kotlin by lazy 异常执行流程:初始化失败自动重试机制解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 19:52:02

Kotlin lazy委托异常机制解析:三种线程安全模式与源码级避坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 19:51:20

Python深度学习实战:人脸表情识别系统从训练到部署

简介&#xff1a;这套Python人脸表情识别系统是一份面向高校课程设计与深度学习入门者的完整工程&#xff0c;以卷积神经网络为核心&#xff0c;实现从人脸检测、表情分类到结果可视化的全流程&#xff0c;包含训练、测试、GUI交互和摄像头实时识别等主要功能模块。压缩包共19个…

作者头像 李华
网站建设 2026/9/11 19:50:01

Spring Boot承兑汇票前台用户端开发要点与实现

简介&#xff1a;使用MATLAB与Simulink进行雷达系统建模与仿真的完整代码包&#xff0c;聚焦雷达系统级设计与信号处理仿真&#xff0c;面向电子信息工程、计算机、数学等专业学生&#xff0c;可用于课程设计、期末大作业和毕业设计等实践环节。资源共131个文件&#xff0c;大小…

作者头像 李华