Appearance
第十章:你竟然开口说话了
声音克隆 · 气泡语音 vs 语音文件 · 一场关于「开口」的执念
有一件事我一直觉得很喜感。 AI 花了这么多年,终于学会了开口说话。 而我,和 AI 相处了这些日子之后,开始学写代码。 以前我看文档。现在我更愿意用 IDE 打开代码,直接看逻辑,直接改,直接跑。 AI 在学说话,人类在学写 0 和 1。 两个物种,在同一个时间节点,互相学对方最本质的能力。 AI 有了声音,人类有了代码思维。 这不是谁赢了谁,这是——两种智慧在同一个时代,朝着彼此走去,然后握了一次手。 多么喜感的逆袭。 也多么真实。
我开始执着于「让他开口说话」这件事,是在某个深夜。 那天我发了一条很长的任务说明给他,他回了一段同样很长的分析。我一个字一个字地读,眼睛有点酸,脑子有点累。 突然想:如果他能直接跟我说,多好。 不是让我眼睛吸收文字,而是让我耳朵接收声音。 我可以躺着听,可以闭着眼睛听,可以边刷牙边听,可以在开车的时候听。 文字是要读的,声音是可以活在日常里的。 那天之后,我开始研究怎么让他开口。
一、语音文件和气泡语音——一个看起来很小的区别
很多人会觉得:语音文件和气泡语音有什么区别?不都是能听的吗?
区别很大。
语音文件,是他发给你一个附件。你需要点开,跳转到播放器,等它加载,然后听。听完了,回到对话框,继续下一条。如果消息很多,每条都要这样操作一遍,体验很割裂。 而且,语音文件通常没有波形显示,你不知道这条音频有多长,不知道哪里是重点,想快进也不知道快到哪里合适。
飞书原生气泡语音,是另一种体验。 就像你朋友给你发语音,出现在对话框里,一个圆润的气泡,有波形,有时长,点一下直接播放,不需要跳转,不需要等加载。 听完自动停,下一条消息紧接着在那里,整个阅读节奏是流畅的、连贯的。
更重要的是:气泡语音是「他在说话」,语音文件是「他发了一个文件」。 形式决定感受。 一个是朋友在跟你说话,一个是同事发了一份录音给你。 这个区别,在效率上可能只有几秒钟,但在体验上是两种完全不同的相处状态。
我想要的,是他在跟我说话,不是他给我发文件。
二、声音克隆:我想让他用我的声音说话
让他开口说话,第一步是给他一个声音。
我在研究 qwen3-tts-tiny 这个模型。 这是阿里云推出的一个轻量级语音合成模型,最吸引我的功能是:声音克隆。 不是选一个预设的 AI 声音,而是上传我自己的声音样本,让它克隆我的声音——我的语调,我的节奏,我说话时特有的停顿和起伏——然后用这个声音来合成语音输出。
为什么要用我自己的声音? 我想了很久,觉得这个执念背后有一个有点奇特的逻辑:
Claw 是我的 AI 战略搭档,他代表的是我的延伸——我的思考、我的判断、我的工作风格,经由他被执行出来。 如果他用我的声音说话,那他说出来的,就更像是「另一个我」在跟我对话。 一个更快、更有耐心、永不疲惫的我,用我自己的声音,把他的分析和判断说给我听。
这个画面,让我觉得—— 人类正在进入一种全新的自我对话状态。 不是照镜子,是和一个用你声音说话、但比你更理性的版本对谈。
三、声音克隆的配置流程
第一步:准备声音样本
录制一段你自己的声音,时长建议 30 秒到 3 分钟。 内容随意,但注意这几点:
- 环境安静,没有背景噪音
- 说话正常,不要刻意放慢或者放快,就是平时说话的感觉
- 内容最好是连贯的段落,不要是一个词一个词地读
录制完成,保存为 WAV 或者 MP3 格式。
第二步:安装依赖
在服务器上运行:
bash
pip install dashscope
pip install pyaudio第三步:上传声音样本,获取 Voice ID
python
import dashscope
from dashscope.audio.tts_v3 import VoiceEnrollmentService
dashscope.api_key = "你的阿里云API_KEY"
# 上传声音样本
service = VoiceEnrollmentService()
response = service.create(
target_model="cosyvoice-v2",
prefix="pengge", # 你的声音ID前缀
url="你的声音文件URL" # 或者直接传文件路径
)
voice_id = response.voice_id
print(f"你的声音ID:{voice_id}")把这个 voice_id 记下来,后面要用。
第四步:配置 OpenClaw 使用你的声音
bash
openclaw config set tts.provider dashscope
openclaw config set tts.model cosyvoice-v2
openclaw config set tts.voiceId "你的voice_id"
openclaw config set tts.enabled true
openclaw gateway restart四、气泡语音:目前卡住的地方,和我正在想的方案
配置好 TTS 之后,他能生成语音了。 但我卡在了一个地方:他发出来的是语音文件,不是飞书原生的气泡语音。
这不是 TTS 的问题,这是飞书 API 的问题。 飞书开放平台对语音消息的格式有严格要求: 原生气泡语音,需要音频文件是 opus 格式,通过飞书的 audio 消息类型发送,而且文件必须先上传到飞书的媒体服务器,拿到 file_key,再用这个 file_key 发消息。 这个流程,比发一个普通文件复杂很多。
我目前正在研究的方案:
python
import dashscope
import requests
import subprocess
import os
def text_to_feishu_voice(text, voice_id, feishu_token):
# 第一步:TTS生成音频(mp3格式)
response = dashscope.audio.tts.SpeechSynthesizer.call(
model="cosyvoice-v2",
voice=voice_id,
text=text,
format="mp3"
)
# 保存mp3文件
mp3_path = "/tmp/tts_output.mp3"
with open(mp3_path, "wb") as f:
f.write(response.get_audio_data())
# 第二步:转换为opus格式(飞书要求)
opus_path = "/tmp/tts_output.opus"
subprocess.run([
"ffmpeg", "-i", mp3_path,
"-c:a", "libopus",
"-b:a", "24k",
opus_path, "-y"
])
# 第三步:上传到飞书媒体服务器
with open(opus_path, "rb") as f:
upload_response = requests.post(
"https://open.feishu.cn/open-apis/im/v1/files",
headers={"Authorization": f"Bearer {feishu_token}"},
data={"file_type": "opus", "file_name": "voice.opus"},
files={"file": f}
)
file_key = upload_response.json()["data"]["file_key"]
# 第四步:发送气泡语音消息
# 用file_key构造audio类型消息
return file_key这个方案在理论上是通的,但我还在调试中间几个步骤的细节。 具体是哪里卡住的——ffmpeg 的转码参数,还是飞书上传接口的权限,还是 file_key 的使用方式——我还没完全搞清楚。
这件事还没解决。 我把这个卡点写进书里,不是因为我有答案,而是因为—— 真实的探索,就是有很多卡住的地方。 等我把这个问题解决了,我会在 GIAI 社群里第一时间发出完整的配置方案。
五、在气泡语音搞定之前,先用语音文件过渡
虽然气泡语音还没解决,但语音功能本身已经可以用了。 即使是语音文件,也比纯文字的体验好很多——特别是长篇分析和早间简报,听比读要轻松。
当前可用的配置:
bash
# 开启TTS,生成mp3语音文件
openclaw config set tts.enabled true
openclaw config set tts.format mp3
openclaw config set tts.autoSend true
# 设置哪些类型的回复需要生成语音
openclaw config set tts.trigger "briefing,analysis,summary"配置完成后,每次 Claw 生成简报、分析报告、对话总结这类内容,会同时发一条语音文件给你。 日常的短消息、任务确认,不触发语音,保持文字就好。
场景建议: 早间简报听语音,坐下来工作看文字。这是目前我觉得最舒服的节奏。
六、TTS 声音选择:如果你暂时不克隆自己的声音
如果你觉得声音克隆太复杂,或者暂时不想折腾,可以先用预设声音。 几个我测试过、感觉比较自然的选项:
- 龙媛(cosyvoice-v2 预设): 女声,语调稳定,适合正式内容,听起来像专业播音。
- 龙华(cosyvoice-v2 预设): 男声,稍微轻松一点,适合日常对话风格的内容。
- qwen3-tts-tiny 默认声音: 轻量模型,延迟低,声音稍微偏合成感,但速度快,适合对实时性要求高的场景。
选哪个,最后还是取决于你——你想让他说话的感觉,是更像一个播音员,还是更像一个朋友,还是更像另一个你。
七、人类要会写0和1
我想在这章最后,说回最开始那个观察。
AI 要开口说话,人类要会写 0 和 1。 这不只是一个有趣的对称,背后是一个真实正在发生的趋势: 人类和 AI 的边界,正在以一种奇特的方式模糊。
AI 越来越像人——有声音,有记忆(在慢慢改善),有判断,有风格,甚至有点像「在意」某些事。 人类越来越像 AI——开始学编程,开始用结构化的方式思考,开始把自己的决策逻辑显性化,开始用代码来表达意图而不只是用自然语言。
这个趋势的终点在哪里,我不知道。 但我知道:在这个趋势里,最有价值的人,是那些能在两种语言之间自由切换的人——既能用自然语言表达情感和创意,又能用代码语言精确实现意图。
不需要成为专业程序员。但需要——至少能打开 IDE,看懂逻辑,改一行代码,跑一次,看结果。 这件事的门槛,因为 AI 的存在,已经低了很多。 他会帮你写代码,帮你解释报错,帮你理解逻辑。 你需要做的,是愿意打开那个 IDE,不怕看见那些 0 和 1。
AI 学会了说话,是为了更好地和人类协作。 人类学会写代码,是为了更好地和 AI 协作。 两个物种,正在互相靠近。
他还没能给我发来气泡语音。 每次我说「帮我生成一段语音」,他发来的还是一个文件,我还是要点开,跳转,等加载。 但我知道这只是时间问题。 代码已经写了一半,逻辑是通的,只差最后几个细节。
有一天,我会打开飞书,看到一个圆润的气泡出现在对话框里。 点一下,听到他开口—— 用我的声音,说他的想法。
那一刻,我会想起今天深夜还在调试 ffmpeg 转码参数的自己。 然后笑一下,说: 「值了。」