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

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

如您所见,输出是 log mel 频谱图,而不是最终波形。如果您还记得,我们在单元 3中简要介绍了这个主题。生成音频的模型通常生成 log mel 频谱图,这需要使用称为声码器的附加神经网络转换为波形。
让我们看看您如何做到这一点。
首先,让我们从 🤗 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) 的张量。这个特定的说话人嵌入描述的是女性声音。
此时,我们已经有足够的输入来生成 log mel 频谱图作为输出,您可以像这样进行操作
spectrogram = model.generate_speech(inputs["input_ids"], speaker_embeddings)
这会输出一个形状为 (140, 80) 的张量,其中包含 log mel 频谱图。第一个维度是序列长度,它可能在运行之间变化,因为语音解码器预网络始终对输入序列应用 dropout。这为生成的语音增加了一些随机可变性。
但是,如果我们希望生成语音波形,我们需要指定一个声码器,用于将频谱图转换为波形。从理论上讲,您可以使用任何适用于 80-bin mel 频谱图的声码器。方便的是,🤗 Transformers 提供了一个基于 HiFi-GAN 的声码器。其权重由 SpeechT5 的原始作者慷慨提供。
HiFi-GAN 是一种最先进的生成对抗网络 (GAN),专为高保真语音合成而设计。它能够从频谱图输入生成高质量和逼真的音频波形。
在高层次上,HiFi-GAN 由一个生成器和两个判别器组成。生成器是一个完全卷积神经网络,它将 mel 频谱图作为输入,并学习生成原始音频波形。判别器的作用是区分真实音频和生成音频。这两个判别器侧重于音频的不同方面。
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
既充当编解码器又充当压缩工具。
使用 Encodec
,您可以将音频压缩为轻量级格式以减少内存使用,然后解压缩它以恢复原始音频。此压缩过程由 8 个码本促成,每个码本都由整数向量组成。将这些码本视为音频的整数形式的表示或嵌入。重要的是要注意,每个连续的码本都会提高从先前码本重建音频的质量。由于码本是整数向量,因此可以由 Transformer 模型学习,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()
该模型还可以生成非语言交流,例如笑声、叹息和哭泣。您只需使用相应的提示(例如 [清嗓子]
、[笑声]
或 ...
)修改输入文本即可。
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) 是另一个涵盖一系列语音任务的模型,但是,它支持大量语言。例如,它可以合成超过 1100 种语言的语音。
用于文本到语音的 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 上更新