natural-voice 是做什么的?
大多数“机器感”的 ElevenLabs 语音并非声音问题,而是脚本问题。模型会严格按照给定的文字朗读,而一个为眼睛阅读而写的脚本(标题式短句、句号结尾的片段、数字、破折号)无论由哪个声音朗读,都会显得断断续续。
本文件夹中的三个工具是实际可运行的。请使用它们,不要仅凭阅读文本来判断自然度。
python3 speakable.py script.txt # 这段文字是为耳朵写的吗?
python3 takes.py script.txt --voice VOICE_ID # 带种子的版本(付费,会先询问)
python3 gaps.py takes/ # 根据句内停顿长度对版本排序
这三个工具均为纯 Python 3.9+ 编写,无需额外安装包。gaps.py 如果系统 PATH 中有 ffmpeg,则会用它来对照音频本身确认停顿。
工作流程
1. 在更改任何内容之前先做诊断。 如果已有音频版本,请对其运行 gaps.py。句子内部(不在逗号或句号之后)超过 0.2 秒的停顿,正是人们听到的“AI 感”。在我们自己的原始版本中,声音在“run”之前停顿了 0.3 秒,又在“Instagram”之前停顿了一次,正好在核心吸引点中间。我们的编辑并没有导致这个问题:停顿存在于原始文件中。
2. 为耳朵重写脚本。 运行 speakable.py 并修复每个标记项。规则如下:
- 用句子,不用标题。 “13 free Claude skills now run your Instagram.” 是一个标题。“Thirteen free Claude skills run your whole Instagram.” 才是人说的话。
- 列表用逗号,不用句号。 “Reels. Captions. Carousels.” 会让模型停顿三次。“reels, captions, carousels, stories” 则流畅自然。
- 数字用文字表达 在口语行中:“eighty-four out of a hundred”,而不是“84 out of 100”。屏幕上的文字可以保留数字。
- 使用缩略形式(you‘ve, it’s, we‘ll)。没人会大声说“you have”。
- 用“so”、“and”、“then”连接片段。连接词是提示模型继续读下去的线索。
- 不要使用破折号。 ElevenLabs 把破折号当作短暂停顿,且官方表示“不够稳定”。用逗号保持连贯,或用省略号制造停顿感。
- 不要使用 SSML。 Eleven v4 或 v3 不支持
<break time=“1s”/>。
3. 指导语气。 Eleven v4 支持方括号内的音频标签。在每一段开始处放一个标签,不要每行都放,并确保标签与该行内容匹配。标签列表见 tags.md。speakable.py 会标记它不认识的标签,因为未知标签可能会被当作音效读出来。
[excited] Thirteen free Claude skills run your whole Instagram.
[mischievously] So we let it write this Reel...
标点符号也是指导手段。省略号增加有分量的停顿,感叹号增加能量,大写字母增加强调(只用在最重要的那个词上,一次就好)。
4. 设置参数。 在 eleven_v4 模型上:
| 设置 | 数值 | 原因 |
|---|---|---|
| stability | 0.30 到 0.40 | 较低的数值带来“更广泛的情感范围”;默认值 0.5 更平淡。低于 0.3 时版本可能会漂移。 |
| similarity_boost | 0.75 | 默认值;保持声音本身 |
| style | 0 | 默认值;其他值会增加延迟 |
| speed | 1.0 到 1.08 | 允许范围是 0.7 到 1.2;社交媒体配音通常略高于 1 |
5. 三个版本,相同文本,不同种子。 只生成一个版本就像掷硬币。分别用种子 1、2、3 运行 takes.py,然后用 gaps.py 排序。听前两个,凭耳朵选择。保留种子值:它能让重新生成时接近相同的版本(ElevenLabs 称其为“尽力而为”,并非绝对保证)。
6. 温和地剪辑。 如果剪辑软件会修剪静音段,请在每个句子后保留大约一秒,在每个逗号后保留大半秒。每次都将停顿剪成同样短的时长,是另一种听起来像机器制造的原因。
7. 听起来仍然像生成的? 停止调参数。用手机录下自己说这句话的音频,然后通过 ElevenLabs 的 Voice Changer(语音转语音)将其转换成你想要的语音。你的节奏、重音和情感会保留下来;只有声音被替换。
我们测量的数据
在我们自己的一个 Reel 上(文件在 examples/ 目录中):
| 之前 | 之后 | |
|---|---|---|
| 脚本 | 为眼睛写的:片段、数字 | 为耳朵写的:speakable.py 检查通过 |
| 标签 | 无 | [excited], [mischievously] |
| 设置 | stability 0.5, speed 1.0 | stability 0.35, speed 1.05 |
| 版本数 | 1 | 3 个种子,由 gaps.py 排序后凭耳朵挑选 |
speakable.py | 65 分,需要重写(句号分隔的列表、数字、无标签) | 100 分,适合朗读 |
| 句内停顿 | 在核心吸引点中,“now”和“run”之间停顿 0.34 秒 | 无 |
声音也变了(从 Will 变成 Chris),所以这并非单一变量的实验室测试。脚本重写是我们能听到的最大改进。
规则
- 绝不发出付费请求而不说明花费。
takes.py会打印字符数并停止,除非你传入--yes参数。 - 绝不打印或提交 API 密钥。
takes.py仅从环境变量ELEVENLABS_API_KEY中读取密钥。 - 进行标注。 如果语音是生成的,请打开平台的 AI 标签。