Tortoise TTS 声音自定义实战指南:基于参考片段打造你自己的多说话人音色
Tortoise TTS 声音自定义实战指南:基于参考片段打造你自己的多说话人音色
Tortoise 是一个以"多说话人"与"真实韵律语调"为核心设计目标的开源 TTS 系统,它不依赖为某个固定声音单独训练模型,而是通过读取你提供的参考音频(reference clips)实时"学会"目标说话人的音色。本文以仓库自带的 voice_customization_guide.md 为主线,结合源码实现,完整讲解参考片段的作用机制、新声音的添加流程、高质量参考片段的挑选准则,以及通过 CLI 与 API 调用自定义声音的完整实战方法。
一、参考片段:Tortoise 多说话人机制的核心
Tortoise 从设计之初就是一个多说话人模型(multi-speaker model)。与单说话人 TTS 不同,它不需要为每个新声音重新训练,而是通过参考片段(reference clips) 来引导语音生成。
参考片段是你提供的、包含目标说话人声音的录音。从 voice_customization_guide.md 的说明可以确认,这些片段会决定输出音频的多个属性:
- 声音本身:音高(pitch)与语调(tone);
- 语速:说话的快慢节奏;
- 发声缺陷:甚至包括口齿不清(lisp)或口吃(stuttering)这类特征;
- 非语音属性:音量大小、背景噪声、录音质量、混响(reverb)等。
也就是说,参考片段不仅决定了"像不像",还决定了"环境听起来怎样"。这在源码层面有清晰的印证:在 tortoise/utils/audio.py 中,load_voice() 会把 voices/<voice>/ 目录下的每个音频文件以 22050 Hz 的采样率加载为波形张量;随后 tortoise/api.py 的 get_conditioning_latents() 会将这些波形转化为一对条件潜变量(conditioning latents):
- 自回归条件潜变量:由自回归模型(
UnifiedVoice)从format_conditioning()生成的 Mel 频谱中提取。format_conditioning()会把片段截取/补齐到固定长度cond_length = 132300,对应 22050 Hz 下约 6 秒(见 tortoise/api.py); - 扩散条件潜变量:将片段重采样到 24000 Hz、截断/补齐到
102400个采样点后,经 TacotronSTFT 生成 Mel 频谱,再由扩散解码器(DiffusionTts)提取(见 tortoise/api.py)。
这两个潜变量会分别注入自回归解码与扩散解码两个阶段,最终由 UniVNet 声码器还原为 24 kHz 的音频波形。因此,"参考片段决定输出音色"不是一个模糊的说法,而是模型前向推理中真实参与计算的输入信号。
补充说明:当不指定任何声音(
--voice random)时,load_voice()会返回(None, None),推理改用随机潜变量生成器(get_random_conditioning_latents(),见 tortoise/api.py),此时输出的是模型自带的"随机音色",而非参考某个说话人。
二、内置声音一览:train_ 前缀的声音为什么效果更好
仓库 tortoise/voices 目录下预置了多套声音,每套声音对应一个子目录,子目录内是若干条参考音频(WAV/MP3 格式)。根据 voice_customization_guide.md 的说明:
- 以
train_开头的声音(如train_atkins、train_dotrice、train_grace、train_kennard、train_dreams、train_empire、train_lescault、train_mouse、train_daws等)来自模型训练集,因此合成质量明显优于其他声音; - 如果你的目标是最高质量的输出,优先从
train_系列中选择; - 如果你想体验 Tortoise 的**零样本模仿(zero-shot mimicking)**能力,则可以使用其余声音(如
angie、daniel、deniro、emma、freeman、geralt、halle、jlaw、pat、tom、weaver、william、mol、rainbow等)——它们仅凭几条参考音频就能复现说话人的音色。
这一点与源码中的加载逻辑一致:get_voices()(见 tortoise/utils/audio.py)会把 tortoise/voices 下每个子目录扫描为候选声音,并把其中的 .wav、.mp3、.pth 文件收集为该声音的素材。
三、添加新声音:六步完整实操
按照 voice_customization_guide.md 的步骤,为 Tortoise 添加一个新声音只需要以下六步:
第 1 步:收集说话人的音频片段
好的音频来源包括:
- YouTube 采访:可以使用
youtube-dl等工具抓取音频; - 有声书(audiobooks);
- 播客(podcasts)。
选材的具体质量标准见下一节,这里先保证"有足够数量、足够干净"的原始素材。
第 2 步:裁剪为约 10 秒的片段
- 把原始录音切分成约 10 秒的短片段;
- 至少准备 3 条片段;更多更好,但作者实际测试中最多只用过 5 条(见 voice_customization_guide.md)。
从源码可以理解 10 秒这个数字的来源:
format_conditioning()对每条片段只取132300个采样点(22050 Hz × 6 秒),多余的尾部会被随机裁剪;而扩散分支则把片段对齐到102400采样点(约 4.3 秒)。片段过长并不会带来额外信息,过短则信息不足。
第 3 步:保存为指定格式的 WAV 文件
- 格式:浮点格式(floating point)的 WAV;
- 采样率:22,050 Hz。
这与 load_audio() 的加载约定完全吻合:load_wav_to_torch() 对 np.float32 类型按 1.0 归一化,并把音频重采样到目标采样率(见 tortoise/utils/audio.py)。
第 4 步:在 voices/ 下创建子目录
在仓库的 tortoise/voices 目录下新建一个子目录,子目录名就是你的"声音名"。例如新建 tortoise/voices/my_speaker/。
第 5 步:放入音频片段
把第 2、3 步准备好的 WAV 片段放入该子目录,例如:
tortoise/voices/my_speaker/
├── 1.wav
├── 2.wav
└── 3.wav
get_voices() 会自动发现这个目录——它扫描 BUILTIN_VOICES_DIR(即 tortoise/voices)下所有子目录(见 tortoise/utils/audio.py),所以不需要修改任何配置文件。
第 6 步:通过 --voice 参数调用
运行 Tortoise 工具时使用 --voice=<你的子目录名>:
python scripts/tortoise_tts.py -o my_speaker_hello.wav -v my_speaker "Hello, this is my custom voice."
首次加载时,load_voice() 会在你放音频的目录下自动生成一个 <voice>.pth 缓存文件(保存的是计算好的条件潜变量,见 tortoise/utils/audio.py),后续推理会直接复用,无需重复计算。
验证方法:先运行 --list-voices 列出所有可用声音,确认你的子目录名已被识别:
python scripts/tortoise_tts.py --list-voices
如果名字不在列表中,scripts/tortoise_tts.py 会直接报错 voice <name> not available, use --list-voices to see available voices(见 scripts/tortoise_tts.py),因此强烈建议把这一步作为新声音的"验收测试"。
四、挑选高质量参考片段:六条准则
参考片段对输出有决定性影响,因此选材质量远比数量重要。以下是 voice_customization_guide.md 给出的六条准则及其背后的原因:
- 避免带背景音乐、噪声或混响的片段。这类片段已被从训练数据集中剔除,Tortoise 对它们的处理效果不可靠;
- 避免演讲录音(speeches)。扩音系统通常会给这类录音引入失真(distortion);
- 避免电话通话录音。电话的窄带频响与信道压缩会严重污染音色特征;
- 避免大量口吃、结巴,或频繁出现 "uh"、"like" 等口头禅的片段。这些发声缺陷会被参考片段"传染"给输出——因为参考片段本身就决定了输出的语速与缺陷特征;
- 尽量寻找与期望输出风格一致的朗读方式。例如你想让目标声音"读有声书",就尽量找 TA 朗读书籍的片段;想让它做新闻播报,就找新闻播报类素材。说话风格本身也是从参考片段中习得的;
- 片段文字内容无关紧要,但文字多样性似乎能带来更好效果。素材间文本差异越大,模型越能学到稳定的、与文本无关的声学特征。
把这六条准则对照第一节的机制可以更好地理解:参考片段决定了音量、背景噪声、录音质量与混响等"环境属性",所以一条干净、无混响的素材,会让你的输出听起来同样干净。
五、使用自定义声音:CLI 与 API 完整调用
5.1 CLI 方式(scripts/tortoise_tts.py)
仓库提供了功能完整的命令行入口 scripts/tortoise_tts.py,与 --voice 相关的关键参数如下:
| 参数 | 说明 |
|---|---|
-v, --voice |
选择声音。默认 random;用 & 连接两个声音进行声音融合;用逗号分隔多个声音进行多声音批量推理;设为 all 使用全部声音 |
-V, --voices-dir |
额外声音目录(逗号分隔可传多个),用于加载 tortoise/voices 之外的声音库 |
-p, --preset |
质量预设:ultra_fast / fast / standard / high_quality,默认 fast |
-l, --list-voices |
列出所有可用声音并退出 |
-P, --play |
直接播放音频(需安装 pydub) |
-o, --output |
输出到单个文件 |
-O, --output-dir |
输出到目录,按文本分段保存为独立剪辑(多声音/多候选时必须使用) |
--candidates |
每个声音生成的候选数量,默认 1;只有第一个候选会进入合并输出 |
--regenerate |
逗号分隔的剪辑编号列表,用于重新生成特定片段 |
--skip-existing |
跳过已存在的剪辑,用于断点续跑 |
--seed |
随机种子,用于复现结果 |
--text-split |
文本切分长度,格式 <desired_length>,<max_length> |
典型用法示例(取自 scripts/tortoise_tts.py 的 usage examples):
# 用随机声音朗读并保存到文件
python scripts/tortoise_tts.py -o hello.wav "Hello, how are you?"
# 从 stdin 读取文本,用 tom 声音播放
echo "Say it like you mean it!" | python scripts/tortoise_tts.py -P -v tom
# 用 tom、emma 两个声音朗读文本文件,输出到目录
python scripts/tortoise_tts.py -O /tmp/tts-results -v tom,emma < textfile.txt
使用你的自定义声音:
# 输出单文件
python scripts/tortoise_tts.py -o out.wav -v my_speaker "Your custom text here"
# 用 & 把自定义声音与内置声音融合
python scripts/tortoise_tts.py -o fused.wav -v "my_speaker&geralt" "Text to speak"
# 通过 --voices-dir 从仓库外加载声音库
python scripts/tortoise_tts.py -o out.wav -v my_speaker -V /path/to/extra_voices "Text"
输出细节(见 scripts/tortoise_tts.py):
- 使用
--output-dir时,每个文本段生成<voice>_<idx>_<candidate>.wav,并额外合成<voice>_combined.wav; - 无论哪种输出方式,最终音频均以 24000 Hz 采样率保存(
torchaudio.save(..., 24000)),与tts()返回的 24 kHz 波形一致(见 tortoise/api.py)。
5.2 声音融合与多声音推理
&融合:如-v "my_speaker&emma",会将两个声音的条件潜变量取平均后作为单一条件。从load_voices()的实现看,原始音频声音会先各自提取潜变量,再对(latents_0, latents_1)分别取均值(见 tortoise/utils/audio.py);- 逗号多声音:如
-v tom,emma,会对每个声音分别完整生成一遍(注意必须配合--output-dir,见 scripts/tortoise_tts.py); all:遍历所有可用声音,适合批量试听对比。
5.3 API 方式
在 Python 代码中同样可以加载自定义声音,核心是把参考片段读取为 22050 Hz 的张量列表后传入 tts_with_preset():
import torch
from tortoise.api import TextToSpeech
from tortoise.utils.audio import load_audio, load_voices
# 方式一:直接传参考片段(voice_samples)
clip_paths = [
"tortoise/voices/my_speaker/1.wav",
"tortoise/voices/my_speaker/2.wav",
"tortoise/voices/my_speaker/3.wav",
]
reference_clips = [load_audio(p, 22050) for p in clip_paths]
tts = TextToSpeech()
pcm_audio = tts.tts_with_preset("Hello from my custom voice.", voice_samples=reference_clips, preset='fast')
# 方式二:复用 load_voices 读取声音目录(与 CLI 逻辑一致)
voice_samples, conditioning_latents = load_voices(["my_speaker"])
pcm_audio = tts.tts_with_preset("Hello from my custom voice.", voice_samples=voice_samples,
conditioning_latents=conditioning_latents, preset='fast')
两个参数的关系(见 tortoise/api.py):voice_samples 优先,模型会现场调用 get_conditioning_latents() 计算条件;若只传 conditioning_latents(即已有的 .pth 潜变量),则跳过音频处理直接推理,这也是 .pth 缓存能够加速推理的原因。
六、进阶玩法:把声音固化为 Conditioning Latents
如果你希望把某个声音"固化"成一份轻量的潜变量文件,便于分发、复用或二次编辑,可以使用仓库自带的 tortoise/get_conditioning_latents.py:
python tortoise/get_conditioning_latents.py --voice my_speaker --output_path results/conditioning_latents
该脚本会对指定声音的所有参考片段调用 tts.get_conditioning_latents(conds),并把得到的 (auto_latent, diffusion_latent) 元组 torch.save 为 <voice>.pth。生成的 .pth 文件可以像 tortoise/voices/cond_latent_example/pat.pth 那样放回 voices/ 目录直接使用——当某个声音目录里只有 .pth 文件时,load_voice() 会直接加载潜变量而不再处理原始音频(见 tortoise/utils/audio.py)。
从脚本 docstring 可以得知,这些潜变量是"富有表现力的可学习向量"(expressive latents),既可用于其他机器学习模型,也可以手工增强后重新喂给 Tortoise 来改变发声特质。
七、质量调优与常见问题
新声音加载成功后,如果合成质量不理想,除了重新挑选参考片段,还可以通过 scripts/tortoise_tts.py 的调优参数在预设基础上做针对性调整:
--num-autoregressive-samples:自回归采样数。Tortoise 是概率模型,采样越多,CLVP 筛选出"好结果"的概率越高;四种预设分别为ultra_fast=16、fast=96、standard=256、high_quality=256(见 tortoise/api.py);--diffusion-iterations:扩散步数,预设分别为 30 / 80 / 200 / 400。超过 250 步通常无明显提升;--cvvp-amount:CVVP 模型的影响权重,[0,1],调高可以在某些情况下降低"多人声混杂"的概率;--seed:固定随机种子,配合--produce-debug-state生成的debug_states/*.pth可以完全复现某次输出,便于排查问题(见 scripts/tortoise_tts.py);--max-mel-tokens:限制输出长度,取值1~600,每个单位对应 1/20 秒。
常见问题速查:
voice xxx not available:声音目录未被识别。检查子目录是否位于 tortoise/voices 下(或是否用--voices-dir指定了外部目录),并确认目录内存在.wav/.mp3/.pth文件;- 片段太短导致效果差:
format_conditioning()只取前 6 秒有效信息,确保每条片段接近 10 秒且内容不重复; - 输出带环境噪声:参考片段决定音量、底噪与混响,优先替换更干净的素材;
- 输出语速/缺陷不符合预期:参考片段决定语速与口吃等特征,检查素材中是否有大量 "uh"、"like" 或结巴片段。
结语
Tortoise 的"零样本多说话人"能力,全部建立在对参考片段的充分利用之上:音高、语调、语速、发声缺陷乃至录音环境,都会从你提供的素材中被编码进条件潜变量,再注入自回归与扩散两条生成链路。遵循 voice_customization_guide.md 的六步添加流程与六条选材准则,配合 scripts/tortoise_tts.py 的参数化调用,你就能在几分钟内为 Tortoise 打造出属于自己的高质量声音,并通过 .pth 潜变量将其固化为可复用、可分享的资产。