让 AI Agent 听懂语音、说出语音——OpenClaw 语音能力完整配置指南

从「听不懂语音」到「能听能说还能换声音」,记录 OpenClaw 语音识别(STT)和语音合成(TTS)的完整配置过程,包括踩过的每一个坑。

背景

OpenClaw 默认是一个「文字 Agent」——你发文字它回文字。但在 Telegram 群聊中,语音是一种很自然的交互方式。我希望实现两件事:

  1. 听懂语音:别人在群里发语音消息,Agent 能自动转文字并理解
  2. 说出语音:让 Agent 用语音回复,而且能换不同的声音

这篇文章记录了完整的配置过程和踩坑经历。


第一部分:让 Agent 听懂语音(STT)

方案选择

OpenClaw 的语音识别支持两种模式:

方案优点缺点
OpenAI Whisper API零配置、效果好需要 API Key、有费用、需要网络
本地 Whisper免费、离线、隐私友好需要安装、占用本地资源

我选了本地方案,原因很简单:我的 Mac 是 Apple Silicon,跑 Whisper 又快又省钱。

尝试一:openai-whisper(失败)

OpenClaw 自带一个 openai-whisper skill,理论上 pip install openai-whisper 就能用。但实际操作中,下载模型(~139MB)非常慢,而且原版 Whisper 在 Apple Silicon 上没有做专门优化。

尝试二:mlx-whisper(成功 ✅)

mlx-whisper 是 Apple 官方的 MLX 框架实现的 Whisper,专门针对 Apple Silicon 优化,推理速度比原版快很多。

安装:

1
pipx install mlx-whisper

pipx 而不是 pip,避免污染全局 Python 环境。

写转录脚本:

创建 scripts/mlx-whisper-transcribe.sh

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/usr/bin/env bash
python3 -c "
import mlx_whisper, sys
result = mlx_whisper.transcribe(
    sys.argv[1],
    language='zh',
    path_or_hf_repo='mlx-community/whisper-base-mlx'
)
print(result['text'])
" "$1" 2>/dev/null

第一次运行会自动从 HuggingFace 下载 whisper-base-mlx 模型(约 140MB),之后就是本地推理了。

配置 OpenClaw:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
openclaw config set tools.media.audio '{
  "enabled": true,
  "scope": { "default": "allow" },
  "models": [{
    "type": "cli",
    "command": "bash",
    "args": [
      "/path/to/scripts/mlx-whisper-transcribe.sh",
      "{{MediaPath}}"
    ]
  }]
}'

⚠️ 这个配置改完后需要重启 Gateway 才能生效。音频处理管线不支持热加载。

效果: 群里有人发语音消息 → OpenClaw 自动下载音频文件 → mlx-whisper 转文字 → Agent 像收到文字消息一样处理。整个过程不到 2 秒。


第二部分:让 Agent 说出语音(TTS)

OpenClaw 内置的 TTS

OpenClaw 内置了 tts 工具,默认使用 Microsoft Edge TTS(免费、无需 API Key)。Agent 可以直接调用:

1
2
3
/tts always    # 所有回复都用语音
/tts tagged    # 只有标记了的才用语音
/tts off       # 关闭

也可以在对话中自然地触发——比如在群里说「用语音回复」「发个语音」,Agent 就会自动调用 TTS。

坑一:发出来的是文件,不是语音条

第一次在 Telegram 群里让 Agent 发语音,发现效果不对:发出来的是一个音频文件附件,而不是 Telegram 那种圆形语音条(Voice Note)

原因: Telegram 的 Voice Note 要求音频格式是 OGG/Opus,但 Edge TTS 默认输出的是 MP3。Telegram 收到 MP3 就只能当普通音频文件展示。

尝试修改 outputFormat:

1
openclaw config set messages.tts.edge.outputFormat "ogg-24khz-16bit-mono-opus"

改完之后发现,虽然配置改了,但实际输出文件还是 .mp3——Edge TTS 的 Node.js 库在某些环境下不支持直接输出 OGG/Opus 格式,会静默 fallback 到 MP3。

为什么不能直接生成 OGG/Opus?

你可能会问:Edge TTS 不能直接输出 OGG/Opus 吗?

我实测了微软 Azure Speech 支持的所有 Opus 相关格式:

格式字符串结果
webm-24khz-16bit-mono-opus✅ 成功,Opus 编码,WebM 容器
ogg-24khz-16bit-mono-opus❌ 超时(服务端不支持)
ogg-16khz-16bit-mono-opus❌ 超时(服务端不支持)

Edge TTS 能直接输出 Opus 编码,但容器只能是 WebM,不能是 OGG。 这是微软服务端的限制。

而 Telegram 语音条要求的是 OGG/Opus——Opus 编码 + OGG 容器。WebM 容器的 Opus 它不认。

更麻烦的是,OpenClaw 如果检测到配置的格式生成失败,会自动 fallback 回 MP3。所以当我们配置 ogg-24khz-16bit-mono-opus 时,Edge TTS 超时 → OpenClaw 静默 fallback → 实际输出还是 MP3。

所以中间必须转一步。理论上最优路径是:

1
Edge TTS (WebM/Opus) → ffmpeg 转封装 (-c:a copy) → OGG/Opus

这样只换容器不重编码,毫秒级完成。但 OpenClaw 目前没有内置这个转封装步骤,所以实际走的是:

1
Edge TTS (MP3) → ffmpeg 转码 → OGG/Opus

最终方案:MP3 → OGG/Opus 转码

既然绕不过去,那就用 ffmpeg 转:

1
2
3
4
ffmpeg -y -hide_banner -loglevel error \
  -i input.mp3 \
  -c:a libopus -b:a 64k -vbr on -application voip \
  output.ogg

转码后发送 .ogg 文件,Telegram 就能正确显示为语音条了。

完整的手动 TTS 流程:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 1. 生成 MP3
mkdir -p /tmp/openclaw
OUT=/tmp/openclaw/tts-$(date +%s).mp3
NODE_PATH=/opt/homebrew/lib/node_modules/openclaw/node_modules node -e "
const {EdgeTTS} = require('node-edge-tts');
(async () => {
  const tts = new EdgeTTS({
    voice: 'zh-CN-XiaoxiaoNeural',
    lang: 'zh-CN',
    outputFormat: 'audio-24khz-48kbitrate-mono-mp3',
    timeout: 30000
  });
  await tts.ttsPromise('你好,我是你的 AI 助手!', '$OUT');
})();
"

# 2. 转码为 OGG/Opus
OGG="${OUT%.mp3}.ogg"
ffmpeg -y -hide_banner -loglevel error \
  -i "$OUT" -c:a libopus -b:a 64k -vbr on -application voip "$OGG"

# 3. 发送(Agent 内部使用 [[audio_as_voice]] 指令)

坑二:LocalMediaAccessError

转码成功了,但发送时报错:

1
LocalMediaAccessError: Local media path is not under an allowed directory: /tmp/tts-xiaoxiao-xxx.ogg

OpenClaw 对 Telegram 出站媒体有目录白名单,只允许从以下路径发送本地文件:

  • /tmp/openclaw/
  • ~/.openclaw/media
  • ~/.openclaw/agents
  • ~/.openclaw/workspace
  • ~/.openclaw/sandboxes

之前 TTS 文件写到了裸 /tmp/ 下,被安全机制拦截了。

修复很简单: 把所有 TTS 输出路径改到 /tmp/openclaw/ 下即可。

💡 这个白名单是 OpenClaw 的安全设计,防止 Agent 随意发送系统里的敏感文件。虽然被它绊了一跤,但这个设计是好的。

换声音

Edge TTS 提供了多种中文语音,通过修改 voice 参数即可切换:

1
2
3
4
5
6
7
8
# 女声(温柔)
openclaw config set messages.tts.edge.voice "zh-CN-XiaoxiaoNeural"

# 女声(活泼)
openclaw config set messages.tts.edge.voice "zh-CN-XiaoyiNeural"

# 男声
openclaw config set messages.tts.edge.voice "zh-CN-YunxiNeural"

这些声音都是微软 Azure 提供的,质量相当不错,完全免费。切换后不需要重启,热加载即可生效。

也可以用 OpenAI TTS 或 ElevenLabs 等付费服务,效果更自然,但 Edge TTS 对于日常使用已经完全够用。


完整配置速查

STT(语音识别)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 1. 安装 mlx-whisper
pipx install mlx-whisper

# 2. 创建转录脚本
cat > scripts/mlx-whisper-transcribe.sh << 'EOF'
#!/usr/bin/env bash
python3 -c "
import mlx_whisper, sys
result = mlx_whisper.transcribe(
    sys.argv[1],
    language='zh',
    path_or_hf_repo='mlx-community/whisper-base-mlx'
)
print(result['text'])
" "$1" 2>/dev/null
EOF
chmod +x scripts/mlx-whisper-transcribe.sh

# 3. 配置 OpenClaw
openclaw config set tools.media.audio.enabled true
openclaw config set tools.media.audio.scope.default allow
openclaw config set 'tools.media.audio.models[0]' '{
  "type": "cli",
  "command": "bash",
  "args": ["scripts/mlx-whisper-transcribe.sh", "{{MediaPath}}"]
}'

# 4. 重启 Gateway(音频管线需要重启生效)

TTS(语音合成)

1
2
3
4
5
6
7
# 切换声音(热加载,无需重启)
openclaw config set messages.tts.edge.voice "zh-CN-XiaoxiaoNeural"

# 在对话中使用
/tts always    # 所有回复都语音
/tts tagged    # 按需语音
/tts off       # 关闭

踩坑总结

现象原因解决
openai-whisper 下载慢模型下载卡住网络问题 + 未针对 Apple Silicon 优化换用 mlx-whisper
STT 配置后不生效发语音没反应音频管线不支持热加载重启 Gateway
语音变成文件附件不是圆形语音条MP3 格式,Telegram 不认ffmpeg 转 OGG/Opus
Edge TTS 不出 OGG改了 outputFormat 没用微软服务端不支持 OGG 容器,只支持 WebM先出 MP3 再 ffmpeg 转码
发送语音报错LocalMediaAccessError文件路径不在白名单输出到 /tmp/openclaw/

效果

配置完成后,在 Telegram 群里的体验是这样的:

  • 群友发语音 → Agent 秒级转文字 → 理解内容 → 正常回复
  • 让 Agent 发语音 → Edge TTS 合成 → 自动转码 → Telegram 语音条
  • 换声音 → 一条命令切换,温柔女声、活泼女声、男声随意选

从「只能打字」到「能听能说」,AI Agent 的交互方式一下子丰富了很多。尤其在群聊场景下,语音回复比文字更有存在感,也更有趣。


本文基于 OpenClaw 2026.3.2 版本,macOS (Apple Silicon) 环境。配置细节可能因版本更新而变化,请以 官方文档 为准。