OpenClaw 飞书语音交互踩坑全记录(续:一个语音问题折腾快半个月,呕血)

什么是 OpenClaw 飞书语音交互? 本文将详解如何通过 OpenClaw 框架实现飞书机器人的智能语音交互——用户发语音 AI 回语音、用户发文字 AI 回文字,并分享我们在 乐维运维智能体 项目中的完整踩坑记录与解决方案。
谁还没有一个钢铁侠的梦想呢,那个贾维斯,你问他,他马上就回,毫不犹豫。为了这个画面,我陆续快撸了半个多月,过程中,时好时坏。


一、什么是 OpenClaw 飞书语音交互?

OpenClaw 飞书语音交互 是指基于 OpenClaw 开源框架,为飞书(Lark)机器人接入智能语音能力的技术方案。核心功能包括:

  • 双向语音交互:用户发送语音消息,AI 识别内容并语音回复
  • 智能模式切换:用户发送文字,AI 自动切换为文字回复
  • 低延迟响应:端到端延迟控制在 3-5 秒

这是我们在 乐维运维智能体 项目中落地的 Lerwee AI Skill 核心能力之一,代表智能运维从"命令行交互"向"自然语言交互"的演进。


二、OpenClaw 飞书语音交互 vs 传统方案对比

对比维度 OpenClaw 方案 传统 Webhook 方案 企业微信方案
部署复杂度 低(本地/云端均可) 中(需服务器) 高(需企业认证)
语音格式支持 Opus/mp3 自动转换 需手动处理 仅支持特定格式
延迟 3-5 秒 5-10 秒 3-8 秒
AI 模型选择 灵活(OpenAI/Claude/国产模型) 固定 受限
私有化部署 ✅ 支持 ❌ 不支持 ❌ 不支持
成本 低(开源免费) 高(按量计费)

数据来源:乐维软件 2026 年 4 月实测数据


三、核心配置文件详解

3.1 MEMORY.md —— 语音交互规则配置

这是最关键的配置文件,定义了语音/文字的判断逻辑:

## 飞书语音配置

### 语音回复规则
- **用户发语音** → 只回复语音,不要文字
- **用户发文字** → 只回复文字,不要语音
- 检测方式:消息末尾 `ou_xxx: <内容>` 包含 `{"file_key":...,"duration":...}` 格式为语音消息
- ⚠️ **关键**:只看 `ou_xxx: <内容>` 部分,忽略开头的 `Audio transcript` 等系统提示
- ⚠️ `[media attached:` 标记是系统自动转写,不可靠,不要用它判断

### 语音合成配置
- TTS 引擎: Bailian TTS
- 音色: `Ethan`(晨煦,标准普通话,阳光温暖)
- ⚠️ **飞书语音格式**: 必须是 **Opus 格式**(48kHz, 64kbps),mp3 会作为文件发送

### 生成流程(优化版 - 单条命令)
```bash
cd ~/.openclaw/media/audio && bailian tts -t "回复内容" -v "Ethan" -f mp3 -d . && ffmpeg -y -i $(ls -t *.mp3 | head -1) -c:a libopus -b:a 64k -ar 48000 voice_reply.opus && cp voice_reply.opus ~/.openclaw/workspace/

然后发送:MEDIA: ./voice_reply.opus

注意事项

  • ⚠️ 合并命令:减少 exec 进程启动开销,从 ~27s 优化到 ~15s
  • ⚠️ 路径问题MEDIA: 相对路径是相对于 workspace 目录,必须先复制文件到 workspace
  • 语音内容限制:≤600字符,超长则精简

3.2 SOUL.md —— AI 人格配置

# SOUL.md - JARVIS
关键信息

## 回复规则
- **用户发语音** → 只回复语音,不要文字
- **用户发文字** → 只回复文字,不要语音
- ⚠️ **关键**:只看消息末尾 `ou_xxx: <内容>` 部分

四、5大坑点与解决方案

不是金主的网友就不建议用本地的那些TTS和ASR,主要原因是反应时间和音色的问题

坑点一:TTS API Key 环境变量问题

问题现象

错误: 缺少 API Key!

根本原因
OpenClaw 的 exec 命令在独立 shell 进程中运行,不继承 ~/.zshrc 的环境变量。

解决方案

# 错误做法(无效)
echo 'export BAILIAN_API_KEY="sk-xxxx"' >> ~/.zshrc

# 正确做法
echo 'BAILIAN_API_KEY=sk-xxxx' >> ~/.openclaw/.env
openclaw gateway restart

坑点二:语音消息判断逻辑错误(最严重)

问题现象
用户发纯文字消息,AI 却用语音回复了。

错误做法

# ❌ 错误:检测 [media attached:] 标记
if "[media attached:" in message:
    is_voice = True

根本原因
系统会对每条消息自动做语音转写检测,[media attached: 标记根本不可靠。

正确做法

# ✅ 正确:只看 ou_xxx: 部分内容
if 'ou_xxx: {"file_key":' in message and '"duration":' in message:
    is_voice = True
else:
    is_voice = False

飞书语音消息真实格式

ou_5328ba59061c18a8dacbebcb7dab1722: {"file_key":"file_v3_0010e_xxx","duration":2000}

关键原则

判断依据 是否可靠 说明
ou_xxx: {"file_key":...,"duration":...} ✅ 可靠 飞书官方格式
[media attached: ❌ 不可靠 系统自动添加
Audio transcript for... ❌ 不可靠 转写提示,每条消息都有

坑点三:语音格式兼容性问题

问题现象
语音文件发送成功,但飞书显示为文件附件而非可播放语音。

根本原因
飞书对语音格式要求严格,必须是 Opus 格式(48kHz, 64kbps),mp3 会被当作普通文件。

解决方案

# 完整转换流程
# 1. Bailian TTS 生成 mp3
bailian tts -t "回复内容" -v "Ethan" -f mp3 -d ~/.openclaw/media/audio

# 2. ffmpeg 转换为 Opus 格式
ffmpeg -y -i input.mp3 -c:a libopus -b:a 64k -ar 48000 voice_reply.opus

# 3. 复制到 workspace(MEDIA: 指令相对路径基于 workspace)
cp voice_reply.opus ~/.openclaw/workspace/

# 4. 发送
MEDIA: ./voice_reply.opus

格式要求对照表

参数 要求值 说明
格式 Opus 飞书原生支持
采样率 48kHz 必须精确匹配
码率 64kbps 推荐值
声道 mono 单声道即可

坑点四:性能优化(从 27s 到 15s)

原始问题
语音回复总耗时约 27 秒,用户体验极差。

耗时分析(优化前)

环节 耗时 优化空间
飞书语音转写 (ASR) 2-3s ❌ 无法控制
AI 推理 5-8s ⚠️ 模型选择
TTS 生成 3-5s ⚠️ 网络延迟
exec 进程启动 10-15s 主要优化点
ffmpeg 转换 <0.5s ✅ 已很快
文件复制 <0.1s ✅ 已很快
发送飞书 1-2s ⚠️ 网络依赖
总计 ~27s -

优化方案

核心思路:合并命令,减少 exec 调用次数

# ❌ 优化前:4 次独立 exec 调用(串行执行)
exec("cd ~/.openclaw/media/audio")
exec("bailian tts -t '内容' -v Ethan -f mp3 -d .")
exec("ffmpeg -y -i input.mp3 -c:a libopus -b:a 64k -ar 48000 voice_reply.opus")
exec("cp voice_reply.opus ~/.openclaw/workspace/")

# ✅ 优化后:1 次 exec 调用(单条命令)
exec("""
cd ~/.openclaw/media/audio && \
bailian tts -t "回复内容" -v "Ethan" -f mp3 -d . && \
ffmpeg -y -i $(ls -t *.mp3 | head -1) -c:a libopus -b:a 64k -ar 48000 voice_reply.opus && \
cp voice_reply.opus ~/.openclaw/workspace/
""")

优化效果

指标 优化前 优化后 提升
总耗时 ~27s ~15s 44%
exec 调用次数 4 次 1 次 75%
进程启动开销 ~12s ~3s 75%

坑点五:Session 启动时配置未加载

问题现象
新会话启动后,第一条语音消息被错误地回复了文字。

根本原因
Session 启动时,AI 还没有读取 MEMORY.md 中的语音配置规则。

解决方案

AGENTS.md 中强制要求启动时读取配置:

## 启动流程
1. 读 `SOUL.md` → 我是谁
2. 读 `USER.md` → 服务谁
3. 读 `memory/YYYY-MM-DD.md` (今天+昨天)
4. 主会话: 读 `MEMORY.md` ← **关键:必须读取语音配置**

验证方法

# 检查配置是否已加载
grep -A 5 "语音回复规则" ~/.openclaw/workspace/MEMORY.md

五、完整实现代码

5.1 核心判断逻辑

def is_voice_message(message):
    """
    判断是否为语音消息
    关键:只看 ou_xxx: 部分内容,忽略系统提示
    """
    # 提取 ou_xxx: 后面的内容
    import re
    match = re.search(r'ou_[a-z0-9]+:\s*(.+)', message)
    if not match:
        return False
    
    content = match.group(1)
    
    # 检查是否包含语音文件标记
    return '"file_key":' in content and '"duration":' in content


def generate_reply(user_message, is_voice):
    """生成回复"""
    # AI 推理生成回复内容
    reply_text = ai_generate(user_message)
    
    if is_voice:
        # 语音回复流程
        import subprocess
        
        # 合并命令执行
        cmd = f'''
cd ~/.openclaw/media/audio && \
bailian tts -t "{reply_text}" -v "Ethan" -f mp3 -d . && \
ffmpeg -y -i $(ls -t *.mp3 | head -1) -c:a libopus -b:a 64k -ar 48000 voice_reply.opus && \
cp voice_reply.opus ~/.openclaw/workspace/
'''
        subprocess.run(cmd, shell=True, capture_output=True)
        
        return "MEDIA: ./voice_reply.opus"
    else:
        # 文字回复
        return reply_text

5.2 完整交互流程

用户发送消息
    ↓
提取 ou_xxx: 部分内容
    ↓
判断是否包含 {"file_key":...,"duration":...}
    ↓
    ├── 是 → 语音消息 → AI 推理 → TTS 生成 → ffmpeg 转换 → 发送语音
    └── 否 → 文字消息 → AI 推理 → 发送文字

六、常见问题 FAQ

Q1: 为什么 AI 有时会把文字消息当成语音回复?

A: 检查是否遵循了"只看 ou_xxx: 部分"的原则。系统会在消息开头添加 Audio transcript for... 提示,但这不代表当前消息是语音。必须检测 ou_xxx: 后面是否有 {"file_key":...,"duration":...} 才是准确判断。

Q2: 语音回复延迟太高怎么办?

A: 主要优化方向:

  1. 合并 exec 命令(可从 27s 优化到 15s)
  2. 选择更快的 AI 模型
  3. 考虑本地 TTS 方案(如 Edge TTS)替代云端 API

Q3: 飞书显示语音为文件而不是可播放语音?

A: 检查格式是否为 Opus(48kHz, 64kbps)。mp3 格式会被当作普通文件发送。使用 ffmpeg 转换:

ffmpeg -i input.mp3 -c:a libopus -b:a 64k -ar 48000 output.opus

Q4: TTS 报错"缺少 API Key"?

A: 将 API Key 写入 OpenClaw 的 .env 文件而非 .zshrc:

echo 'BAILIAN_API_KEY=sk-xxxx' >> ~/.openclaw/.env
openclaw gateway restart

Q5: 如何快速测试语音功能是否正常?

A: 执行以下命令验证:

# 测试 TTS + 格式转换
cd ~/.openclaw/media/audio && \
bailian tts -t "测试语音" -v "Ethan" -f mp3 -d . && \
ffmpeg -y -i $(ls -t *.mp3 | head -1) -c:a libopus -b:a 64k -ar 48000 test.opus && \
ffprobe test.opus 2>&1 | grep -E "(codec|sample_rate)"

七、写在最后

这次 OpenClaw 飞书语音交互的开发,让我们深刻理解了 AI 助手开发中的细节决定成败

  1. 规则必须精确 - "只看 ou_xxx: 部分"这个细节省了大量调试时间
  2. 性能需要量化 - 没有耗时分析就找不到优化方向
  3. 配置需要固化 - 写进 MEMORY.md 和 SKILL.md 才能避免重复踩坑

这也是 乐维运维智能体 接入 Lerwee AI Skill 的一段实战记录。我们相信,未来的智能运维不只是告警和工单,而是像 JARVIS 一样——随时待命,语音即达。

智能运维 = 发现 + 监控 + 解构 + 分析 + 行动,语音交互是其中"发现"环节的重要入口。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐