☰
OpenClaw voice-call 语音通话插件演进全解:从首发功能矩阵到 TTS 核心迁移
2026/10/17 2:02:13 网站建设 项目流程
  • 人工智能
  • 大模型
  • LLM 网关
  • AI Agent
  • 即时通讯

【免费下载链接】openclaw-zero-token

OpenClaw: Use All Major AI Models NO API Token! Claude/ChatGPT/Gemini/DeepSeek/Doubao/Grok/Qwen/Manus/Kimi

项目地址:https://gitcode.com/gh_mirrors/op/openclaw-zero-token
点击查看免费下载

导读

本文以 OpenClaw 官方语音通话插件@openclaw/voice-call的 CHANGELOG 为骨架,系统梳理该插件自0.1.0首发以来的能力矩阵与关键破坏性变更。你将了解:插件支持哪些电信提供商(Twilio / Telnyx / Plivo / Mock)、两种外呼模式(notify / conversation)如何工作、入站策略与 allowlist 如何配置、Webhook 服务器与 ngrok / Tailscale 暴露方案、OpenAI Realtime 流式 STT 的接入细节,以及 2026.1.26 版本中电话 TTS 迁移到核心messages.tts后配置项如何调整。文中所有结论均以当前仓库源码与配置为证据,可对照文件路径深入验证。


一、版本演进概览:与核心 OpenClaw 对齐的发布节奏

CHANGELOG 前半部分(2026.3.1至2026.3.14,含2026.3.8-beta.1)的每个条目都只有一句相同的说明:"Version alignment with core OpenClaw release numbers."(版本号与 OpenClaw 核心发行号对齐)。

这说明 voice-call 插件在 0.1.0 首发之后进入了一个稳定维护期——其功能面没有大幅变动,但插件版本号跟随 OpenClaw 核心版本发布节奏同步递增。这种对齐策略的收益在于:

  • 用户可以通过核心版本号直接判断插件是否匹配当前宿主环境,避免版本错配;
  • package.json中的peerDependencies与install.minHostVersion均声明>=2026.3.28,即插件要求宿主 OpenClaw 至少为 2026.3.28,package.json 中openclaw.release.publishToNpm表明该插件通过 npm 渠道发布。

两个真正承载技术信息的里程碑是:

  1. 0.1.0——首个公开版本,一次性引入了四大提供商、双模式外呼、入站策略、Webhook、流式 STT/TTS、CLI、网关 RPC 与可观测性的完整能力矩阵;
  2. 2026.1.26——引入破坏性变更,电话 TTS 全面迁移到核心messages.tts配置,废弃了插件自带的旧字段。

下文分别对这两个里程碑展开源码级剖析。


二、0.1.0 首发功能矩阵:从提供商到可观测性的完整链路

2.1 四大提供商:Twilio / Telnyx / Plivo / Mock

CHANGELOG 首发条目声明支持Twilio (Programmable Voice + Media Streams)、Telnyx (Call Control v2)、mock provider for local dev。结合 README 与源码,实际能力矩阵为:

提供商协议/产品关键配置适用场景
TwilioProgrammable Voice + Media StreamsaccountSid/authToken生产首选,支持 WebSocket 双向音频流
TelnyxCall Control API v2apiKey/connectionId/publicKey生产备选,需 webhook 公钥验签
PlivoVoice API + XML transfer + GetInput speechauthId/authToken生产备选(README 已补充,CHANGELOG 0.1.0 未列出)
Mock无网络调用无需凭证本地开发/测试

所有提供商在 providers/base.ts 中实现了统一的VoiceCallProvider接口,职责明确:

  • verifyWebhook(ctx)——校验 webhook 签名/HMAC,必须在解析事件前调用;
  • parseWebhookEvent(ctx, options?)——把各提供商私有负载归一化为统一事件;
  • initiateCall(input)/hangupCall(input)——外呼发起与挂断;
  • playTts(input)/startListening(input)/stopListening(input)——媒体控制;
  • getCallStatus(input)——重启时向提供商核对持久化通话是否仍存活,瞬时错误(网络、5xx)必须返回isUnknown: true,以便调用方保留通话并依赖定时器兜底。

providers/telnyx.ts 与 providers/twilio.ts 各自封装了提供商 REST API 与签名校验逻辑;MockProvider 则让整套状态机在无网络环境下可完整跑通。

2.2 外呼双模式:notify 与 conversation

CHANGELOG 提到 "outbound notify vs. conversation modes, configurable auto-hangup, and multi-turn continuation"。源码在 config.ts 中用CallModeSchema定义了两种模式:

  • notify(默认):单向通知——接通后播报消息,TTS 播放结束延迟notifyHangupDelaySec(默认 3 秒)后自动挂断。Twilio 场景下直接以内联 TwiML 下发<Say>+<Hangup/>(见 manager/twiml.ts),无需走 webhook 往返;
  • conversation:保持通话开启,支持多轮问答(continue续话),直到显式end或触发maxDurationSeconds(默认 300 秒)超时。

相关可调参数与默认值(均来自 config.ts):

参数默认值含义
outbound.defaultModenotify外呼默认模式
outbound.notifyHangupDelaySec3notify 模式下 TTS 后自动挂断延迟(秒)
maxDurationSeconds300最大通话时长(秒)
ringTimeoutMs30000外呼振铃超时(毫秒)
silenceTimeoutMs800静音判定说话结束的阈值(毫秒)
transcriptTimeoutMs180000等待用户语音转写结果的超时(毫秒)
maxConcurrentCalls1最大并发通话数
staleCallReaperSeconds0陈旧通话自动回收阈值(秒,0 表示禁用)

2.3 入站处理:disabled / allowlist / open 三态策略

CHANGELOG 声称 "Inbound handling: policy controls (disabled/allowlist/open), allowlist matching, and inbound greeting"。源码中的InboundPolicySchema(config.ts)实际枚举了四个值:

  • disabled(默认):拒绝所有入站来电(仅支持外呼);
  • allowlist:仅接受allowFrom名单中的号码;
  • pairing:未知来电者可请求配对(预留能力);
  • open:接受所有来电(危险选项,需谨慎)。

allowFrom数组中的号码统一按 E.164 格式校验(正则^\+[1-9]\d{1,14}$)。allowlist 的匹配逻辑在 allowlist.ts 中实现:normalizePhoneNumber剥离所有非数字字符后做严格相等比较,避免国际区号写法差异导致误判。inboundGreeting用于入站接通后的欢迎语。

2.4 Webhook 服务器:内置 HTTP 服务与公网暴露

CHANGELOG 提到 "Webhooks: built-in server with configurable bind/port/path pluspublicUrloverride"。对应配置块serve的默认值为port: 3334、bind: "127.0.0.1"、path: "/voice/webhook"(见 config.ts)。webhook.ts 中的VoiceCallWebhookServer负责:

  • 接收三家提供商的事件回调,先做签名/HMAC 校验再解析;
  • 在streaming.enabled时升级 WebSocket 处理媒体流;
  • 通过webhookSecurity配置(allowedHosts/trustForwardingHeaders/trustedProxyIPs)控制 X-Forwarded-* 头信任策略,防止 URL 重建被伪造;
  • 内置请求体大小上限与超时保护(MAX_WEBHOOK_BODY_BYTES、WEBHOOK_BODY_TIMEOUT_MS),并限制同一时刻 in-flight 的 webhook 处理数量。

公网暴露(exposure)有两条路径:

  1. ngrok:tunnel: { provider: "ngrok" },可选ngrokAuthToken(通过环境变量NGROK_AUTHTOKEN注入)与ngrokDomain(自定义域名,付费功能)。实现位于 tunnel.ts 的startNgrokTunnel:spawnngrok http <port>,解析 JSON 日志中的started tunnel消息获取公网 URL 并拼接路径;
  2. Tailscale:tailscale: { mode: "serve" | "funnel", path: "/voice/webhook" }——serve仅对 tailnet 私有暴露,funnel提供公网 HTTPS。实现通过调用tailscale serve/funnel命令完成(见 webhook/tailscale.ts 与getTailscaleDnsName)。

此外publicUrl配置可直接指定公网 webhook URL,若设置则绕过隧道自动探测。

2.5 流式 STT:OpenAI Realtime 音频流转写

CHANGELOG 声称 "Streaming: OpenAI Realtime STT over media WebSocket with partial + final transcripts"。实现链路为:

  • media-stream.ts 的MediaStreamHandler建立 WebSocket 服务端,接收 Twilio 推送的 mu-law 8kHz 音频,转发给 OpenAI Realtime STT;
  • providers/stt-openai-realtime.ts 的OpenAIRealtimeSTTProvider通过wss://api.openai.com/v1/realtime?intent=transcription建立会话,支持服务端 VAD(静音检测)、partial 回调(实时中间结果)与 final 转写(说话结束后完整结果),断线自动重连最多 5 次;
  • STT 默认模型为gpt-4o-transcribe,silenceDurationMs默认 800ms,vadThreshold默认 0.5(0~1,越大越不敏感)。

流媒体通道配有完整的安全与容量护栏(config.ts 与 media-stream.ts):

  • preStartTimeoutMs(默认 5000):未在时限内发出合法start帧的预认证连接将被关闭,防御闲置连接占用攻击;
  • maxPendingConnections(默认 32):最大并发待启动连接数;
  • maxPendingConnectionsPerIp(默认 4):单 IP 待启动连接上限;
  • maxConnections(默认 128):全部开放媒体流连接硬上限;
  • 发送缓冲上限 1MB(MAX_WS_BUFFERED_BYTES),防止背压失控。

2.6 语音合成(首发形态):OpenAI TTS + Twilio<Say>兜底

首发版本中,TTS 使用 OpenAI TTS(model/voice/instructions三个字段),Twilio 场景在流媒体不可用时以<Say>指令兜底。voice-mapping.ts 提供了一个重要的兼容层:将 OpenAI 语音名映射到 Twilio Polly 语音——例如alloy → Polly.Joanna、onyx → Polly.Brian、nova → Polly.Salli,未知名回退Polly.Joanna。这保证了同一套 voice 配置在流式 TTS 与 TwiML<Say>两种通道下声音风格一致。

2.7 工具 / 网关 RPC / CLI:三层控制面

CHANGELOG 首发条目标明三层操作入口,源码均有对应实现:

Agent 工具voice_call(五个 action):

Action参数用途
initiate_callmessage, to?, mode?发起外呼
continue_callcallId, message续话并等待回复
speak_to_usercallId, message单向播报
end_callcallId挂断
get_statuscallId查询状态

Gateway RPC(voicecall.initiate | continue | speak | end | status,另兼容遗留的voicecall.start):供网关侧程序化调用,参数与工具 action 一一对应。

CLI(注册于 cli.ts 的voicecall命令组):

命令必填参数说明
call--message,--to(可省略,回退配置toNumber)发起外呼,打印 JSON{callId}
start--tocall的兼容别名
continue--call-id--message播报并等待回应
speak--call-id--message只播报不等待
end--call-id挂断
status--call-id输出通话 JSON 状态
tail--file/--since/--poll实时 tail JSONL 通话日志
latency--file/--last汇总最近 N 条记录的 turn 延迟与监听等待时长(min/max/avg/p50/p95)
expose--mode off\|serve\|funnel启停 Tailscale serve/funnel 暴露

其中call与start的--mode默认值在 CLI 实现中是conversation(与配置默认notify不同),tail的默认日志路径为~/.openclaw/voice-calls/calls.jsonl,可由store配置覆盖——这些细节以 cli.ts 源码为准。

2.8 可观测性与响应控制

  • JSONL 通话日志:CallManager将每条通话记录(含 state、transcript、metadata 中的lastTurnLatencyMs等)追加写入calls.jsonl,CLIvoicecall tail与voicecall latency均基于该文件;
  • 响应控制:responseModel(默认openai/gpt-4o-mini)、responseSystemPrompt、responseTimeoutMs(默认 30000)三个参数控制 AI 自动应答的模型、提示与超时。

自动应答的语音输出采用严格的 JSON 契约:{"spoken":"..."}。response-generator.ts 展示了完整链路——以主叫号码归一化后的voice:<digits>作为 session key,复用与消息通道相同的嵌入式 Pi Agent 基础设施(runEmbeddedPiAgent),并通过VOICE_SPOKEN_OUTPUT_CONTRACT约束模型只输出可播报内容;随后extractSpokenTextFromPayloads会剔除代码围栏、isReasoning/isError负载以及 "Thinking process"、"Reasoning:" 等疑似元思考段落,只把干净语音文本交给 TTS。


三、2026.1.26:TTS 迁移与破坏性变更详解

2026.1.26是 CHANGELOG 中唯一标注Breaking的版本,共四条变更,全部围绕通话语音合成配置的重构:

3.1 核心变更:电话 TTS 迁移到messages.tts

Breaking: voice-call TTS now uses coremessages.tts(plugin TTS config deep-merges with core).

迁移后,通话中的流式语音由OpenClaw 核心的messages.tts配置统一驱动,插件自己的tts配置块仅作为覆盖层,通过deep-merge(深度合并)叠加到核心配置之上。

源码佐证在 telephony-tts.ts:createTelephonyTtsProvider先调用applyTtsOverride(coreConfig, ttsOverride),将插件tts配置与coreConfig.messages.tts执行deepMergeDefined深度合并(仅覆盖显式定义的字段,未定义字段保留核心默认值),随后把合并结果交给核心的textToSpeechTelephony运行时完成 PCM 到 mu-law 8kHz 的转换(convertPcmToMulaw8k),供电话线路播放。对应测试见 telephony-tts.test.ts 与 deep-merge.test.ts。

3.2 提供商范围收窄:OpenAI + ElevenLabs

Telephony TTS supports OpenAI + ElevenLabs; Edge TTS is ignored for calls.

迁移后,电话线路只支持OpenAI与ElevenLabs两家 TTS 提供商;核心 TTS 中可能配置的Edge(微软)TTS 在通话场景被显式忽略。插件级tts.openai(apiKey/baseUrl/model/voice/speed/instructions)与tts.elevenlabs(apiKey/baseUrl/voiceId/modelId/seed/voiceSettings/languageCode等)配置结构完整定义在 openclaw.plugin.json 的configSchema.tts中,供 UI 表单与配置校验直接使用。

3.3 废弃旧字段:tts.model/tts.voice/tts.instructions

Removed legacytts.model/tts.voice/tts.instructionsplugin fields.

首发版本中扁平的tts.model、tts.voice、tts.instructions三个顶层字段被移除,改由嵌套的tts.openai.*/tts.elevenlabs.*表达。升级时需要把旧配置改写为:

// 迁移前(已废弃) { tts: { model: "gpt-4o-mini-tts", voice: "alloy", instructions: "Speak naturally", }, } // 迁移后(deep-merge 到核心 messages.tts) { tts: { provider: "openai", // 或 "elevenlabs" openai: { model: "gpt-4o-mini-tts", voice: "alloy", instructions: "Speak naturally", apiKey: "sk-...", // 亦可走环境变量 }, }, }

3.4 ngrok 免费版绕过开关重命名并收紧

Ngrok free-tier bypass renamed totunnel.allowNgrokFreeTierLoopbackBypassand gated to loopback +tunnel.provider="ngrok".

旧的 ngrok 免费版兼容开关被重命名为tunnel.allowNgrokFreeTierLoopbackBypass,并增加两道门禁:

  • 仅当serve.bind为回环地址(127.0.0.1/::1/localhost,见 runtime.ts 的isLoopbackBind)时生效;
  • 仅当tunnel.provider === "ngrok"时生效。

其作用不是跳过签名校验,而是允许在 ngrok 免费版场景下信任转发头以重建用于签名的公网 URL(config.ts 的注释明确强调 "This does NOT bypass signature verification")。整体签名校验默认开启,skipSignatureVerification仅限开发环境使用。


四、生产级可靠性设计(源码佐证)

除 CHANGELOG 与 README 明确点名的功能外,仓库中还沉淀了一系列通话可靠性机制,值得在生产部署时关注:

  • Webhook 重放保护:README 声明对 Twilio/Plivo 提供重放保护,重复的合法回调会被安全忽略;Twilio 语音回合附带 per-turn token(turnToken),过期/重放的<Gather>回调无法完成新回合(见 types.ts 中NormalizedEvent的dedupeKey与turnToken字段)。
  • 通话持久化与重启恢复:manager.ts 的initialize会从calls.jsonl恢复活跃通话,向提供商核对真实状态(getCallStatus),重建 providerCallId 映射,并为已接通的通话重启maxDurationSeconds定时器;超过最大时长的旧通话会被直接清理。
  • 陈旧通话回收器(stale call reaper):webhook/stale-call-reaper.ts 每 30 秒扫描一次,超过staleCallReaperSeconds且未到终态的通话会被自动结束;默认0(禁用),生产环境官方建议 120~300 秒。
  • 流断开宽限窗口:Twilio 媒体流断线后不会立即挂断,而是留出约 2 秒宽限(STREAM_DISCONNECT_HANGUP_GRACE_MS),允许快速重连不中断通话(README Notes 亦有说明)。
  • notify 模式初始播报抑制 barge-in:外呼 conversation 模式的初始欢迎语播报期间临时抑制打断(barge-in),播报结束后恢复正常打断。
  • 流式 TTS 失败即失败:Twilio 流媒体激活期间不降级到<Say>兜底,流 TTS 失败会直接导致本次播放请求失败,避免两通道混用导致状态错乱(README Notes)。

五、快速上手:安装、配置与验证路径

以下为可直接落地的实操路径(详见 README):

5.1 安装

# 方式 A(推荐):通过 OpenClaw 安装,装完重启 Gateway openclaw plugins install @openclaw/voice-call # 方式 B(本地开发):复制到全局扩展目录 mkdir -p ~/.openclaw/extensions cp -R extensions/voice-call ~/.openclaw/extensions/voice-call cd ~/.openclaw/extensions/voice-call && pnpm install

5.2 最小配置(Twilio)

配置放在plugins.entries.voice-call.config下:

{ enabled: true, provider: "twilio", // "twilio" | "telnyx" | "plivo" | "mock" fromNumber: "+15550001234", // E.164 格式(正则 ^\+[1-9]\d{1,14}$) toNumber: "+15550005678", // 默认外呼号码 twilio: { accountSid: "ACxxxxxxxx", // 也可用环境变量 TWILIO_ACCOUNT_SID authToken: "your_token", // 也可用环境变量 TWILIO_AUTH_TOKEN }, serve: { // Webhook 内置服务器 port: 3334, // 默认 3334 bind: "127.0.0.1", // 默认回环地址 path: "/voice/webhook", // 默认路径 }, // 公网暴露三选一: // publicUrl: "https://example.ngrok.app/voice/webhook", // tunnel: { provider: "ngrok", ngrokAuthToken: "..." }, // tailscale: { mode: "funnel", path: "/voice/webhook" } outbound: { defaultMode: "notify" }, // notify | conversation streaming: { enabled: true, // 启用 OpenAI Realtime 流式 STT openaiApiKey: "sk-...", streamPath: "/voice/stream", preStartTimeoutMs: 5000, maxPendingConnections: 32, maxPendingConnectionsPerIp: 4, maxConnections: 128, }, }

各提供商密钥均支持环境变量注入(config.ts 的resolveVoiceCallConfig):TWILIO_ACCOUNT_SID/TWILIO_AUTH_TOKEN、TELNYX_API_KEY/TELNYX_CONNECTION_ID/TELNYX_PUBLIC_KEY、PLIVO_AUTH_ID/PLIVO_AUTH_TOKEN、NGROK_AUTHTOKEN/NGROK_DOMAIN。validateProviderConfig会在启动时校验所选提供商必需字段,缺失即报错(如 Telnyx 未配置publicKey且未开skipSignatureVerification会直接拒绝启动)。

5.3 发一条外呼并跟踪

# 发起通知型外呼(打印 {callId}) openclaw voicecall call --to "+15555550123" --message "Hello from OpenClaw" # 查看通话状态 openclaw voicecall status --call-id <id> # 实时跟踪 JSONL 通话日志(默认 ~/.openclaw/voice-calls/calls.jsonl) openclaw voicecall tail # 用 Tailscale funnel 暴露 webhook openclaw voicecall expose --mode funnel

5.4 验证路径

仓库为上述能力提供了完整的测试覆盖,是理解行为细节的最佳入口:

  • manager.closed-loop.test.ts——完整通话闭环状态机;
  • manager.inbound-allowlist.test.ts——入站 allowlist 策略;
  • manager.notify.test.ts 与 manager.restore.test.ts——notify 模式与重启恢复;
  • telephony-tts.test.ts 与 deep-merge.test.ts——TTS 深度合并;
  • webhook.test.ts、webhook-security.test.ts、webhook.hangup-once.lifecycle.test.ts——Webhook 处理与安全;
  • media-stream.test.ts、providers/stt-openai-realtime.test.ts——流媒体与实时转写;
  • providers/twilio.test.ts、providers/telnyx.test.ts、providers/plivo.test.ts、providers/mock.test.ts——四家提供商实现。

六、结语:从 CHANGELOG 看插件的设计取向

voice-call/CHANGELOG.md虽然篇幅精炼,却准确勾勒出该插件的设计取向:统一提供商抽象、双模式外呼状态机、严格的安全护栏(签名校验 / 重放防护 / 连接容量限制)、与核心 Agent 基础设施(Pi Agent、messages.tts)深度打通。理解 0.1.0 的功能矩阵与 2026.1.26 的 TTS 迁移,即可掌握该插件当前版本的配置心智模型——电话语音统一由核心messages.tts驱动,插件配置仅做增量覆盖;而对版本号与核心发行号的对齐策略,则提醒升级插件前先确认宿主 OpenClaw 版本满足>=2026.3.28的依赖要求。后续若需落地生产,建议以 README、openclaw.plugin.json(完整配置 schema)与 config.ts(默认值权威来源)三者互为参照。

  • 人工智能
  • 大模型
  • LLM 网关
  • AI Agent
  • 即时通讯

【免费下载链接】openclaw-zero-token

OpenClaw: Use All Major AI Models NO API Token! Claude/ChatGPT/Gemini/DeepSeek/Doubao/Grok/Qwen/Manus/Kimi

项目地址:https://gitcode.com/gh_mirrors/op/openclaw-zero-token
点击查看免费下载

相关推荐

上一篇:Android富文本处理终极指南:RichText库的完整使用教程
下一篇:如何在电脑上从零跑起Ryujinx:一个C写的Switch模拟器实操记录

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询