拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Cloudflare Agents 语音包演进全解析:从 @cloudflare/voice 迁移到 agents/voice 的实战指南

Cloudflare Agents 语音包演进全解析从 cloudflare/voice 迁移到 agents/voice 的实战指南【免费下载链接】agentsBuild and deploy AI Agents on Cloudflare项目地址: https://gitcode.com/GitHub_Trending/agents1/agentscloudflare/voice是 Cloudflare Agents 仓库当前工作目录GitHub_Trending/agents1/agents中随agentsSDK 一起发布的实时语音能力包历经 0.0.2 到 0.5.0 的持续迭代最终在 0.5.0 被正式标记为弃用deprecated语音能力整体并入主包agents以agents/voice子路径对外提供。本文以 packages/voice/CHANGELOG.md 为骨架逐版本梳理这一演进过程从 0.1.0 的连续 STT 架构重构到采样率、播放调度、转写生命周期、每轮时序指标等一系列工程细节的打磨并给出可直接落地的迁移步骤。读完本文你将掌握cloudflare/voice与agents/voice之间的完整映射关系、新版连续 STT 会话模型的工作原理以及VoiceClient/ React hooks 的关键配置项与调试手段。一、包定位一个兼容层在 monorepo 中的位置在仓库中cloudflare/voice对应 packages/voice 目录其package.json明确将自身描述为 Compatibility package for the Agents SDK voice exportsagentsSDK 语音导出的兼容包。它的源码结构非常薄——四个入口文件全部是对主包的一行式再导出re-export文件内容src/voice.tsexport * from agents/voicesrc/voice-client.tsexport * from agents/voice/clientsrc/voice-react.tsxexport * from agents/voice/reactsrc/errors.tsexport * from agents/voice/errors从源码结构看兼容包不包含任何语音逻辑实现真正的实现在 packages/agents 中。查看其package.json的exports字段packages/agents/package.json可以看到主包暴露了远比兼容包更完整的语音入口agents/voice、agents/voice/client、agents/voice/react、agents/voice/errors以及兼容包尚未覆盖的agents/voice/types、agents/voice/workers-ai、agents/voice/sfu、agents/voice/text甚至包括通道侧入口agents/channels/voice这意味着agents主包才是语音能力的前沿阵地cloudflare/voice只是面向存量用户的一层保鲜包装。当前 packages/voice/package.json 的peerDependencies声明agents: 0.23.0 2.0.0这也解释了为什么语音包的每次重要改动几乎都会伴随agents最低版本要求的上调。二、0.5.0正式弃用与四条导入路径的迁移0.5.0 是 CHANGELOG 中最新也是最重要的一个版本cloudflare/voice被弃用所有能力并入agents。CHANGELOG 明确承诺All existing entry points remain compatible re-export wrappers——所有既有入口仍作为兼容再导出包装保留。对应的迁移映射表同样记录在 packages/voice/README.md 与 docs/voice/index.md旧导入新导入cloudflare/voiceagents/voicecloudflare/voice/clientagents/voice/clientcloudflare/voice/reactagents/voice/reactcloudflare/voice/errorsagents/voice/errors新项目只需安装一个依赖npm install agents然后按新路径导入import { withVoice, WorkersAIFluxSTT, WorkersAITTS } from agents/voice; import { VoiceClient } from agents/voice/client; import { useVoiceAgent } from agents/voice/react;官方文档docs/agents/voice.md强调导出的名称、Voice 线上协议wire protocol与 SQLite 表名均未改变兼容包在整个 Agents 1.x 生命周期内都会持续维护。也就是说迁移在绝大多数场景下只是换 import 路径级别的改动运行时与类型身份完全一致。这一设计让存量用户可以低风险升级同时让新特性只在主包中演进。三、0.1.0架构级重构——转向每通话连续 STT 会话在 0.1.0 之前语音管线依赖客户端发送start_of_speech/end_of_speech事件来驱动 STT 分段处理。0.1.0 做了一次破坏性 API 变更彻底改变了语音包的架构模型其影响贯穿后续所有版本新模型转写器会话transcriber session在start_call时创建并存活于整个通话周期由模型自身负责轮次检测turn detection客户端不再需要为 STT 发送起止语音事件。这一模型与 docs/agents/voice.md 中 Continuous STT 一节的描述完全对应The transcriber session is created atstart_calland lives for the entire call. All audio is fed continuously — the model handles speech boundary detection (turn detection). 客户端收到的transcript_interim消息实时携带部分转写结果start_of_speech/end_of_speech仅用于客户端 UI 状态说话指示、音量电平。3.1 新增 APItranscriber属性取代了stt、streamingStt与vad三个旧属性成为唯一的 STT 配置入口createTranscriber(connection)钩子支持运行时切换模型例如在 Flux 与 Nova 3 之间做下拉切换WorkersAIFluxSTT基于 Workers AI 的按通话 Flux 会话推荐用于withVoice完整语音代理WorkersAINova3STT按通话 Nova 3 流式会话推荐用于withVoiceInput纯语音输入/听写query选项VoiceClientOptions向 WebSocket URL 追加查询参数例如用于模型选择行为收紧start_call时若未配置转写器则直接抛错重复的start_call在已处于通话中时被静默忽略。3.2 移除与变更移除stt批式 STT、streamingStt按话语流式、vad服务端 VAD移除WorkersAISTT、WorkersAIVAD、pcmToWav工具移除prerollMs、vadThreshold、vadPushbackSeconds、vadRetryMs、minAudioBytes等调参选项移除VoiceInputAgentOptions类型与beforeTranscribe钩子音频现在连续喂入而非分批处理管线指标中移除vad_ms与stt_ms不再支持 HibernationwithVoice与withVoiceInput现在要求继承自AgentDurable Object而非 partyserver 的Server。3.3 防驱逐机制keepAlive新模型下会话存活整个通话周期为避免通话期间 Durable Object 被驱逐语音代理使用keepAlive机制。docs/agents/voice.md 的 Conversation History 一节印证了这一点Voice agents usekeepAliveto prevent eviction during active calls. 这也解释了后续 0.3.1 版本为何专门修复连接拆除时keepAlive的 alarm 写入仍在飞行途中引发的未处理拒绝详见下文第六节。四、持续打磨采样率、播放调度与设备路由0.1.0 之后CHANGELOG 记录了大量针对听感与播放正确性的工程修复这些细节直接影响语音产品的真实体验。4.1 采样率支持sampleRate选项0.3.4旧版本中原始的pcm16音频载荷被假定为固定的 16kHz。0.3.4 起新增sampleRate选项默认16000由服务端在audio_config消息中声明VoiceClient读取后通过新的sampleRategetter 暴露以该采样率构造AudioBuffer用于播放。这样原生采样率非 16kHz 的提供商如 24kHz 的 Gemini TTS能以正确速度播放服务端省略该字段时回退到 16kHz。配置方式const VoiceAgent withVoice(Agent, { sampleRate: 24000, // 与所选 TTS 提供商的原生采样率对齐 audioFormat: mp3, // 发给客户端的音频格式默认 mp3 historyLimit: 20, // 加载进上下文的最近消息数默认 20 maxMessageCount: 1000 // SQLite 中保存的最大消息数默认 1000 });4.2 消除块边界爆音基于播放游标的无缝调度0.3.20.3.2 修复了一个可闻的缺陷VoiceClient原先逐块播放响应——每个块在currentTime启动、等待ended事件后再调度下一块导致每个块的接缝处都会出现几毫秒静默事件循环延迟加上下一块准备耗时在听感上表现为每个块一下的周期性咔哒声。修复方式是把各块在音频时钟上背靠背调度start(Math.max(currentTime, cursor)) // cursor 为持续推进的播放游标因为块现在可以提前排队调度客户端必须追踪所有已排程的音频源并在打断/结束通话时全部停止此前只需停止当前活动源同时播放计数会持续到最后一个排程块结束保证排程尾部期间的 barge-in打断检测依然有效。4.3 修复跨轮次的慢放播放桥的按轮次重建0.3.30.3.3 修复了一个隐蔽问题当一轮播放结束后存在空闲间隔下一轮开头的声音会以错误速率播放听感为慢动作随后逐渐恢复正常。根因是VoiceClient通过MediaStreamAudioDestinationNode → HTMLAudioElement桥播放音频复用那个已空闲的元素会让新的一轮从错误的速率点继续。修复策略是当桥完全排空且空闲超过一个短阈值后拆除并重建播放桥确保每一轮都通过新创建的元素播放由于轮内各块会在播放游标上持续排程至少一个源重建绝不会发生在轮次中途。4.4 输出设备选择outputDeviceId与setOutputDevice()0.3.00.3.0 为VoiceClient增加outputDeviceId选项和setOutputDevice()方法用于在浏览器支持 sink 选择时将助手语音路由到指定的音频输出设备。React 侧的使用方式详见 docs/agents/voice.md 的 Output Device Selectionconst [outputDeviceId, setOutputDeviceId] useState(default); const voice useVoiceAgent({ agent: MyAgent, outputDeviceId });实践要点deviceId来自navigator.mediaDevices.enumerateDevices()中kind audiooutput的条目default与undefined使用系统默认输出不支持 sink 选择的浏览器继续走默认输出并在请求非默认设备时设置outputDeviceError设备标签在用户授予麦克风权限前可能为空因此展示扬声器选择器时应等startCall()之后刷新设备列表。另外setOutputDevice()可以在不重连通话的前提下切换播放设备非常适合通话中的扬声器切换场景。五、转写生命周期、诊断与每轮时序指标0.4.0 是一份内容密集的版本聚焦语音生命周期准确性、诊断能力与每轮时序可见性其中大部分能力已经在当前 docs/agents/voice.md 中有完整的 API 呈现。5.1 生命周期清理清除过期的 interim 转写在通话开始、结束、断开、关闭或启动失败时清除残留的临时转写文本避免把上一轮的半截语音带入新状态speaking事件语义收紧仅在发送首个服务端音频块时才发出speaking转写器就绪transcriber readiness0.3.4 引入——语音代理会等待流式 STT 启动完成后再进入listening状态或运行 call-start 钩子。自定义转写器会话若异步建立上游流式连接可实现waitUntilReady(): Promisevoid就绪时 resolve启动失败时 reject通话回到idle。若close()在就绪等待期间放弃了启动需要 settle 该 promise避免服务端启动工作无限等待同步就绪的提供商可省略此方法错误上报转写器启动与运行期失败通过onFatalError、结构化客户端错误以及可靠的通话清理来报告结构化诊断与日志新增无内容的浏览器诊断与结构化 Worker 错误日志且不会读取任意的提供商响应体避免破坏响应流。5.2 结果分类与VoiceTurnMetrics0.4.0 保留了模型的完成原因finish reason可区分五类完成结果no-output无输出、output-limit输出达上限、content-filtered内容被过滤与 model-error模型错误再加上正常的完成。在此基础上通过VoiceClient与 React hooks 暴露稳定的、带类型的每轮时序汇总覆盖语音时序speechStartToFirstInterimMs、speechStartToFinalMs轮次与模型时序afterTranscribeMs、modelToFirstTextMs、exposedReasoningMs模型流暴露的推理时长、modelStreamConsumptionMs、finalInputToFirstAudioMs、turnTotalMsTTS 时序ttsToFirstAudioMs、ttsWallMs、以及累积的重叠 TTS 工作量ttsWorkMs关于指标语义docs/agents/voice.md 的 Pipeline metrics 一节给出了关键约束VoiceTurnMetrics对每个被分配的语音或文本轮次都会发射一次包括中止、跳过、空输出、模型错误、TTS 错误等结局turnId、source、outcome是用于关联与解释的维度而非测量值未触达的时序字段会被省略而非置零所有时长使用 Worker 时钟彼此重叠、不可相加。withVoiceInput只发射其可测得的语音、afterTranscribe与总时长模型与 TTS 时序保持缺省。终端结局terminal outcome包括completed、no_output、output_limit、content_filtered、model_error、tts_error、aborted、skipped、error。消费方式client.addEventListener(turnmetrics, (turnMetrics) { console.log(turnMetrics.turnId, turnMetrics.outcome); }); client.turnMetrics; // VoiceTurnMetrics | null最近一次终端汇总React 侧同理useVoiceAgent()与useVoiceInput()都通过turnMetrics暴露最近一次终端汇总。0.4.0 同时声明保持既有四字段指标线上形状兼容wire shape同时让无音频与流式 TTS的计量口径一致。六、错误处理、文本流与提示构造语义6.1 防泄漏的 teardown 处理0.3.10.3.1 修复了连接拆除时fire-and-forget语音生命周期处理器泄漏未处理拒绝的问题。withVoiceInput混入mixin在同步的onMessage处理器中派发start_call、end_call、interrupt与转写发射事件且不等待它们完成若客户端中途断开例如keepAlive()的 alarm 写入仍在飞行中可能浮现一条可重试的 Network connection lost. 拒绝。修复后这些后台任务经由一个 teardown 感知的辅助函数运行吞掉预期的连接拆除错误并把意外错误记入日志。6.2 支持 AI SDKfullStream0.3.30.3.3 起语音轮次支持 AI SDK 的fullStream响应并会在使用textStream时给出警告。docs/agents/voice.md 中的推荐做法正是返回result.fullStreamasync onTurn(transcript: string, context: VoiceTurnContext) { const workersai createWorkersAI({ binding: this.env.AI }); const result streamText({ model: workersai(cf/moonshotai/kimi-k2.7-code), system: You are a helpful voice assistant. Keep responses concise., messages: [ ...context.messages.map(m ({ role: m.role as user | assistant, content: m.content })), { role: user, content: transcript } ], abortSignal: context.signal }); return result.fullStream; }0.2.0 还专门修复过withVoice对 AI SDKtextStream响应的文本流处理使onTurn()直接返回streamText(...).textStream时也能正常产出 TTS 音频。6.3 工具调用间的文本间距0.3.60.3.6 修复了被工具调用分隔的流式文本段之间的空格问题Think messenger 投递与 Voice 现在共用来自agents/chat的同一套边界感知文本拼接逻辑。这带来两个迁移要求从cloudflare/think/messengers导入textDeltaFromStreamChunk()的存量用户需改用TextStreamCallback并传入完整的结构化流事件安装cloudflare/think0.16.0或cloudflare/voice0.3.6时需同步升级到agents0.21.0两者都要求agents 0.20.2若此前依赖工具调用两侧文本被无空格拼接需要更新精确文本断言。6.4VoiceTurnContext.messages语义0.3.60.3.6 明确了VoiceTurnContext.messages的定义它是当前转写之前的已完成历史针对语音轮次与文本轮次均如此从而避免按文档方式构造提示时出现重复的用户消息。对既有onTurn()实现的迁移指导若你直接把context.messages作为完整 LLM 输入请只追加一次transcript若你原本就在context.messages之外另附transcript无需任何改动在onTurn()内部直接调用getConversationHistory()仍会包含当前转写。这与 docs/agents/voice.md 的说明一致The pipeline persists the current transcript before invoking the hook, so a directgetConversationHistory()call insideonTurn()includes it. 同时context还提供connectionWebSocket 连接与signal在打断或断开时中止。七、提供商生态内置与第三方流式 STT7.1 Workers AI 内置提供商免 API Key类类型默认模型推荐场景WorkersAIFluxSTT连续 STTcf/deepgram/fluxwithVoiceWorkersAINova3STT连续 STTcf/deepgram/nova-3withVoiceInputWorkersAITTSTTScf/deepgram/aura-1两者通用import { WorkersAIFluxSTT, WorkersAINova3STT, WorkersAITTS } from agents/voice; transcriber new WorkersAIFluxSTT(this.env.AI, { eotThreshold: 0.8, // 结束轮次end-of-turn阈值 keyterms: [Cloudflare, Workers] // 领域关键词提升识别率 }); tts new WorkersAITTS(this.env.AI, { model: cf/deepgram/aura-1, speaker: asteria });相关修复记录0.2.0 修复了 Workers AI STT 会话在 Flux 与 Nova 3 上的边界情况——Flux 现在从轮次生命周期事件中保留最近的非空轮次转写使得携带空transcript的EndOfTurn事件仍能发出完整话语且 Flux 的StartOfTurn驱动服务端 barge-in模型检测到用户说话即中止正在进行的 LLM/TTS 播放Nova 3 则防御性地在读取前规范化已定稿段状态避免异常关闭路径下陈旧 teardown 消息抛错。0.3.6 还修复了仅把首个keyterms词条传给 Workers AI Flux 与 Nova-3 STT 的问题现在会传递完整数组。7.2 第三方提供商CHANGELOG 0.3.5 为语音管线新增了AssemblyAI 与 ElevenLabs 流式 STT 提供商。当前生态对应仓库voice-providers目录下的独立包如 voice-providers/assemblyai、voice-providers/deepgram、voice-providers/elevenlabs、voice-providers/telnyx包类能力cloudflare/voice-assemblyaiAssemblyAISTT连续 STTUniversal 3.5 Pro Realtimecloudflare/voice-deepgramDeepgramSTT连续 STTcloudflare/voice-elevenlabsElevenLabsSTT、ElevenLabsTTS连续 STT 与高质量 TTScloudflare/voice-telnyxTelnyxSTT、TelnyxTTS连续 STT、TTS 与电话传输cloudflare/voice-twilioTwilio 适配器电话通话接入import { AssemblyAISTT } from cloudflare/voice-assemblyai; export class MyAgent extends VoiceAgentEnv { transcriber new AssemblyAISTT({ apiKey: this.env.ASSEMBLYAI_API_KEY }); tts new WorkersAITTS(this.env.AI); }AssemblyAI 有一个值得注意的工程细节每轮代理回复后管线会自动把说出的文本回喂给 AssemblyAI 作为会话上下文agent_context从而提升对yes、7pm这类短应答的识别准确率。0.4.0 同时更新了随附的语音提供商使生命周期失败能够向上传播、错误日志保持一致。7.3 电话接入Twilio的音频格式注意点使用 Twilio 适配器时有一个关键约束见 docs/agents/voice.md 的 Telephony (Twilio)WorkersAITTS返回 MP3而 Workers 运行时无法将 MP3 解码为 PCM因此电话场景必须使用输出原始 PCM 的 TTS 提供商例如 ElevenLabs 搭配outputFormat: pcm_16000。八、React hooks 的演进enabled选项与调参语义8.1enabled选项0.2.0useVoiceAgent新增enabled选项让 React 应用可以延迟创建与连接VoiceClient直到异步前置条件例如按用户生成的 capability token就绪const voice useVoiceAgent({ agent: MyAgent, enabled: isReady // false 时不创建/不连接 VoiceClient });处于禁用态时hook 不创建也不连接VoiceClient返回空闲/断开状态且startCall()、sendText()、sendJSON()等动作回调均为安全的 no-op。当enabled翻转为true时hook 以当前选项连接首次启用被视为初始连接因此onReconnect只在后续连接身份变化时触发。8.2 调参选项与重连语义选项类型默认值说明silenceThresholdnumber0.04RMS 低于此值视为静音silenceDurationMsnumber500触发end_of_speech的静音时长msinterruptThresholdnumber0.05播放期间检测到说话所需的 RMSinterruptChunksnumber2连续高 RMS 块达到该数量即触发打断注意修改调参选项会触发客户端重连连接 key 包含这些选项。useVoiceInput是面向听写/语音转文字的轻量 hook把各轮话语累积成一个字符串并暴露turnMetrics最新终端 STT 汇总与clear()等方法。九、依赖治理与发布工程细节CHANGELOG 中有一组容易被忽略但工程价值很高的记录集中在peerDependencies的治理上0.0.5把通配符*的 peer 依赖替换为真实版本区间——agents为0.9.0 1.0.0partysocket为^1.0.00.1.1 / 0.1.2发布脚本曾把宽区间覆盖成过紧的^0.x.y导致安装警告。0.1.2 修正了发布时的 peer 依赖范围0.1.1 又把updateInternalDependencies从patch改为minor防止未来发布时再次覆盖区间0.1.3把agents的 peer 下限从0.9.0收紧到0.11.7与 monorepo 实际测试集对齐上限1.0.0不变。其可见效果是用新版cloudflare/voice配旧版agents0.11.7会出现 peer 警告——这正是设计意图低于 0.11.7 的agents不再被测过0.0.4修复 TypeScript 6 声明产出。TS6 强制 TS4094禁止在导出的匿名类类型中使用#private成员通过为withVoice与withVoiceInput混入函数增加显式返回类型接口VoiceAgentMixinMembers、VoiceInputMixinMembers生成的.d.ts只暴露公共 API 表面。结合 packages/voice/package.json当前要求的agents 0.23.0 2.0.0是该治理链条的最新形态react作为可选的 peer 依赖peerDependenciesMeta.react.optional: true保证非 React 环境也能使用VoiceClient。该包以dist/、docs/、README.md为发布内容通过 nx 构建目标把 docs/voice 文档与 scripts/copy-package-docs.ts 一并纳入产物。十、迁移总览与落地建议结合 docs/voice/index.md面向迁移的官方指引与 docs/agents/voice.md最新完整参考把存量项目迁移到agents/voice的建议步骤总结如下升级依赖npm install agents并把cloudflare/voice替换为agents确保版本满足 CHANGELOG 中对应能力要求的agents下限如 0.3.6 要求0.20.2批量替换导入路径按第二节表格完成cloudflare/voice、/client、/react、/errors四处替换核对onTurn()提示构造确认context.messages只追加一次transcript对应 0.3.6 语义如果依赖textDeltaFromStreamChunk()改为TextStreamCallback并传入完整结构化流事件利用新增能力接入sampleRate对齐 TTS 原生采样率、outputDeviceId支持多扬声器、enabled控制连接时机、turnMetrics观察每轮时序并区分no_output/output_limit/content_filtered/model_error等结局注意电话场景约束Twilio 适配器必须使用输出 PCM 的 TTS 提供商。整体演进逻辑可以概括为语音管线从客户端驱动的 VAD 分段走向服务端连续 STT 模型轮次检测随之带来更低的端到端延迟连续喂入、提前排队调度、更强的持久性按通话会话 keepAlive防驱逐与更高的可观测性结构化诊断 每轮时序指标。而 0.5.0 把这一切收拢进agents主包只是让能力在哪里这个问题变得更简单从今往后语音能力的演进都以agents/voice为准cloudflare/voice仅作为向后兼容的别名继续存在。【免费下载链接】agentsBuild and deploy AI Agents on Cloudflare项目地址: https://gitcode.com/GitHub_Trending/agents1/agents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门