OpenClaw 接入 Gradium 语音合成:安装、配置与多表面音频输出实战指南
【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 🦞项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw
Gradium 是 OpenClaw 的官方外部 TTS(Text-to-Speech)插件之一,为 Agent 的对外回复提供标准 WAV 音频、语音消息(voice note)兼容的 Opus 输出,以及面向电话(telephony)场景的 8 kHz u-law 音频。本文以 docs/providers/gradium.md 为主线,结合仓库内 extensions/gradium 插件的源码与测试用例,完整讲解 Gradium 的安装、密钥配置、声音管理、逐条消息换声指令与输出格式选择机制,读完即可在 OpenClaw 中把 Gradium 稳定地用起来。
Gradium 提供方概览
Gradium 是一个面向 OpenClaw 的文本转语音服务提供方,它只负责语音合成这一件事:把文本渲染成标准音频回复(WAV)、语音消息兼容的 Opus 输出,以及用于电话交互表面的 8 kHz u-law 音频。其核心属性如下:
| 属性 | 值 |
|---|---|
| Provider id | gradium |
| 认证方式 | GRADIUM_API_KEY环境变量或配置项apiKey |
| Base URL | https://api.gradium.ai(默认) |
| 默认声音 | Emma(YTpq7expH9539ERJ) |
在 OpenClaw 的 TTS 提供方矩阵(见 docs/tools/tts.md)中,Gradium 被标注为支持语音消息(voice-note)与电话(telephony)输出的提供方,其输出格式能力与本文后面「输出格式」一节完全对应。
安装插件
Gradium 是官方外部插件,安装后需要重启 Gateway 才会生效:
openclaw plugins install @openclaw/gradium-speech openclaw gateway restart插件安装包名为@openclaw/gradium-speech,从插件清单文档 docs/plugins/reference/gradium.md 可以看到它还可以通过 ClawHub 路由安装:clawhub:@openclaw/gradium-speech。
从源码看,插件入口 extensions/gradium/index.ts 通过definePluginEntry注册,在register(api)阶段调用api.registerSpeechProvider(buildGradiumSpeechProvider())把 Gradium 语音提供方挂载到 OpenClaw 的 speechProviders 契约上;插件的 openclaw.plugin.json 声明了契约speechProviders: ["gradium"]、启动时不激活(activation.onStartup: false),并声明其依赖的环境变量为GRADIUM_API_KEY,方便openclaw doctor之类的工具做配置体检。
密钥与认证配置
创建 Gradium API Key 后,通过环境变量或配置键暴露给 OpenClaw。配置键优先于环境变量:从 speech-provider.ts 的实现看,resolveGradiumApiKey先取配置中的apiKey,为空时才回退到process.env.GRADIUM_API_KEY。
环境变量方式:
export GRADIUM_API_KEY="gsk_..."配置键方式(~/.openclaw/openclaw.json):
{ tts: { auto: "always", provider: "gradium", providers: { gradium: { apiKey: "${GRADIUM_API_KEY}", }, }, }, }apiKey支持${ENV}形式的变量引用,也支持 SecretRef。无论哪种方式,只要拿不到有效密钥,合成请求都会以Gradium API key missing失败——这一点由 speech-provider.test.ts 与第 175-186 行的测试用例直接验证:没有密钥时isConfigured返回false,synthesize直接抛错且不会发出任何网络请求。
完整配置与参数说明
在全局tts配置块下把 Gradium 设为默认提供方:
{ tts: { auto: "always", provider: "gradium", providers: { gradium: { speakerVoiceId: "YTpq7expH9539ERJ", // apiKey: "${GRADIUM_API_KEY}", // baseUrl: "https://api.gradium.ai", }, }, }, }| 配置键 | 类型 | 说明 |
|---|---|---|
tts.providers.gradium.apiKey | string | 解析后的 API 密钥,支持${ENV}变量引用和 secret refs。 |
tts.providers.gradium.baseUrl | string | api.gradium.ai上的 HTTPS Gradium API URL,尾部斜杠会被去除。默认https://api.gradium.ai。 |
tts.providers.gradium.speakerVoiceId | string | 未出现指令覆盖时使用的默认声音 id。 |
源码中的配置归一化与安全校验
配置并不是拿来即用的,插件在读取时会做严格的归一化和白名单校验,实现位于 shared.ts 的normalizeGradiumBaseUrl:
- 空值回退到默认
https://api.gradium.ai; - 必须是合法 URL,否则报
Gradium baseUrl must be a valid https URL; - 协议必须是
https:(http://api.gradium.ai会被拒绝); - 主机名必须精确等于
api.gradium.ai,连https://api.gradium.ai.example.com这类后缀伪装域名也会被拒绝; - 会清空 URL 中的用户名、密码、query 与 hash,并去掉末尾斜杠。
安全边界不止停留在配置层。tts.ts 中实际发请求时通过fetchWithSsrFGuard并显式传入policy: { hostnameAllowlist: [GRADIUM_API_HOSTNAME] },在传输层再次锁定出站域名,避免未来的配置校验放宽意外扩大凭据外泄面。测试 speech-provider.test.ts 验证了:把baseUrl指向非 Gradium 域名时,合成在发出 API Key 之前就会被拦截,fetch根本不会被调用。
输出格式不可配置
输出格式由目标表面(target surface)自动决定,不能在openclaw.json中配置——这一点在 docs/providers/gradium.md 中明确说明,也与源码一致:synthesize与synthesizeTelephony各自写死输出格式,提供方不会合成其他格式。
内置声音列表与默认声音
| 名称 | Voice ID |
|---|---|
| Arthur | 3jUdJyOi9pgbxBTK |
| Christina | 2H4HY2CBNyJHBCrP |
| Emma(默认) | YTpq7expH9539ERJ |
| John | KWJiFWu2O9nMPYcR |
| Kent | LFZvm12tW_z0xfGo |
| Sydney | jtEKaLYNn6iif5PR |
| Tiffany | Eu9iL_CYe8N-Gkx_ |
这 7 个声音在源码中定义为常量表 shared.ts(GRADIUM_VOICES),默认声音DEFAULT_GRADIUM_VOICE_ID与文档一致。插件通过voices与listVoices把它们暴露给 OpenClaw,供 TTS 指令、状态查询等场景使用。
逐条消息换声(voice override)
当当前语音策略允许声音覆盖时,可以在消息中内联使用指令 token 切换声音,以下写法完全等价,取值都是 Gradium 原生的 voice id:
/voice:LFZvm12tW_z0xfGo /voice_id:LFZvm12tW_z0xfGo /voiceid:LFZvm12tW_z0xfGo /gradium_voice:LFZvm12tW_z0xfGo /gradiumvoice:LFZvm12tW_z0xfGo如果语音策略禁用了声音覆盖,该指令会被消费但直接忽略。从源码看,指令解析实现在 speech-provider.ts 的parseDirectiveToken:只有voice、voice_id、voiceid、gradium_voice、gradiumvoice这五个键被识别;当policy.allowVoice为假时返回handled: true但不带任何 overrides,从而做到“消费但忽略”;允许时则把当前覆盖集合并入voiceId。合成时 speech-provider.ts 会优先采用req.providerOverrides?.voiceId,其次才回退到配置的默认声音——这也解释了「无指令覆盖时使用默认声音」的语义。telephony 测试用例(speech-provider.test.ts)同样验证了 override 的 voice id 会原样进入请求体。
输出格式:按目标表面自动选择
Gradium 的输出格式由目标表面决定,提供方不会合成其他格式:
| 目标 | 格式 | 文件扩展名 | 采样率 | 语音兼容标志 |
|---|---|---|---|---|
| 标准音频 | wav | .wav | provider 决定 | 否 |
| 语音消息 | opus | .opus | provider 决定 | 是 |
| 电话 | ulaw_8000 | 无 | 8 kHz | 不适用 |
源码中的选择逻辑非常直白:speech-provider.ts 的synthesize判断req.target === "voice-note",是则用opus(voiceCompatible: true,扩展名.opus),否则用wav(扩展名.wav);synthesizeTelephony固定使用ulaw_8000,采样率8_000Hz。
在 OpenClaw 的整体 TTS 输出体系(docs/tools/tts.md 的「Output formats」一节)中,Gradium 的定位是:普通音频附件出 WAV,语音消息目标出 Opus,Talk/电话场景出 8 kHzulaw_8000。OpenClaw 的语音消息投递是通道能力驱动的,通道插件会广告是否要求原生 voice-note 目标,以及在发送前是否对非原生输出做转码。
底层合成请求实现
Gradium 的合成请求在 tts.ts 的gradiumTTS中实现,把文本发给 Gradium 的 TTS 端点:
- 端点:
POST {baseUrl}/api/post/speech/tts,默认即https://api.gradium.ai/api/post/speech/tts; - 请求头:
x-api-key(API Key)与Content-Type: application/json; - 请求体:
{ "text": "要合成的文本", "voice_id": "YTpq7expH9539ERJ", "only_audio": true, "output_format": "wav", "json_config": "{\"padding_bonus\":0}" }测试 tts.test.ts 逐字段断言了这个请求体(text、voice_id、only_audio: true、output_format、json_config为字符串化的{"padding_bonus":0})。
响应处理同样有一系列防护:
- 超时:请求携带
timeoutMs(来自请求上下文,未显式配置时 OpenClaw 的tts.timeoutMs默认为30000毫秒); - 字节上限:音频响应用
readProviderBinaryResponse流式读取并限制最大字节数,默认DEFAULT_TTS_MAX_BYTES = 16 * 1024 * 1024(16 MB),也可由请求的媒体大小上限(mediaMaxMb之类的配置)收紧。测试 speech-provider.test.ts 验证了超过上限时报Gradium TTS audio response exceeds ...; - 错误处理:JSON 错误会解析出
message并附带x-request-id,例如Gradium API error (401): Invalid API key [request_id=grad_req_123](见 tts.test.ts);非 JSON 错误体则回退到原文;错误响应体的读取也被封顶,避免整体消费超大响应; - 成功响应校验:即使 HTTP 200,如果内容不是合法的音频响应(如 JSON 错误页、HTML 登录页、空音频),也会以
Gradium API error: malformed audio response拒绝(见 tts.test.ts)。
自动选择顺序与多提供方回退
在 OpenClaw 已配置的多个 TTS 提供方中,Gradium 的自动选择顺序(auto-select order)为30。当tts.provider没有固定时,OpenClaw 会按注册表自动选择顺序挑选第一个已配置的提供方;多个提供方都已配置时,选中的提供方优先,其余作为回退(fallback)选项。该值在源码 speech-provider.ts 中定义为autoSelectOrder: 30,与文档完全一致。
关于提供方选择、回退链、/tts指令与ttsagent 工具的完整行为,请参阅 Text-to-Speech 文档;Gradium 插件的分发信息(包名、安装路由、契约面)见 Gradium 插件参考。如果要让某个 Agent、频道或账号单独使用 Gradium 的声音,还可以借助agents.entries.*.tts、channels.<channel>.tts等层级覆盖机制,在共享全局凭据的同时局部切换提供方与声音。
小结
在 OpenClaw 中使用 Gradium 只需四步:安装@openclaw/gradium-speech插件并重启 Gateway、配置GRADIUM_API_KEY、在tts.providers.gradium下设置默认声音与可选baseUrl、再把tts.provider固定为gradium。之后 OpenClaw 会按目标表面自动选择 WAV(标准音频)、Opus(语音消息)或 8 kHz u-law(电话)输出,并支持通过/voice:等五种等价指令逐条消息换声。插件源码在 extensions/gradium 目录下,其配置校验、域名白名单、字节上限与错误处理测试(speech-provider.test.ts、tts.test.ts)可作为排查合成失败与安全边界问题时的第一手依据。
【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 🦞项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考