音频课程文档
文本转语音的预训练模型
并获得增强的文档体验
开始使用
文本转语音的预训练模型
与 ASR(自动语音识别)和音频分类任务相比,可用的预训练模型检查点明显较少。在 🤗 Hub 上,你会发现将近 300 个合适的检查点。在这些预训练模型中,我们将重点关注 🤗 Transformers 库中现成的两种架构——SpeechT5 和 Massive Multilingual Speech (MMS)。在本节中,我们将探讨如何在 Transformers 库中使用这些预训练模型进行 TTS。
SpeechT5
SpeechT5 是微软的 Junyi Ao 等人发布的一个模型,能够处理一系列语音任务。虽然在本单元中,我们侧重于文本转语音方面,但该模型可以用于语音转文本任务(自动语音识别或说话人识别),以及语音转语音任务(例如语音增强或不同声音之间的转换)。这得益于模型的设计和预训练方式。
SpeechT5 的核心是一个常规的 Transformer 编码器-解码器模型。与其他 Transformer 一样,编码器-解码器网络使用隐藏表示对序列到序列的转换进行建模。这个 Transformer 主干对于 SpeechT5 支持的所有任务都是相同的。
这个 Transformer 辅以六个特定于模态(语音/文本)的 pre-nets 和 post-nets。输入语音或文本(取决于任务)通过相应的 pre-net 进行预处理,以获得 Transformer 可以使用的隐藏表示。然后,Transformer 的输出被传递到 post-net,后者将使用它在目标模态中生成输出。
这就是该架构的样子(图片来自原始论文)

SpeechT5 首先使用大规模的未标记语音和文本数据进行预训练,以获得不同模态的统一表示。在预训练阶段,所有 pre-nets 和 post-nets 同时使用。
预训练后,整个编码器-解码器主干针对每个单独的任务进行微调。在此步骤中,仅使用与特定任务相关的 pre-nets 和 post-nets。例如,要将 SpeechT5 用于文本转语音,您需要用于文本输入的文本编码器 pre-net 和用于语音输出的语音解码器 pre-net 和 post-net。
这种方法可以获得针对不同语音任务进行微调的多个模型,所有这些模型都受益于对未标记数据的初始预训练。
尽管微调模型最初使用来自共享预训练模型的相同权重集,但最终版本都大相径庭。例如,您不能拿一个微调过的 ASR 模型,然后替换掉 pre-nets 和 post-net 来获得一个可用的 TTS 模型。SpeechT5 很灵活,但没那么灵活;)
让我们看看 SpeechT5 专门用于 TTS 任务的 pre-nets 和 post-nets 是什么样子的
- 文本编码器前置网络:一个文本嵌入层,将文本标记映射到编码器期望的隐藏表示。这类似于 BERT 等 NLP 模型中发生的情况。
- 语音解码器前置网络:它将对数梅尔谱图作为输入,并使用一系列线性层将谱图压缩成隐藏表示。
- 语音解码器后置网络:它预测要添加到输出谱图的残差,并用于优化结果。
结合起来,这就是 SpeechT5 文本转语音架构的样子

如您所见,输出是对数梅尔谱图,而不是最终的波形。如果您还记得,我们在第 3 单元中简要提到了这个主题。生成音频的模型通常会生成对数梅尔谱图,需要使用称为声码器的额外神经网络将其转换为波形。
让我们看看如何做到这一点。
首先,让我们从 🤗 Hub 加载经过微调的 TTS SpeechT5 模型,以及用于分词和特征提取的处理器对象
from transformers import SpeechT5Processor, SpeechT5ForTextToSpeech
processor = SpeechT5Processor.from_pretrained("microsoft/speecht5_tts")
model = SpeechT5ForTextToSpeech.from_pretrained("microsoft/speecht5_tts")
接下来,对输入文本进行分词。
inputs = processor(text="Don't count the days, make the days count.", return_tensors="pt")
SpeechT5 TTS 模型不仅限于为单个说话人创建语音。相反,它使用所谓的说话人嵌入来捕捉特定说话人的声音特征。
说话人嵌入是一种以紧凑方式表示说话人身份的方法,无论语音长度如何,都以固定大小的向量表示。这些嵌入捕捉了说话人声音、口音、语调和其他区分不同说话人的独特特征的基本信息。此类嵌入可用于说话人验证、说话人识别、说话人分离等。生成说话人嵌入的最常用技术包括:
- I-Vectors(身份向量):I-Vectors 基于高斯混合模型(GMM)。它们将说话人表示为从说话人特定 GMM 的统计数据派生的低维固定长度向量,并以无监督方式获得。
- X-Vectors:X-Vectors 是使用深度神经网络(DNN)派生的,通过结合时间上下文来捕获帧级说话人信息。
X-Vectors 是一种最先进的方法,与 I-Vectors 相比,在评估数据集上表现出卓越的性能。深度神经网络用于获取 X-Vectors:它训练以区分说话人,并将可变长度的语音映射到固定维度的嵌入。您还可以加载预先计算的 X-Vector 说话人嵌入,它将封装特定说话人的说话特征。
让我们从 Hub 上的数据集中加载这样的说话人嵌入。这些嵌入是使用此脚本从 CMU ARCTIC 数据集中获得的,但任何 X-Vector 嵌入都应该有效。
from datasets import load_dataset
embeddings_dataset = load_dataset("Matthijs/cmu-arctic-xvectors", split="validation")
import torch
speaker_embeddings = torch.tensor(embeddings_dataset[7306]["xvector"]).unsqueeze(0)
说话人嵌入是一个形状为 (1, 512) 的张量。这个特定的说话人嵌入描述了一个女性声音。
此时,我们已经有足够的输入来生成对数梅尔谱图作为输出,您可以这样做
spectrogram = model.generate_speech(inputs["input_ids"], speaker_embeddings)
这会输出一个形状为 (140, 80) 的张量,其中包含对数梅尔谱图。第一个维度是序列长度,它在不同运行之间可能会有所不同,因为语音解码器前置网络总是将 dropout 应用于输入序列。这会给生成的语音添加一些随机变异性。
然而,如果我们要生成语音波形,我们需要指定一个声码器用于谱图到波形的转换。理论上,您可以使用任何适用于 80 频段梅尔谱图的声码器。方便的是,🤗 Transformers 提供了一个基于 HiFi-GAN 的声码器。它的权重由 SpeechT5 的原始作者慷慨提供。
HiFi-GAN 是一种最先进的生成对抗网络 (GAN),专为高保真语音合成而设计。它能够从谱图输入生成高质量和逼真的音频波形。
从高层次看,HiFi-GAN 由一个生成器和两个判别器组成。生成器是一个全卷积神经网络,它将梅尔谱图作为输入,并学习生成原始音频波形。判别器的作用是区分真实音频和生成音频。这两个判别器侧重于音频的不同方面。
HiFi-GAN 在大量高质量音频录音数据集上进行训练。它使用一种所谓的 对抗性训练,其中生成器和判别器网络相互竞争。最初,生成器会生成低质量的音频,判别器可以很容易地将其与真实音频区分开来。随着训练的进行,生成器会改进其输出,旨在欺骗判别器。反过来,判别器在区分真实音频和生成音频方面变得更加准确。这种对抗性反馈循环有助于两个网络随着时间的推移而改进。最终,HiFi-GAN 学会了生成与训练数据特征非常相似的高保真音频。
加载声码器就像加载任何其他 🤗 Transformers 模型一样简单。
from transformers import SpeechT5HifiGan
vocoder = SpeechT5HifiGan.from_pretrained("microsoft/speecht5_hifigan")
现在您所需要做的就是在生成语音时将其作为参数传递,输出将自动转换为语音波形。
speech = model.generate_speech(inputs["input_ids"], speaker_embeddings, vocoder=vocoder)
让我们听听结果。SpeechT5 使用的采样率始终为 16 kHz。
from IPython.display import Audio
Audio(speech, rate=16000)
太棒了!
随时可以试用 SpeechT5 文本转语音演示,探索其他声音,尝试不同的输入。请注意,此预训练检查点仅支持英语
Bark
Bark 是 Suno AI 在 suno-ai/bark 中提出的基于 Transformer 的文本转语音模型。
与 SpeechT5 不同,Bark 直接生成原始语音波形,无需在推理过程中使用单独的声码器——它已经集成。这种效率是通过利用 Encodec
实现的,它既充当编解码器又充当压缩工具。
使用 Encodec
,您可以将音频压缩成轻量级格式以减少内存使用,然后对其进行解压缩以恢复原始音频。此压缩过程由 8 个码本促进,每个码本都由整数向量组成。可以将这些码本视为音频的整数形式表示或嵌入。重要的是要注意,每个后续码本都会提高从先前码本重建音频的质量。由于码本是整数向量,因此可以通过 Transformer 模型学习它们,这些模型在该任务中非常高效。这就是 Bark 专门训练的目的。
更具体地说,Bark 由 4 个主要模型组成
BarkSemanticModel
(也称为“文本”模型):一个因果自回归 Transformer 模型,它将分词后的文本作为输入,并预测捕获文本含义的语义文本标记。BarkCoarseModel
(也称为“粗略声学”模型):一个因果自回归 Transformer,它将BarkSemanticModel
模型的结果作为输入。它的目标是预测 EnCodec 所需的前两个音频码本。BarkFineModel
(“精细声学”模型),这次是一个非因果自编码器 Transformer,它基于先前码本嵌入的总和迭代地预测最后一个码本。- 预测了来自
EncodecModel
的所有码本通道后,Bark 使用它来解码输出音频数组。
值得注意的是,前三个模块中的每一个都可以支持条件说话人嵌入,以根据特定的预定义语音调节输出声音。
Bark 是一个高度可控的文本转语音模型,这意味着您可以使用各种设置,我们将在后面看到。
首先,加载模型及其处理器。
处理器在这里的作用是双重的
- 它用于对输入文本进行分词,即将其切成模型可以理解的小块。
- 它存储说话人嵌入,即可以影响生成的语音预设。
from transformers import BarkModel, BarkProcessor
model = BarkModel.from_pretrained("suno/bark-small")
processor = BarkProcessor.from_pretrained("suno/bark-small")
Bark 非常通用,可以生成由说话人嵌入库调节的音频,该库可以通过处理器加载。
# add a speaker embedding
inputs = processor("This is a test!", voice_preset="v2/en_speaker_3")
speech_output = model.generate(**inputs).cpu().numpy()
它还可以生成即用型多语言语音,例如法语和中文。您可以在此处找到支持的语言列表。与下面讨论的 MMS 不同,无需指定所使用的语言,只需将输入文本适应相应的语言即可。
# try it in French, let's also add a French speaker embedding
inputs = processor("C'est un test!", voice_preset="v2/fr_speaker_1")
speech_output = model.generate(**inputs).cpu().numpy()
该模型还可以生成**非语言交流**,例如笑声、叹息和哭泣。您只需使用相应的提示修改输入文本,例如 [clears throat]
(清嗓子)、[laughter]
(笑声)或 ...
。
inputs = processor(
"[clears throat] This is a test ... and I just took a long pause.",
voice_preset="v2/fr_speaker_1",
)
speech_output = model.generate(**inputs).cpu().numpy()
Bark 甚至可以生成音乐。您可以通过在单词周围添加 ♪ 音乐音符 ♪ 来提供帮助。
inputs = processor(
"♪ In the mighty jungle, I'm trying to generate barks.",
)
speech_output = model.generate(**inputs).cpu().numpy()
除了所有这些功能之外,Bark 还支持批处理,这意味着您可以同时处理多个文本条目,但会以更密集的计算为代价。在某些硬件(例如 GPU)上,批处理可以加快整体生成速度,这意味着一次性生成样本可能比逐个生成样本更快。
让我们尝试生成几个示例
input_list = [
"[clears throat] Hello uh ..., my dog is cute [laughter]",
"Let's try generating speech, with Bark, a text-to-speech model",
"♪ In the jungle, the mighty jungle, the lion barks tonight ♪",
]
# also add a speaker embedding
inputs = processor(input_list, voice_preset="v2/en_speaker_3")
speech_output = model.generate(**inputs).cpu().numpy()
让我们逐个听一下输出。
第一个
from IPython.display import Audio
sampling_rate = model.generation_config.sample_rate
Audio(speech_output[0], rate=sampling_rate)
第二个
Audio(speech_output[1], rate=sampling_rate)
第三个
Audio(speech_output[2], rate=sampling_rate)
Bark,像其他 🤗 Transformers 模型一样,可以通过几行代码进行优化,以提高速度和减少内存影响。要了解如何操作,请点击此 Colab 演示笔记本。
大规模多语言语音 (MMS)
如果您正在寻找除英语之外的预训练模型怎么办?大规模多语言语音 (MMS) 是另一个涵盖一系列语音任务的模型,但它支持大量语言。例如,它可以合成 1,100 多种语言的语音。
MMS 用于文本转语音是基于 VITS Kim et al., 2021,这是最先进的 TTS 方法之一。
VITS 是一种语音生成网络,可将文本转换为原始语音波形。它像一个条件变分自编码器一样工作,从输入文本估计音频特征。首先,生成以频谱图表示的声学特征。然后使用从 HiFi-GAN 改造的转置卷积层解码波形。在推理过程中,文本编码被上采样并使用流模块和 HiFi-GAN 解码器转换为波形。像 Bark 一样,不需要声码器,因为波形是直接生成的。
pip install git+https://github.com/huggingface/transformers.git
让我们试试 MMS,看看我们如何合成除英语之外的语言(例如德语)的语音。首先,我们将加载正确的语言的模型检查点和分词器
from transformers import VitsModel, VitsTokenizer
model = VitsModel.from_pretrained("facebook/mms-tts-deu")
tokenizer = VitsTokenizer.from_pretrained("facebook/mms-tts-deu")
您可能会注意到,要加载 MMS 模型,您需要使用 VitsModel
和 VitsTokenizer
。这是因为如前所述,用于文本转语音的 MMS 是基于 VITS 模型的。
让我们选择一个德语示例文本,就像这首儿歌的前两行一样
text_example = (
"Ich bin Schnappi das kleine Krokodil, komm aus Ägypten das liegt direkt am Nil."
)
要生成波形输出,请使用分词器对文本进行预处理,然后将其传递给模型
import torch
inputs = tokenizer(text_example, return_tensors="pt")
input_ids = inputs["input_ids"]
with torch.no_grad():
outputs = model(input_ids)
speech = outputs["waveform"]
我们来听一下
from IPython.display import Audio
Audio(speech, rate=16000)
太棒了!如果您想尝试使用其他语言的 MMS,请在 🤗 Hub 上查找其他合适的 vits
检查点。
现在让我们看看如何自己微调 TTS 模型!
< > 在 GitHub 上更新