SpeechTokenizer: Unified Speech Tokenizer for Speech Language Models

语音语言模型的统一语音标记器

https://github.com/ZhangXInFD/SpeechTokenizer

SpeechTokenizer: Unified Speech Tokenizer for Speech Language Models

SpeechTokenizer是一个统一的语音语言模型的语音分词器,它采用了编码器-解码器架构与残差矢量量化(RVQ)。统一语义和声学标记SpeechTokenizer在不同的RVQ层上分层地解开语音信息的不同方面。具体地,RVQ的第一量化器输出的代码索引可以被认为是语义令牌,并且其余量化器的输出主要包含音色信息,其用作对由第一量化器丢失的信息的补充。

目前的Speech Langauge Model(speech LM)大多依赖于语音的离散表示。具体来说,这些模型首先将连续的语音信号转换成离散的tokens,进而像处理文本一样以自回归的方式进行训练,再通过一个解码器将离散tokens恢复为语音。

比较常用的语音离散表示大致可分为两种:语义semantic token和 声学acoustic token。token如其名,通常认为semantic token建模语音中较为global的内容信息,它们来自于以mask langauge modeling为training objective的自监督预训练模型,比较常见的有HuBERT, W2VBERT等;acoustic token建模语音中的局部声学细节,通常来自于以reconstruction为training objective的neural audio codec,比较常见的有SoundStream, EnCodec。

基于这两种token,目前已有的speech LM建模范式大致可分为三类

  1. Semantic language models: 基于semantic token的自回归模型,常外接一个unit-vocoder来恢复语音,比如SpeechGPT。这类模型虽然可以完成一些语音内容相关的任务,但是它们产生的音质比较一般,并且无法完成一些副语言学相关的任务,比如音色转换等。
  2. Acoustic language models: 基于acoustic token的speech LM,比如VALL-E。这类模型产生的语音音质比较好,并且可以较好地完成一些比如zero-shot TTS的任务,但是会存在内容不准确的问题。
  3. Hierarchical speech language models: 这类模型由Semantic language models和Acoustic language models 级联而成,既可以产生比较精确的内容,也可以产生较好的音质,比如AudioPaLM。但是这类模型,建模阶段太多,较为复杂,需要两种tokenizer的参与;而且在semantic token和acoustic token之间其实存在有很大的信息冗余,会带来一些不必要的建模难度。

因此,如果想要打造好的speech LM,需要有一个理想的speech tokens,它应该具有以下两个特征:

  1. 和文本的对齐程度比较高
  2. 保留了语音中各个方面的信息

但是现有的speech tokens都不是专门为构建speech LM而设计的,并不清楚它们和speech LM的适配性。因此我们建立了SLMTokBench来评估不同类型speech token在构建speech LM方面的适用性。它从文本对齐程度和信息保留程度两个方面来量化分析speech tokens,具体评测方法可以看我们论文。通过SLMTokBench,我们发现semantic tokens和文本的对齐程度比较高,但是损失了语音中很大一部分说话人信息。acoustic tokens保留了语音中的各个方面信息,但是和文本的对齐程度不够高。因此,他们都不适合于构建speechLM。

方法

虽然说SoundStream和Encodec这样的基于RVQ-VAE的压缩建模方法包含了语音的声学特征,但其中也不可避免地带入了语义特征。二者提取的实际上更像是一种语义特征和声学特征的混合体。基于此,SpeechTokenizer在二者的基础上,引入了语义引导信息来解耦语义特征和声学特征。语义特征和声学特征的解耦对于最终的语音合成有着相当的重要性。SpeechTokenizer的具体做法是:使用HuBERT的特征对RVQ1的特征做语义蒸馏,其余部分保留声学信息。

基于此,我们想统一semantic token和acoustic token,我们提出了SpeechTokenizer,它基于EnCodec架构,在不同的RVQ层上对语音信息进行解耦和分层建模,从而让第一层token建模语音中的内容信息,剩下几层token补充除内容信息之外的其他信息,如下图。这是首个专为speech LM设计的语音离散化工具。

具体实现方法为在EnCodec的整体框架上,使用HuBERT representation对RVQ-1的quantized output进行semantic guidance,从而达到第一层token建模语音中的内容信息的效果,并且残差结构会使得剩下的几层来补充内容信息之外的其他信息。使用EnCodec的基于卷积的编码器-解码器网络,该网络使用选定的步幅因子执行时间缩减。值得注意的是,我们已经用两层BiLSTM代替了最初在EnCodec编码器中的卷积块之后的两层LSTM,以增强语义建模能力。我们对附录B中的模型结构进行了消融研究。我们使用残差向量量化(RVQ)来量化编码器的输出,RVQ是一种可以在初始量化步骤之后使用不同码本来量化残差的方法。有关模型结构的更多详细信息,请参见附录D。 在训练期间,语义教师提供语义表示以指导残差量化过程。

并且基于SpeechTokenizer,我们可以统一上面讲的三种speech LM建模范式,从而构建unified speech language model(USLM),模型结构如下图

在SpeechTokenizer上构建一个统一的语音语言模型。它由自回归模型和非自回归模型组成,可以对语音信息进行分层建模。自回归(AR)模型通过对来自第一RVQ量化器的令牌进行建模来捕获内容信息。非自回归(NAR)模型通过从以第一层令牌为条件的后续量化器生成令牌来补充AR模型的语言信息。我们在零拍TTS任务上验证了统一语音语言模型的有效性。

回归(AR)模型通过对来自第一RVQ量化器的令牌进行建模来捕获内容信息。非自回归(NAR)模型通过从以第一层令牌为条件的后续量化器生成令牌来补充AR模型的语言信息。

NAR模型可以是条件流匹配[speech-Gen]、扩散模型 【Seed-TTS】等

在推理过程中,我们将文本输入转换为音素序列,将语音提示转换为语音标记。它们连接在一起形成AR和NAR模型的提示。在此基础上,AR模型生成第一级令牌,而NAR模型迭代地生成后续级别的令牌。由AR和NAR模型生成的令牌然后被连接以构造语音令牌矩阵。最后,我们使用SpeechTokenizer解码器来生成以完整令牌矩阵为条件的波形。

Speech Language Model Token Benchmark:

文本对齐评估:

下游模型采取语音令牌作为输入。具体来说,对于每个离散表示,我们首先建立一个嵌入矩阵,该矩阵可以随机初始化,也可以从离散化过程中获得的k均值质心矩阵或矢量量化码本中导出。我们使用嵌入矩阵来嵌入离散表示并获得连续表示,然后将其输入下游模型。我们在LibriSpeech train-clean-100子集上训练下游模型,并使用dev-clean子集来估计互信息。我们还计算了测试集上的单词错误率(WER)。

信息保存评估:

为了评估离散语音表示中语音信息的保留,我们将语音令牌转换回语音,并通过内容和音质的自动度量来评估重新合成的语音。我们训练一个单元-HiFIGAN(Polyak 等人,2021)在LibriSpeech数据集上将HuBERT单位转换为波形。值得注意的是,为了避免额外信息的干扰,我们在训练期间不提供任何说话人信息。对于Encodec令牌,我们使用Encodec解码器直接产生波形。通过使用Whisper en-medium模型转录重新合成的语音来计算WER来评估内容保存(拉德福 等人,2023年)。通过利用WavLM-TDNN(Chen 等人,2022)来计算合成语音和地面实况语音之间的说话人相似度。 我们从LibriSpeech测试集中随机抽取300个语音样本进行评估。

比较语义 & 声学令牌

我们使用HuBERT L9单元来表示语义令牌,使用EnCodec代码来表示声学令牌语义标记实现了与文本的高互信息,但其重新合成的语音具有低说话人相似性。声学标记实现低WER和高说话人相似度的再合成语音,但与文本的互信息低。

SpeechTokenizer

模型结构

我们的模型基于 RVQ-GAN 框架,遵循与 SoundStream和 EnCodec相同的模式。如图 2 所示,模型使用了 EnCodec 中基于卷积的编码器-解码器网络,通过选择的步长因子进行时间下采样。值得注意的是,我们将 EnCodec 编码器中卷积模块后原本使用的两层 LSTM 替换为两层 BiLSTM,以增强语义建模能力。我们在附录 B 中进行了模型结构的消融研究。我们使用残差矢量量化(RVQ)对编码器输出进行量化,这种方法可以在初始量化步骤后使用不同的码书对残差进行量化。模型结构的进一步细节可参见附录 D。在训练期间,一个语义教师为残差量化过程提供语义表示指导。

语义提炼

为了实现跨不同RVQ层的不同信息的分层建模,我们采用语义指导的第一个量化器,使其能够捕获内容信息。利用残差结构使得后续量化器能够补充剩余的非语言信息。

我们采用HuBERT(Hsu 等人,2021)作为我们在这项研究中的语义老师,因为HuBERT被证明包含大量的内容信息(Mohamed 等人,2022年)。我们介绍了两种类型的蒸馏:连续表示蒸馏和伪标签预测。

对于连续表示蒸馏,我们采用第9层HuBERT表示或所有HuBERT层的平均表示作为语义教师。训练目标是最大化RVQ第一层和语义教师表示的输出之间的所有时间步长在维度级别上的余弦相似性。形式上,连续蒸馏损失定义为:

其中 𝐐1 和 𝐒 分别表示RVQ第一层和语义教师表示的量化输出。 𝐀 表示投影矩阵, D 是语义教师表征的维度。上标 (:,d) 表示包括来自维度 d 处的所有时间步的值的向量。 cos⁡(⋅) 表示余弦相似性, σ⁢(⋅) 表示S形激活。这种连续蒸馏损失函数偏离了常用的方法,该方法基于学生和教师模型在同一时间步输出的表示来计算损失。附录C对这两种方法进行了比较分析。

对于伪标签预测,我们采用HuBERT单元作为目标标签。培训目标如下:

其中 𝐪1t 和 𝐮t 分别表示第一VQ层和HuBERT单元在时间步t的量化输出。 T 表示时间步长的数量, 𝐀 是投影矩阵。

Training Objective

我们的训练方法包括重建任务和语义蒸馏任务。在重建任务中,我们采用了GAN目标,优化了重建项,判别损失项和RVQ承诺损失的组合。在语义蒸馏任务中,训练目标涉及语义蒸馏损失项。在下文中, 𝐱 表示语音信号,并且 𝐱^ 表示通过网络重构的信号.

重建损失重建损失包括时域和频域损失。鉴别损失我们使用与HiFi-CodecYang等人(2023)相同的鉴别器,其中包括三个鉴别器:基于多尺度STFT(MS-STFT)的鉴别器;多周期鉴别器(MPD)和多尺度鉴别器(MSD)。鉴别器的更多详细信息可参见附录D。对抗性损失用于提高感知质量,并且它被定义为在多个鉴别器上和在时间上平均的在多个鉴别器的logits上的铰链损失。RVQ Commitment Loss 我们在预量化值和其量化值之间添加承诺损失 ℒw ,而不为量化值计算梯度。RVQ承诺损失被定义为: ℒw=∑i=1Nq∥𝐳i−𝐳qi∥22. ,其中 𝐳i 和 𝐳qi 分别表示对应码本中的当前残差和最近条目。

通常,生成器被训练以优化以下损失:

RVQ token中信息解耦的效果如何?

我们做了one-shot voice conversion的实验。具体做法为把source speech的RVQ-1 token和reference speech的RVQ-2:8 token拼在一起送到decoder中得到converted speech。我们发现这种简单拼接RVQ token的做法也可以有不错的音色转换的效果,说明信息解耦是比较成功的。可以到我们的demo page上听效果。

SpeechTokenizer能否直接应用到unseen langauge上?

SpeechTokenizer在训练过程中只见过英语,我们直接用它直接来tokenize 德语和中文speech。发现RVQ-1送到decoder得到的speech比较机械,没有音色和韵律,说明也有比较好的解耦效果,大家可以去project page听demo。从下面频谱图也可以看出RVQ-1得到的语音丢掉了一些如共振峰等特征。

paraformer-工业级非自回归端到端语音识别模型

论文地址:https://arxiv.org/abs/2206.08317

代码:https://github.com/modelscope/FunASR/

摘要:

Transformers在 ASR 领域占据主导地位。虽然能够产生良好的性能,但它们使用自回归(AR)解码器来逐一生成令牌,这在计算效率上是低效的。为了加快推理速度,可以使用非自回归 (NAR) 方法,例如单步 NAR 的设计是为了实现并行生成。然而,由于输出标签之间的独立性假设,单步 NAR 的性能不如 AR 模型,尤其是在大规模语料库的情况下。改进single-step NAR 面临两个挑战:首先是准确预测输出 token 的数量并提取隐藏变量;其次,增强输出标签之间相互依赖性的建模。为了应对这两个挑战,我们提出了一种快速且准确的并行Transformer,称为 Paraformer。该模型属于单步非自回归模型。这利用基于连续积分和激发的预测器来预测令牌的数量并生成隐藏变量。然后,扫视语言模型(GLM)采样器生成语义嵌入,以增强 NAR 解码器对上下文相互依赖进行建模的能力。最后,我们设计了一种策略来生成负样本以进行最小错误率训练,以进一步提高性能。使用公共 AISHELL-1、AISHELL-2 基准和工业级 20,000 小时任务的实验表明,所提出的 Paraformer 可以达到与最先进的 AR Transformer相当的性能,并且加速超过 10 倍。

1. Paraformer使用基于CIF的predictor预测输出标签的个数并产生隐变量;【文献18】

2. GLM sampler用于产生语义向量增强非自回归模型对上下文的建模能力;【文献19】

3. 最后作者设计了一个策略产生负例,并用MWER损失训练使模型的识别能力进一步提升。【文献20】

介绍:

过去几年,端到端(E2E)模型在自动语音识别(ASR)任务上的性能已经超越了传统层级系统。存在三种流行的 E2E 方法:连接主义时间分类 (CTC)、循环神经网络转换器 (RNN-T) 和基于注意力的编码器-解码器 (AED) 。其中,AED 模型由于其卓越的识别精度而在 ASR 的 seq2seq 建模中占据主导地位。例如 Transformer 和 Conformer。虽然性能良好,但此类 AED 模型内的自回归 (AR) 解码器需要一一生成令牌,因为每个令牌都以所有先前的令牌为条件。因此,解码器的计算效率低下,并且解码时间随着输出序列长度线性增加。为了提高效率并加速推理,有人提出使用非自回归(NAR)模型并行生成输出序列。

基于推理时需要的迭代次数,NAR 模型可以分为迭代模型或单步模型。在前者中,A-FMLM 是单步自回归模型的最早尝试,旨在通过不断迭代来预测以未屏蔽标记为条件的屏蔽标记。由于需要预先定义目标令牌长度,性能受到影响。为了解决这个问题,Mask-CTC 和变体提出通过 CTC 解码来增强解码器输入。即便如此,这些迭代 NAR 模型需要多次迭代才能获得有竞争力的结果,限制了实践中的推理速度。最近,提出了几种单步 NAR 模型来克服这一限制。它们通过消除时间依赖性同时生成输出序列。虽然单步 NAR 模型可以显着提高推理速度,但其识别精度明显不如 AR 模型,尤其是在大规模语料库上评估时。

前面提到的单步非自回归模型主要关注如何预测输出标签的个数和准确提取隐变量。和机器翻译通过predictor预测输出标签个数相比,ASR预测输出标签个数确实比较难,因为有很多的潜在影响因素,比如说话人的语速、静音、噪音。另一方面,经过作者的观察和分析,单步非自回归模型相比自回归模型具有更多的替换错误,如下图1。作者认为缺少上下文依赖信息导致预测标签个数准确率差不多,但替换错误上升明显(AR和vanilla NAR比较),尤其是单步自回归模型的条件独立假设。另外,所有的非自回归模型都是在学术基准阅读音频上实验的,并没有验证这些模型在工业基准数据上的效果。这篇论文的目标是提升单步非自回归模型的识别效果,使其达到和自回归模型相同的水准,并在大规模工业级数据上验证。

图1

文章提出了一个又快又准的并行transformer模型,可以克服上面提到的两个挑战。首先,不像前面的基于CTC的工作,作者提出了使用基于CIF【continuous integrate-and-fire】的predictor网络评估目标长度并产生隐变量。对于第二个挑战,作者设计了基于GLM【glancing language mode】的sampler模块增强非自回归解码器对输出上下文的建模能力。这个工作受到了机器翻译工作的启发。作者另外设计了一个包含负例的策略,利用MWER损失指导模型学习提升模型性能。

Paraformer是第一个在性能上可以和自回归模型媲美,并且在大规模数据集上相比自回归模型有10倍+的推理速度提升。

方法

整体框架

如上图所示,整个框架包含五个模块:encoder、 predictor、sampler、decoder、loss function。其中Encoder和自回归模型的Encoder一样,本文使用SAN-M【multihead-attention的部分换成了san-M】和FFN,也可以使用conformer等结构。Predictor用于生成声学特征指导解码。Sampler模块使用声学特征和标签特征生成语义特征【用于学习输入的上下文内容语义信息,增强非自回归解码器对输出上下文的建模能力】。Decoder和自回归解码器相同,只不过这里是双向解码器[类似bert]。解码器包含多个SAN-M、FNN和cross MHA模块。除了CE loss,还会使用MAE loss训练predictor,MWER损失也一起参与模型训练。

整个流程阐述:
输入音频为X,长度为T;音频对应的文本标签为Y,长度为N。Encoder的输入为X,输出为H。Predictor的输入为H,输出为预测的输出标签长度N’并生成声学向量Ea。第一轮解码Decoder的输入为H和Ea,输出为Y’。图中红色虚线Pass1标记部分表示输入Ea,但是并不对这个输入进行反向传播学习。第二轮解码前会首先经过Sampler模块。Sampler模块在声学向量Ea和输出标签向量Ec之间进行采样得到语义向量Es。其中Char指的是标签Y。采样过程依赖Y和Y’之间的距离。第二轮解码Decoder的输入为H和Es,输出为Y’‘,这次进行反向传播学习。此次反向传播学习指导decoder学习上下文语音信息,同时也会指导predictor和encoder的学习。Sampler使用Y’进行距离计算不会进行反向传播学习。最后输出的Y’’会被采样为MWER训练生成负例候选。使用N和N’计算MAE。MWER、MAE和CE loss一起作为loss进行训练。
推理时,sampler模块是不激活的,并且双向并行解码器只使用声学向量Ea和隐向量H通过一轮输出最终的预测结果。尽管decoder在每次训练时会前向推理两次,但是因为在推理时只进行了一次所以并不会使计算复杂度变大。

Predictor

Predictor由两个卷基层组成,输出的float weight α 在0~1之间。作者通过累计此权重预测输出标签的长度。MAEloss定义为:

其实就是将所有α 进行了累加,加起来的长度就是预测的长度。LOSS就是真实长度和预测长度差的绝对值。作者引入了CIF机制产生声学向量。CIF是一个软的(非0/1,可以是小数)和单一对齐的,在AED模型中作为流式解决方案的实现。声学向量的生成时,CIF对权重α 进行累计,如果超过了设定的阈值β ,说明某一个声学向量的边界确定了。对边界之内的向量H根据权重α 进行缩放累计即可得到某一个声学向量。此过程重复直到结尾,可得到所有的声学向量。如下图所示:

在训练时权重α会根据N进行缩放(比如累计的α为N’,使用N/N’对所有的α 进行缩放,使用缩放后的α计算声学向量Ea。缩放是为了让的Ea维度和Ec的维度保持一致),但是在推理时无法进行缩放,导致训练和推理之间存在不一致。为了弥补这个不一致,作者提出了使用动态阈值β而不是固定阈值。计算公式如下:

下面是一个向上取整,所以分子小于等于分母,阈值β < = 1 。

Sampler 【参考字节Glancing Transformer

GLM目的就是更好的学习输出序列的上下文语义关系,利用上下文进行当前的文本预测 学习输出标签之间的依赖关系

在普通的单步非自回归模型中,优化的目标为:

然而,正如上面所说的,单步非自回归模型中的输出标签独立性假设导致模型识别效果不如自回归模型。GLM模块的loss定义如下:

其中GLM(Y,Y′)表示Sampler模块在Ea​和Ec​中选中Ec​替换Ea​对应的Y′′中token的集合;GLMˉ(Y,Y′)表示Sampler模块在Ea​和Ec​中未选中Ec​替换Ea​对应的Y′′的token的集合;GLM(Y,Y′)的定义如下:

上面公式的含义是从Ec​中采样⌈αd(Y,Y′)⌉个向量替换对应位置的Ea​,生成新的向量为Es​。其中α是控制采样率的采样因子,越大表示使用Ec​替换Ea​的概率越大。该采样概率应该在最初模型效果不好时设置的稍微大一些,然后随着整个的训练过程的进行逐渐减小。为了达到这个目的,作者简单实用汉明距离,其定义为:

也就是,最开始的时候模型学习不好,d会比较大,当模型学习越来越好时,d也逐渐减小。表示最开始训练时,使用较多的Ec​替换Ea​,也就是上下文信息更多和准确,减小模型的学习难度;当模型学习的越来越好时,使用较少的标签信息迫使模型进一步学习。

总结,sampler模块结合了标注标签向量Ec​,实现方法是随机替换Ea​中⌈αd(Y,Y′)⌉个向量生成新的含有语义的向量Es​。训练并行decoder使用语义上下文GLM(Y,Y′)预测目标标签GLMˉ(Y,Y′),使模型学习输出标签之间的依赖关系

补充Glancing Transformer 原理:

自回归模型中最为常用的训练方式是最大似然估计(MLE),不少非自回归模型也直接使用 MLE 进行训练。但是非自回归模型的输出方式是并行的,输出语句中的任何部分在输出之前都无法获得输出语句中其余词的确切值。所以直接使用 MLE 训练并行输出的非自回归模型无法有效地建模输出语句中词之间的依赖关系。值得注意的是,词之间依赖关系的建模对输出通顺的语句至关重要,拥有良好生成质量的自回归模型和多轮迭代解码的模型均对这种依赖关系进行了有效的建模。

直接训练完全并行生成来学习目标语句中词之间的依赖关系对模型并不友好。一种更为简单有效的依赖关系学习方式是根据部分输入词预测其余目标词。但是这种学习方式需要部分目标词作为输入,不符合非自回归模型并行生成的要求。作者观察到随着模型自身更好地学习到词之间的依赖关系,模型对于依赖关系的学习可以逐渐摆脱使用目标语句部分词作为输入的需求。基于以上观察,Glancing Transformer(GLAT)利用了一种 glancing language model 的方法,通过渐进学习的方式进行词之间依赖关系的建模。在渐进学习的过程中,模型会先学习并行输出一些较为简单的语句片段,然后逐渐学习整句话的单步并行生成。

具体地,在第一次解码的时候,和常规的非自回归模型一样,模型使用完全并行解码的方式输出语句。然后将第一次解码得到的输出和训练数据中的目标语句进行对比。如果输出和目标语句差距较大,说明模型在训练中难以拟合该训练样本,因此这时 GLAT 会选择提供更多目标词作为输入来帮助学习词之间依赖关系。反之,如果输出和目标语句比较接近,则模型自身已经较好地学习了如何并行生成该目标语句,所需要的目标词数量也相应减少。

在第二步解码之前,模型的解码器可以得到部分目标词作为输入,这些词的数量由第一步的解码结果所决定。这时,模型在并行输出之前可以获得部分目标词的确切值,所以在学习输出剩余目标词的过程中就可以对目标语句中词之间的依赖关系进行建模。

随着训练的进行,模型对数据拟合程度更高,因此能够更准确地生成目标语句。与此同时,需要作为解码器输入的目标语句中的词的数量会越来越少,在训练后期逐渐接近学习完全并行生成的训练场景(例如上图右边的例子)。具体的方法细节和实现方式可以参考论文。

Loss Function:

一共定义了三个loss:CE、MAE、MWER。训练时进行联合训练:

对于MWER,具体的计算公式如下:

非自回归模型使用贪婪搜索,所以只有一个输出路径。正如前面提到的,在使用MWER训练时作者使用负例采样策略通过随机遮蔽top1分值标签产生多个候选路径。

实验

实验设置

在AISHELL-1、AISHELL-2以及工业级2wh数据集上验证上述方法的效果。其中工业级的测试集有两个:普通30h、远场15h。具体的工业级语料介绍可以参考文献21和28。RTF的测试在NVIDIA tesla V100上完成。

结果如上表格。在上述两个测试集上的测试都是在ESPNET框架上实现的,不包含LM和预训练模型。
AISHELL-1 的AR baseline参考文献15,效果在所有AR模型中是最好的(排除使用更多数据知识的模型)。因为作者当前的目标是通过模型结构提升模型效果而不是通过数据。普通的NAR和Paraformer的结构相同,但是没有Sampler。

结论:
1. 普通NAR的表现超过了其它的NAR工作,比如文献15和文献12
2. 普通NAR模型的表现比AR模型稍微差一些,因为缺乏了输出标签之间的上下文信息。
3. Paraformer通过使用基于GLM的Sampler模块对普通NAR模型增强,得到了和AR模型相近的识别表现。
4. Paraformer模型在dev和test测试上的CER分别为:4.6%和5.2%,推理速度比AR基线模型快12倍

工业级2wh数据集

结果如上表格所示,进行了多个扩展实验。动态β表示2.2节中的动态阈值,CTC表示带有LM的DFSMN-CTC-sMBR系统,参考文献32。RTF在OpenNMT上进行评估。
实验有两个模型,一个41M的一个63M的。AR基线模型中attention的维度为256,和文献21一致。这里的结论和前面有所不同。

结论

  1. 可以看到在大型数据集上,普通NAR模型和AR模型的识别效果差距很大(AISHELL上差别较小)。
  2. 普通NAR模型虽然和CTC都有输出标签独立假设限制,但是普通NAR模型效果优于CTC效果。
  3. 普通NAR模型结合GLM时,效果提升。
  4. 当进一步结合MWER训练方法时,效果进一步提升。
  5. Paraformer模型效果和AR模型效果很接近,差别在相对2%以内,但是推理速度提升10倍+。
  6. Paraformer结合动态β \betaβ,效果进一步提升。因为相比固定阈值,动态阈值减少了推理和训练的不一致,更准确地提取了声学向量信息。
  7. 将模型变大时,得到了和前面相似的结论。Paraformer相比普通NAR模型效果提升;和AR模型效果相当,但是推理速度提升10倍+。
  8. Paraformer-63M和AR transformer-41M模型相比较,尽管Paraformer模型较大,但是Paraformer推理速度更快。也就是说,在远场测试集上Paraformer-63M模型相比AR transformer-41M模型,识别效果相对提升6.0%,并且推理速度提升7.4倍。 也就是,在实际生产中,可以通过使用较大的Paraformer模型达到比AR模型更好的识别效果以及更快的推理速度。

对采样因子α的超参数测试结果参见上表格。和预期相同α变大时,模型效果变好,因为在训练时提供了更多的上下文信息;然而如果该参数太大会导致训练和测试不一致。基本上,α 在0.5~1.0之间的表现比较稳定。

  1. 在小型训练集上普通NAR和AR模型的识别性能差别不大,但是在工业级大数据集上差距明显。这是第一个在大规模工业级数据上验证NAR模型效果的研究。
  2. Paraformer相比普通NAR模型识别效果相对提升11%,和精细训练的AR模型效果相当。

分析:见文章第一张图。普通NAR模型相比AR模型,插入错误多一点,但是删除错误少一点。说明普通NAR模型的predictor预测输出的标签个数较准确。然而替换错误比较多,侧面反应两者性能差距很大。作者认为这是由普通NAR模型的条件独立假设造成的。Paraformer模型相比普通NAR模型替换错误下降很多,也暗示了识别效果提升很多。作者认为这是由于GLM模块使NAR模型学习到了标签之间的依赖关系。Paraformer模型相比AR模型替换错误稍微多一些,也暗示着识别准确率稍微差一些。作者认为AR模型中基于LM的beam search解码扮演了很重要的角色,相比GLM效果更好。为了减少这个性能差距,作者将在未来工作中在Paraformer模型上结合外部语言模型。

个人思考/疑问

  1. MWER loss没看懂,需要看文献20.
  2. Char 的 Embedding使用的torch.nn.Embedding,直接学习嘛?还是预设值好的。
  3. 端到端语音识别中的Embedding,例如wenet框架的token 的 Embedding能不能使用NLP领域用文字训练得到的Embedding,如果能的话为啥主流的不是这种的,这个Embedding不比直接学习更好嘛?
  4. wenet的重打分架构,decoder能不能直接根据CTC N-best结果得到矫正的识别结果,相当于做矫正/纠错?
  5. Paraformer能不能直接结合在当前的wenet框架中,使用conformer那套encoder,而不是SAN-M。从文章结论看,可以使用更大的模型训练Paraformer,效果比之前的模型效果好,且推理速度快,是一个可以实践的方向。
  6. Paraformer结构能不能和wenet重打分那套结合?Pafaformer的输出替代CTC的那一支,然后再加上decoder部分的重打分。这样相当于有了两个decoder。按道理就是训练会慢,但是推理应该还好吧?可能可行。——》Paraformer输出只有一个结果,重打分啥啊。。这个做不了。但是decoder可以作为纠错模型对结果进行纠错。
  7. 作者提出的在外面再结合一个语言模型应该是可行的。

[18] L. Dong and B. Xu, “CIF: Continuous integrate-and-fire for end-to-end speech recognition,” in ICASSP 2020-2020 IEEE Interna-tional Conference on Acoustics, Speech and Signal Processing(ICASSP). IEEE, 2020, pp. 6079–6083.
[19] L. Qian, H. Zhou, Y. Bao, M. Wang, L. Qiu, W. Zhang, Y. Yu,and L. Li, “Glancing transformer for non-autoregressive neural machine translation,” arXiv preprint arXiv:2008.07905, 2020.
[20] R. Prabhavalkar, T. N. Sainath, Y. Wu, P. Nguyen, Z. Chen, C.-C. Chiu, and A. Kannan, “Minimum word error rate training for attention-based sequence-to-sequence models,” in 2018 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2018, pp. 4839–4843

ChatTTS

https://github.com/2noise/ChatTTS/blob/main/docs/cn/README.md
https://2noise.com/
https://github.com/libukai/Awesome-ChatTTS
  1. 对话式 TTS: ChatTTS 针对对话式任务进行了优化,能够实现自然且富有表现力的合成语音。它支持多个说话者,便于生成互动式对话。
  2. 精细的控制: 该模型可以预测和控制精细的韵律特征,包括笑声、停顿和插入语。
  3. 更好的韵律: ChatTTS 在韵律方面超越了大多数开源 TTS 模型。我们提供预训练模型以支持进一步的研究和开发。

数据集和模型

  • 主模型使用了 100,000+ 小时的中文和英文音频数据进行训练。
  • HuggingFace 上的开源版本是一个在 40,000 小时数据上进行无监督微调的预训练模型。
###################################
# Sample a speaker from Gaussian.

rand_spk = chat.sample_random_speaker()
print(rand_spk) # save it for later timbre recovery

params_infer_code = ChatTTS.Chat.InferCodeParams(
    spk_emb = rand_spk, # add sampled speaker 
    temperature = .3,   # using custom temperature
    top_P = 0.7,        # top P decode
    top_K = 20,         # top K decode
)

###################################
# For sentence level manual control.

# use oral_(0-9), laugh_(0-2), break_(0-7) 
# to generate special token in text to synthesize.
params_refine_text = ChatTTS.Chat.RefineTextParams(
    prompt='[oral_2][laugh_0][break_6]',
)

wavs = chat.infer(
    texts,
    params_refine_text=params_refine_text,
    params_infer_code=params_infer_code,
)

###################################
# For word level manual control.

text = 'What is [uv_break]your favorite english food?[laugh][lbreak]'
wavs = chat.infer(text, skip_refine_text=True, params_refine_text=params_refine_text,  params_infer_code=params_infer_code)
torchaudio.save("output2.wav", torch.from_numpy(wavs[0]), 24000)

模型组成:LlamaModel、DVAE(VQVAE)、VOCOS声码器

文本控制

  • 1. Input Text : 需要转换的文本,支持中文和英文混杂
  • 2. Refine text : 是否对文本进行口语化处理
  • 3. Text Seed : 配置文本种子值,不同种子对应不同口语化风格
  • 4. 🎲 : 随机产生文本种子值
  • 5. Output Text : 口语化处理后生成的文本

音色控制

  • 6. Timbre : 预设的音色种子值
  • 7. Audio Seed : 配置音色种子值,不同种子对应不同音色
  • 8. 🎲 : 随机产生音色种子值
  • 9. Speaker Embedding : 音色码,详见 音色控制

情感控制

  • 10. temperate : 控制音频情感波动性,范围为 0-1,数字越大,波动性越大
  • 11. top_P :控制音频的情感相关性,范围为 0.1-0.9,数字越大,相关性越高
  • 12. top_K :控制音频的情感相似性,范围为 1-20,数字越小,相似性越高

系数控制

  • 13. DVAE Coefficient : 模型系数码
  • 14. Reload : 重新加载模型系数

播放控制

  • 15. Auto Play : 是否在生成音频后自动播放
  • 16. Stream Mode : 是否启用流式输出
  • 17. Generate : 点击生成音频文件
  • 18. Output Audio : 音频生成结果
  • 19. ↓ : 点击下载音频文件
  • 20. ▶️ : 点击播放音频文件

示例控制

  • 21. Example : 点击切换示例配置

快速体验

网址类型
Original Web原版网页版体验
Forge WebForge 增强版体验
LinuxPython 安装包
Samples音色种子示例
Cloning音色克隆体验

热门分支

功能增强

项目Star亮点
jianchang512/ChatTTS-ui提供 API 接口,可在第三方应用中调用
6drf21e/ChatTTS_colab提供流式输出,支持长音频生成和分角色阅读
lenML/ChatTTS-Forge提供人声增强和背景降噪,可使用附加提示词
CCmahua/ChatTTS-Enhanced支持文件批量处理,以及导出 SRT 文件
HKoon/ChatTTS-OpenVoice配合 OpenVoice 进行声音克隆

功能扩展

项目Star亮点
6drf21e/ChatTTS_Speaker音色角色打标与稳定性评估
AIFSH/ComfyUI-ChatTTSComfyUi 版本,可作为工作流节点引入
MaterialShadow/ChatTTS-manager提供了音色管理系统和 WebUI 界面

FunAudioLLM:人类和LLMs之间自然交互的语音理解和生成基础模型

https://funaudiollm.github.io/  [阿里团队]
arxiv.org/abs/2407.04051

[Paper] [Code] [Modelscope:SenseVoiceCosyVoice] [HuggingFace: SenseVoice]

我们介绍FunAudioLLM,本报告介绍了FunAudioLLM,这是一个旨在增强人类与大型语言模型之间的自然语音交互的框架(LLMs)。其核心是两个创新模型:SenseVoice用于高精度多语言语音识别,情感识别和音频事件检测;CosyVoice用于多语言,音色和情感控制的自然语音生成。SenseVoice具有极低的延迟并支持50多种语言,而CosyVoice在多语言语音生成、零触发语音生成、跨语言语音克隆和指令遵循功能方面表现出色。与SenseVoice和CosyVoice相关的模型已经在Modelscope和Huggingface上开源,沿着相应的训练,推理和微调代码发布在GitHub上。 通过将这些模型与LLMs集成,FunAudioLLM可以实现语音翻译、情感语音聊天、交互式播客和富有表现力的有声读物叙述等应用,从而推动语音交互技术的发展。

SenseVoice支持多语言语音识别,其训练时间超过30万小时。具体来说,SenseVoice-Small在推理方面非常高效,其中识别延迟小于80 ms,分别比Whisper-Small和Whisper-large快5倍和15倍以上,SenseVoice-Large支持50多种语言的高精度ASR。此外,SenseVoice支持丰富的转录,包括最先进的情感识别、音频事件检测、反向文本标准化(Pusateri 等人,2017)和标点符号(Chen 等人,2020年)。

语音生成模型,CosyVoice,可以生成多语言的语音,这是超过17万小时和五种语言,包括中文(ZH),英语(EN),日语(JP),广东话(Yue)和韩语(KO)的训练。CosyVoice生成的样本可以实现低于2%的WER和超过75%的说话人相似度,达到人类平价的质量水平。CosyVoice支持零样本上下文学习,这使得语音克隆只需要3秒的提示语音。音色、情感、韵律和风格可以在语言内部或跨语言复制。我们还发布了一个指令模型,它可以控制说话者身份,说话风格(例如,情感)和其他具有自然纹理指令的细粒度语言特征。

Speech-to-Speech Translation:

通过集成SenseVoice、LLMs和CosyVoice,我们可以毫不费力地执行语音到语音翻译(S2ST)。

Emotional VoiceChat 情感语音聊天:

通过集成SenseVoice、LLMs和CosyVoice,我们可以开发一个情感语音聊天应用程序。

Interactive Podcast 互动播客:通过集成SenseVoice,一个基于LLM的多智能体系统,具有实时世界知识,以及CosyVoice,我们可以创建一个交互式播客。

有声书:通过LLMs的分析能力来构建和识别书籍中的情感,并将其与CosyVoice合成,我们实现了具有增强表现力的有声读物。

CosyVoice:

在推理阶段概述CosyVoice模型。概括地说,CosyVoice包括一个自回归Transformer,用于为输入文本生成相应的语音标记,一个基于ODE的扩散模型,流匹配,用于从生成的语音标记重建Mel频谱,以及一个基于HiFiGAN的声码器,用于合成波形。虚线模块在特定模型用途中是可选的,例如跨语言、SFT推理等。[论文]

图1:所提出的CosyVoice模型的概述。(a)演示了 𝒮3
标记器,其中虚线模块仅在训练阶段使用。(b)是CosyVoice的示意图,由文本到令牌LLM和令牌到语音流匹配模型组成。 S、E和T表示“start of sequence”、“end of sequence”和“turn of speech”标记。虚线表示推理阶段的自回归解码。(c)提供了我们的流匹配模型的放大视图,该模型以概率密度路径上的时间步长 t处的说话者嵌入 𝐯、语义标记 μ、掩蔽语音特征 X~和中间状态 Xt为条件。
图2:(a)零触发上下文学习和(B)跨语言语音克隆的序列构建。LID表示目标语言标识符。

CosyVoice由四个组件组成,即文本编码器、语音分词器[ speech tokenizer]、大语言模型和条件流匹配模型。具体地说,文本编码器用于对齐文本和语音token的语义空间,而  speech tokenizer 用于提取语义记号,如图1(a)所示。我们采用一个大的语言模型来学习整个文本编码和语音标记序列,将TTS重新表述为一个给定文本作为提示的自回归序列生成问题。然后,如图1(c)所示,利用条件流匹配模型,通过最佳路径上的去噪过程将语音令牌转换为Mel频谱图 。2020)用于以所生成的Mel频谱图作为输入来合成波形。

语音的受监督语义令牌 [ speech tokenizer] :

采用有监督的自动语音识别(ASR)模型来导出用于语音的有监督的语义语音( 𝒮3 )分词器。该模型是我们专有的SenseVoice ASR模型的微调版本。它接受了多语言音频数据的训练,并具有丰富的音频内容理解能力。 与原始ASR模型不同,我们将编码器分为两部分,并在它们之间插入矢量量化层。给定Mel频谱图 X 作为输入,其经历位置编码和 Encoder1 以获得上下文感知表示 H :

然后,一个矢量量化器(VQ)参与获得离散令牌。 对于帧 l 处的隐藏表示 𝐡l ,码本 C 中的最近嵌入的索引被视为该时间步处的语音令牌 μl :

语音令牌的对应码本嵌入被用作量化的隐藏表示 H¯={𝐜μ1,𝐜μ2,…,𝐜μL} ,并通过剩余的编码器层 Encoder2 :

 在 Encoder2 之后,接下来是基于transformer的ASR解码器,预测文本标签的后验概率:

TTS的大型语言模型:

我们将TTS任务表述为具有大型语言模型的自回归语音令牌生成问题(LLM)。对于LLM,序列构建是最重要的事项,其构建如下:

S and E denote the start and end of sequence, respectively.T is “turn of speech” tokens. 𝐯 is a speaker embedding vector extracted from the speech X with a pre-trained voice-print model2. The text encodings Y¯={𝐲¯u}u⁣∈⁣[1:U] is obtained by passing the text through a Byte Pair Encoded (BPE) tokenizer and text encoder:

由于文本和语音标记位于不同的语义层,因此文本编码器用于对齐它们的语义空间并有利于LLM建模。 在文本编码和语音标记 {μl}l⁣∈⁣[1:L] 之间插入开始标识符T报告问题,语音标记 {μl}l⁣∈⁣[1:L] 是用2.1中描述的监督语义标记器提取的。在训练阶段,我们采用教师强迫方案,其中左移序列作为模式输入,原始序列作为期望输出。 注意,在训练期间仅考虑语音标记的交叉熵损失和:

Optimal-transport Conditional Flow Matching:

在CosyVoice中,采用最优传输条件流匹配模型(OT-CFM)来学习Mel谱图的分布,并以生成的语音令牌为条件从其生成样本。 与扩散概率模型(DPM)相比,OT-CFM可以实现更好的性能,具有更简单的梯度,更容易的训练和更快的生成.

  在连续时间归一化流(CNF)中,从先验分布 p0⁢(X) 到Mel谱图 q⁢(X) 的数据分布构造概率密度路径。 概率密度路径由依赖于时间的矢量场 νt⁢(X):[0,1]×ℝL∗D→ℝL∗D 定义,其通过以下常微分方程(ODE)生成流 ϕt :

流匹配模型(The flow matching model)用于估计条件概率 P(S|X, v, Sref)。其中,X 和 v 分别表示语音片段和说话人嵌入,S 和 Sref 分别表示目标和参考语音的梅尔频谱。该模型使用卷积 Transformer U-Net 来确定最优传输 ODE 中先验分布与目标分布之间的矢量场。在推理阶段,只需五到十次迭代即可生成令人满意的梅尔频谱图。此外,还采用无分类器指导技术,通过屏蔽 70% 到 100% 的前置特征条件来增强上下文学习能力。

在从预测的梅尔频谱图合成波形时,我们使用改进的 HiFTNet 声码器,以支持流式生成。

可以实现的任务:

(a)零触发上下文学习和(B)跨语言语音克隆的序列构建。LID表示语言标识符。

Multi-lingual Voice Generation 【多语言的语音合成】

Zero-shot In-context Generation 零样本上下文生成

CosyVoice模型具有零触发的上下文学习能力,允许仅用简短的参考语音样本复制任意语音。这个过程需要仔细构造令牌语言模型(LM)的输入序列,如图2所示。 对于同一语言的提示语音和输入文本,我们将它们合并成一个统一的输入,将提示语音标记视为预生成的。利用该输入序列,自回归LM迭代地预测后续令牌,直到其遇到针对前一元素的“序列结束”令牌E。 然而,当提示语音和输入文本在语言上不同时,我们省略与提示相关联的文本和标记,以防止原始语言的韵律特征影响目标语言。 重要的是要注意,提示文本(对应于提示语音的内容)可以通过人工注释或ASR模型(如SenseVoice)转录。与提示文本类似,提示令牌是使用 𝒮3 tokenizer从提示语音中提取的。在生成语音标记之后,它们被附加在提示标记之后,形成流匹配模型的复合条件。此外,说话人嵌入和梅尔声谱图的提示语音,以进一步提高音色和环境的一致性。

Instructed Voice Generation指令语音生成:

Speaker Identity Control、细粒度控制、Style Control、情感丰富的声音生成、Speaker Fine-tune、Speaker Interpolation

为了进一步实现对CosyVoice的可控性,我们尝试集成额外的指令微调(Ji 等人,2023年)。CosyVoice-instruct扩展了CosyVoice-base,具有增强的后续功能。具体地说,它支持对诸如说话人身份(即,说话者的特征)、说话风格(包括情感、性别、语速和音调)以及细粒度的副语言特征。这些功能包括插入笑声、呼吸、边笑边说以及强调某些单词的能力。

SenseVoice:

SenseVoice 是具有音频理解能力的音频基础模型,包括语音识别(ASR)、语种识别(LID)、语音情感识别(SER)和声学事件分类(AEC)或声学事件检测(AED)。提出了具有不同大小和架构的两个模型以适应不同的要求:SenseVoice-Small,用于快速语音理解的仅编码器语音基础模型,以及SenseVoice-Large,编码器-解码器(Vaswani 等人,2017)语音基础模型,用于更准确的语音理解,支持更多语言。

SenseVoice模型概述。SenseVoice是一个语音基础模型,具有多种语音理解功能,包括ASR、LID、SER和AED。SenseVoice-Small是一种用于快速语音理解的仅编码器语音基础模型,SenseVoice-Large是一种编码器-解码器语音基础模型,用于更准确的语音理解,支持更多语言。

𝐞LID 、 𝐞SER 、 𝐞AEC 、 𝐞ITN/NoITN 是四个特殊标记的嵌入:

⟨LID⟩ 表示LID任务。如果 ⟨LID⟩ 被放置 ,则模型被训练以预测输出的对应位置处的语言标记。 在训练阶段,我们根据概率0.8用真实语言标记随机替换 ⟨LID⟩ ,以便模型可以预测语言标记,或者在推理阶段配置指定的语言标记。

⟨SER⟩ 表示SER任务。如果 ⟨SER⟩ 被放置,则训练模型以预测输出的对应位置处的语音情感标签。

⟨AEC⟩ 表示AEC任务。如果 ⟨AEC⟩ 被放置 ,则模型被训练以预测输出的对应位置处的音频事件标签。

⟨ITN⟩ 或 ⟨NoITN⟩ 指定转录样式。如果提供了 ⟨ITN⟩ ,则模型被训练为使用反向文本规范化(ITN)和标点符号进行转录。如果提供了 ⟨NoITN⟩ ,则模型被训练为在没有ITN和标点符号的情况下转录。

在训练阶段,利用交叉熵损失对LID、SER和AEC任务进行优化。ASR任务使用CTC损失来优化

SenseVoice-Large是一个自回归编码器-解码器模型,用于多语言ASR和多语音理解任务。与Whisper类似(拉德福 等人,2023),SenseVoice-Large通过解码器的输入令牌序列来指定任务。具体来说,我们通过分别包括 ⟨LID⟩ 、 ⟨SER⟩ 、 ⟨AED⟩ 令牌来指定是否预测具有时间戳的语言、语音情感和音频事件。与SenseVoice-Small相比,SenseVoice-Large的优势在于转录准确性和支持大量语言(50+)。

SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测

  • 多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。
  • 富文本识别:
    • 具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。
    • 支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。
  • 高效推理: SenseVoice-Small 模型采用非自回归端到端框架,推理延迟极低,10s 音频推理仅耗时 70ms,15 倍优于 Whisper-Large。
  • 微调定制: 具备便捷的微调脚本与策略,方便用户根据业务场景修复长尾样本问题。
  • 服务部署: 具有完整的服务部署链路,支持多并发请求,支持客户端语言有,python、c++、html、java 与 c# 等。

推理效率:

表1. 比较了SenseVoice、Paraformer和Whisper的模型结构、参数规模、支持的语言和推理效率。SenseVoice-small采用非自回归架构,与Whisper相比,它在推理效率方面具有显着优势。

性能评测:

我们在开源基准数据集(包括AISHELL-1、AISHELL-2、Wenetspeech、Librisepeech和Common Voice)上比较了SenseVoice和Whisper的多语言识别性能和推理效率。使用A800机器进行推理效率评估。SenseVoice-small采用非自回归端到端架构,推理延迟极低-与Whisper-small相比快7倍,与Whisper-large相比快17倍。

1、文本识别:[在开源基准数据集(包括 AISHELL-1、AISHELL-2、Wenetspeech、Librispeech 和 Common Voice)上比较了 SenseVoice 与 Whisper 的多语言语音识别性能和推理效率。在中文和粤语识别效果上,SenseVoice-Small 模型具有明显的效果优势。]

2、情感识别

SenseVoice也可以用于离散情感识别。支持快乐、悲伤、愤怒和中立。我们在7个流行的情感识别数据集上对其进行了评估。SenseVoice-Large可以在大多数数据集上接近或超过SOTA结果,即使没有目标语料库微调。

由于目前缺乏被广泛使用的情感识别测试指标和方法,我们在多个测试集的多种指标进行测试,并与近年来 Benchmark 上的多个结果进行了全面的对比。所选取的测试集同时包含中文 / 英文两种语言以及表演、影视剧、自然对话等多种风格的数据,在不进行目标数据微调的前提下,SenseVoice 能够在测试数据上达到和超过目前最佳情感识别模型的效果。

我们还在测试集上对多个开源情感识别模型进行对比,结果表明,SenseVoice-Large 模型可以在几乎所有数据上都达到了最佳效果,而 SenseVoice-Small 模型同样可以在多数数据集上取得超越其他开源模型的效果。

3、事件检测

SenseVoice-Small和SenseVoice-Large模型都可以检测到语音中的音频事件,包括音乐、掌声、笑声。SenseVoice-Large可以预测音频事件的开始和结束位置,而SenseVoice Small只能预测音频中发生了什么(只有一个事件),但是,它可以检测更多的事件,例如在人机交互过程中可能发生的咳嗽,打喷嚏,呼吸和哭泣。

尽管 SenseVoice 只在语音数据上进行训练,它仍然可以作为事件检测模型进行单独使用。我们在环境音分类 ESC-50 数据集上与目前业内广泛使用的 BEATS 与 PANN 模型的效果进行了对比。SenseVoice 模型能够在这些任务上取得较好的效果,但受限于训练数据与训练方式,其事件分类效果专业的事件检测模型相比仍然有一定的差距。

限制:

1、SenseVoice有一些需要解决的局限性。首先,对于资源不足的语言,ASR性能通常要低得多。其次,SenseVoice不是为流式转录而设计的。因此,未来的工作可能会集中在开发基于SenseVoice的流式语音理解模型。

2、CosyVoice也有一些限制。首先,它支持的语言数量有限。虽然它可以根据明确的指令表达情感和说话风格,但它不能根据文本的语义内容推断出适当的情感或风格。此外,CosyVoice在唱歌时表现不佳。在保持声音原有音色的同时,实现富有表现力的情感变化仍有改进的空间。

3、另一个限制是FunAudioLLM中的两个创新模型没有使用LLMs进行端到端的训练。这种流水线方法可能会引入错误传播,这可能会影响整体性能。

sensevoice 推理代码:

    def inference(
        self,
        data_in,
        data_lengths=None,
        key: list = ["wav_file_tmp_name"],
        tokenizer=None,
        frontend=None,
        **kwargs,
    ):


        meta_data = {}
        if (
            isinstance(data_in, torch.Tensor) and kwargs.get("data_type", "sound") == "fbank"
        ):  # fbank
            speech, speech_lengths = data_in, data_lengths
            if len(speech.shape) < 3:
                speech = speech[None, :, :]
            if speech_lengths is None:
                speech_lengths = speech.shape[1]
        else:
            # extract fbank feats
            time1 = time.perf_counter()
            audio_sample_list = load_audio_text_image_video(
                data_in,
                fs=frontend.fs,
                audio_fs=kwargs.get("fs", 16000),
                data_type=kwargs.get("data_type", "sound"),
                tokenizer=tokenizer,
            )
            # print(audio_sample_list)
            time2 = time.perf_counter()
            meta_data["load_data"] = f"{time2 - time1:0.3f}"
            speech, speech_lengths = extract_fbank(
                audio_sample_list, data_type=kwargs.get("data_type", "sound"), frontend=frontend
            )
            time3 = time.perf_counter()
            meta_data["extract_feat"] = f"{time3 - time2:0.3f}"
            meta_data["batch_data_time"] = (
                speech_lengths.sum().item() * frontend.frame_shift * frontend.lfr_n / 1000
            )

        speech = speech.to(device=kwargs["device"])
        speech_lengths = speech_lengths.to(device=kwargs["device"])
        print("speech", speech.shape, speech_lengths)
        language = kwargs.get("language", "auto")
        language_query = self.embed(
            torch.LongTensor(
                [[self.lid_dict[language] if language in self.lid_dict else 0]]
            ).to(speech.device)
        ).repeat(speech.size(0), 1, 1)
        print("language_query", language_query.shape)
        use_itn = kwargs.get("use_itn", False)
        textnorm = kwargs.get("text_norm", None)
        if textnorm is None:
            textnorm = "withitn" if use_itn else "woitn"
        textnorm_query = self.embed(
            torch.LongTensor([[self.textnorm_dict[textnorm]]]).to(speech.device)
        ).repeat(speech.size(0), 1, 1)
        print("textnorm_query", textnorm_query.shape)
        speech = torch.cat((textnorm_query, speech), dim=1)
        speech_lengths += 1
        print("speech_add_textnorm", speech.shape, speech_lengths)
        event_emo_query = self.embed(torch.LongTensor([[1, 2]]).to(speech.device)).repeat(
            speech.size(0), 1, 1
        )
        print("event_emo_query", event_emo_query.shape)
        input_query = torch.cat((language_query, event_emo_query), dim=1)
        print("input_query", input_query.shape)
        speech = torch.cat((input_query, speech), dim=1)
        speech_lengths += 3
        print("speech_final", speech.shape, speech_lengths)

        # Encoder
        encoder_out, encoder_out_lens = self.encoder(speech, speech_lengths)
        print("encoder_out", encoder_out.shape, encoder_out_lens)
        if isinstance(encoder_out, tuple):
            encoder_out = encoder_out[0]

        # c. Passed the encoder result and the beam search

        # 束搜索和CTC解码
        ctc_logits = self.ctc.log_softmax(encoder_out)

        results = []
        b, n, d = encoder_out.size()
        if isinstance(key[0], (list, tuple)):
            key = key[0]
        if len(key) < b:
            key = key * b
        for i in range(b):

#对每个 batch 样本提取 CTC logits 输出的前 encoder_out_lens[i] 帧。
#使用 argmax 找到每个时间步概率最大的类别 ID (yseq)。
#使用 torch.unique_consecutive 去除连续的重复类别 ID(CTC 解码中的常见步骤,用于去除重复的符号)。
            x = ctc_logits[i, : encoder_out_lens[i].item(), :]
            yseq = x.argmax(dim=-1)
            yseq = torch.unique_consecutive(yseq, dim=-1) # 使用 torch.unique_consecutive 去除连续的重复类别 ID(CTC 解码中的常见步骤,用于去除重复的符号)

            ibest_writer = None
            if kwargs.get("output_dir") is not None:
                if not hasattr(self, "writer"):
                    self.writer = DatadirWriter(kwargs.get("output_dir"))
                ibest_writer = self.writer[f"1best_recog"]

#使用 mask 去掉 CTC 解码中的 blank ID。
#将整数 ID 列表转化为对应的字符或单词(通过 tokenizer.decode)。
            mask = yseq != self.blank_id
            token_int = yseq[mask].tolist()

            # Change integer-ids to tokens
            text = tokenizer.decode(token_int)

            result_i = {"key": key[i], "text": text}
            results.append(result_i)

            if ibest_writer is not None:
                ibest_writer["text"][key[i]] = text

        return results, meta_data

CTC使用blank id来对齐不同长度的输入和输出:

  • 在语音识别等任务中,输入的语音帧数往往远多于输出的字符数。CTC 通过引入 blank ID 来解决这个问题,使模型能够生成对齐(alignment),从而允许输入长度大于输出长度。
  • blank 用来表示在某个时间步模型没有输出任何字符,或者保持上一个字符的状态不变。

去除重复和冗余:

  • 语音帧与字符之间的对齐并不是一一对应的,CTC 会允许模型在多个时间步中输出相同的字符,同时在其他时间步输出 blank
  • 解码过程中,当遇到连续的相同字符时,只保留第一个字符,忽略重复出现的字符和 blank,这帮助去除冗余。
  • 例如,模型输出可能是 [a, blank, blank, a, a, blank, t, blank, blank],最终解码结果会变为 "a, t"

Sequence Modeling With CTC

网址: https://distill.pub/2017/ctc/

在语音识别中,我们的数据集是音频文件和其对应的文本,不幸的是,音频文件和文本很难在单词的单位上对齐。除了语言识别,在OCR,机器翻译中,都存在类似的Sequence to Sequence结构,同样也需要在预处理操作时进行对齐,但是这种对齐有时候是非常困难的。如果不使用对齐而直接训练模型时,由于人的语速的不同,或者字符间距离的不同,导致模型很难收敛。

我们可以设计一个规则,比如“一个字符对应十个语音输入”。但是人们的语速是不同的,所以这种规则总是可以被打破的。另一种方法是手动将每个字符与其在音频中的位置对齐。从建模的角度来看,这工作得很好,我们知道每个输入时间步的基本事实。 然而,这对数据集的标注工作是非常耗时的。

这个问题不仅仅出现在语音识别中。我们在许多其他地方看到它。来自图像或笔画序列的手写识别就是一个例子。

CTC(Connectionist Temporal Classification 连接时序分类)是一种避开输入与输出手动对齐的一种方式,是非常适合语音识别或者OCR这种应用的。

给定输入序列 𝑋=[𝑥1,𝑥2,…,𝑥𝑇] 以及对应的标签数据 𝑌=[𝑦1,𝑦2,..,𝑦𝑈] ,例如语音识别中的音频文件和文本文件。我们的工作是找到 𝑋 到 𝑌 的一个映射,这种对时序数据进行分类的算法叫做Temporal Classification。

对比传统的分类方法,时序分类有如下难点:

  1. 𝑋 和 𝑌 的长度都是变化的;
  2. 𝑋 和 𝑌 的长度是不相等的;
  3. 对于一个端到端的模型,我们并不希望手动设计𝑋 和 𝑌 的之间的对齐。

CTC提供了解决方案,对于一个给定的输入序列 𝑋 ,CTC给出所有可能的 𝑌 的输出分布。根据这个分布,我们可以输出最可能的结果或者给出某个输出的概率。我们会要求CTC有效地完成下面这两件事。

1、损失函数:给定输入序列 𝑋 ,我们希望最大化 𝑌 的后验概率 𝑃(𝑌|𝑋) , 𝑃(𝑌|𝑋) 应该是可导的,这样我们能执行梯度下降算法;

2、测试:给定一个训练好的模型和输入序列 𝑋 ,我们希望输出概率最高的 𝑌 :

当然,在测试时,我们希望 𝑌∗ 能够尽快的被搜索到。

算法详解

给定输入 𝑋 ,CTC输出每个可能输出及其条件概率。问题的关键是CTC的输出概率是如何考虑 𝑋 和 𝑌 之间的对齐的,这种对齐也是构建损失函数的基础。所以,首先我们分析CTC的对齐方式,然后我们在分析CTC的损失函数的构造。

1.1 对齐

需要注意的是,CTC本身是不需要对齐的,但是我们需要知道 𝑋 的输出路径和最终输出结果的对应关系,因为在CTC中,多个输出路径可能对应一个输出结果,举例来理解。例如在OCR的任务中,输入 𝑋 是含有“CAT”的图片,输出 𝑌 是文本[C, A, T]。将 𝑋 分割成若干个时间片,每个时间片得到一个输出,一个最简答的解决方案是合并连续重复出现的字母,如图2.

这个问题有两个缺点:

  1. 几乎不可能将 𝑋 的每个时间片都和输出Y对应上,例如OCR中字符的间隔,语音识别中的停顿;
  2. 不能处理有连续重复字符出现的情况,例如单词“HELLO”,按照上面的算法,输出的是“HELO”而非“HELLO”。

为了解决上面的问题,CTC引入了空白字符 𝜖 ,例如OCR中的字符间距,语音识别中的停顿均表示为 𝜖 。所以,CTC的对齐涉及去除重复字母和去除 𝜖 两部分,如图3。

这种对齐方式有三个特征:

  1. 𝑋 与 𝑌 之间的时间片映射是单调的,即如果 𝑋 向前移动一个时间片, 𝑌 保持不动或者也向前移动一个时间片;
  2. 𝑋 与 𝑌 之间的映射是多对一的,一个或多个输入元素可以与单个输出元素对齐,但反之则不然,所以也有了特征3;
  3. 𝑋 的长度大于等于 𝑌 的长度。

1.2 损失函数

CTC对齐为我们提供了一种从每个时间步的概率到输出序列的概率的自然方法。

也就是说,对应标签 𝑌 ,其关于输入 𝑋 的后验概率可以表示为所有映射为 𝑌 的路径之和,我们的目标就是最大化 𝑌 关于 𝑥=𝑦 的后验概率 𝑃(𝑌|𝑋) 。假设每个时间片的输出是相互独立的,则路径的后验概率是每个时间片概率的累积,公式及其详细含义如图5。

上面的CTC算法存在性能问题,对于一个时间片长度为 𝑇 的 𝑁 分类任务,所有可能的路径数为 𝑁𝑇 ,在很多情况下,这几乎是一个宇宙级别的数字,用于计算Loss几乎是不现实的。在CTC中采用了动态规划的思想来对查找路径进行剪枝,算法的核心思想是如果路径 𝜋1 和路径 𝜋2 在时间片 𝑡 之前的输出均相等,我们就可以提前合并他们,如图6。

其中,横轴的单位是 𝑋 的时间片,纵轴的单位是 𝑌 插入 𝜖 的序列 𝑍 。例如对于单词“ZOO”,插入 𝜖 后为:

𝑍={𝜖,𝑍,𝜖,𝑂,𝜖,𝑂,𝜖}

我们用 𝛼𝑠,𝑡 表示路径中已经合并的在横轴单位为 𝑡 ,纵轴单位为 𝑠 的节点。根据CTC的对齐方式的三个特征,输入有9个时间片,标签内容是“ZOO”, 𝑃(𝑌|𝑋) 的所有可能的合法路径如下图:

图7:CTC中单词ZOO的所有合法路径

有两个有效的起始节点和两个有效的最终节点,因为序列开头和结尾的 𝜖ϵ 是可选的。完全概率是最后两个节点的和。现在我们可以有效地计算损失函数,下一步是计算梯度并训练模型。CTC损失函数相对于每个时间步的输出概率是可微的,因为它只是它们的总和和乘积。考虑到这一点,我们可以解析地计算损失函数相对于(未归一化的)输出概率的梯度,并从那里像往常一样运行反向传播。

对于数据集 𝐷 ,模型的优化目标是最小化负对数似然:

1.3 预测

当我们训练好一个RNN模型时,给定一个输入序列 𝑋 ,我们需要找到最可能的输出,也就是求解

𝑌∗=arg⁡max𝑌⁡𝑝(𝑌|𝑋)

求解最可能的输出有两种方案,一种是Greedy Search,第二种是beam search

1.3.1 Greedy Search

每个时间片均取该时间片概率最高的节点作为输出:

1.3.2 Beam Search

Beam Search是寻找全局最优值和Greedy Search在查找时间和模型精度的一个折中。一个简单的beam search在每个时间片计算所有可能假设的概率,并从中选出最高的几个作为一组。然后再从这组假设的基础上产生概率最高的几个作为一组假设,依次进行,直到达到最后一个时间片,下图是beam search的宽度为3的搜索过程,红线为选中的假设。

到目前为止,我们提到了CTC的一些重要属性。在这里,我们将更深入地了解这些属性是什么以及它们提供了什么样的权衡。

CTC的性质:

  1. 条件独立:CTC的一个非常不合理的假设是其假设每个时间片都是相互独立的,这是一个非常不好的假设。在OCR或者语音识别中,各个时间片之间是含有一些语义信息的,所以如果能够在CTC中加入语言模型的话效果应该会有提升。
  2. 单调对齐:CTC的另外一个约束是输入 𝑋 与输出 𝑌 之间的单调对齐,在OCR和语音识别中,这种约束是成立的。但是在一些场景中例如机器翻译,这个约束便无效了。
  3. 多对一映射:CTC的又一个约束是输入序列 𝑋 的长度大于标签数据 𝑌 的长度,但是对于 𝑌 的长度大于 𝑋 的长度的场景,CTC便失效了。

GPT-4o背后的语音技术

5月14日凌晨,OpenAI推出了最新的生成模型GPT-4o,带来了一系列震撼的功能,用技术彻底颠覆了产品形态。产品最大的亮点在于:以近乎完美的交互方式,为每位用户带来GPT-4级别的智能体验。在语音方面,GPT-4o做到了实时低延迟,平均响应时间与人类反应速度相当,输出的语音能够理解极度贴合对话上下文,能够理解人类的情感情绪,听觉质量上佳,与真人无异。

OpenAI的博客:https://openai.com/index/hello-gpt-4o/

GPT-4o是一个any2any的多模态模型,能够接受文本、音频、图像、视频等多模态输入,也能够生成包含文本、语音、图像和视频等混合内容的多模态输出。限于篇幅,本文主要谈谈语音多模态的实现,并分享一些对于语音研究未来发展的看法。

当我们主要关注文本和语音模态时,GPT-4o其实就是一个语音语言模型(speech language model, SLM)。该SLM同时具备语音理解能力和语音合成能力,输入端和输出端均支持文本和语音的混合多模态。那么,这一SLM应该如何实现呢?在大语言模型(large language model, LLM)滥觞的今日,不难想到这样一种方法:将连续的语音数据离散化成如同单词(或者称token,词元)一样的表示,并入到LLM的词表中,再走一遍训练LLM的老路。

基于上述思想来构建SLM,需要解决以下几个问题:

  1. 语音如何离散化?
  2. 如何让LLM理解语音的token?加入语音token之后,LLM在语音数据的理解上是否具有涌现性?
  3. LLM如何合成/解码语音?

接下来,我们按图索骥,分别看看上述三个问题应该如何解决。看完现有的方案之后,也会谈谈一些关于工程实现的思考以及新兴语音技术对于游戏业务的影响。最后,我会给出一个完整的roadmap来收束全文。

语音的离散化:向LLM看齐!

在谈及语音离散化之前,我们先来看看语音和文本作为两种不同的模态,有什么区别,有什么联系。这直接关系到后文建模方法的选择以及离散化特征的关注点。

语音和文本的差别主要体现在:文本离散、序列短、信息密度高(几乎每个词都包含语义);语音则连续、序列长、信息密度低。语音序列长、信息密度低的特点,意味着语音数据有很大的压缩空间,这一点和图像非常类似。因此,一些用于图像的离散化压缩方法也可以用在语音上。

除了差异,语音和文本也有一定的联系:语音是文本的超集,既包含文本内容(说话人说了什么,也就是语义信息),也包含语音特有的音色、韵律、语速等声学信息(也叫做副语言)。既然语音包含文本,那么在NLP中预训练语言模型也可以用来建模语音中的上下文依赖关系,从而得到语音的离散化token。基于这些方法得到的token主要包含语音的语义信息。

花开两朵,各表一枝。我们先来看看语音的语义token如何获取。

语义token:  用MLM建模语音的上下文依赖

语音的语义建模方法,最常用到的就是BERT的MLM方法,比较经典的工作有三个:wav2vec 2.0[1]、HuBERT[2]和w2v-BERT[3]。

类似于BERT,wav2vec 2.0[1]在隐空间(latent space)随机mask了一定比例的语音输入,然后用基于对比学习的训练目标学习帧的表征。值得注意的一点是,对比学习中目标帧的离散化处理是一个非常巧妙的操作,它将无限的连续特征空间坍缩为有限的离散空间,让帧特征的鲁棒性更强了。这在语音领域上非常有用的trick,允许模型接受带有噪声的语音作为输入。

图1:wav2vec 2.0的模型架构

wav2vec 2.0只是借用了BERT中mask的操作,训练目标大体上是基于对比学习的范式。那么,能直接用BERT的MLM建模目标来得到高质量的语音表征吗?其后的HuBERT[2]做的就是这个事情。HuBERT[2]的核心点在于使用简单的KMeans聚类方法为语音数据抽取离散化的分类标签,也就是文中所说的hidden unit/acoustic unit。有了分类标签,然后就是用BERT的MLM loss来学习语音数据中内在的上下文依赖关系。对于KMeans聚类对初始值和K值高灵敏的特点,作者设计了ensemble和iterative refinement方法予以解决。前者就是多个聚类模型ensemble,后者就是先在基于MFCC的聚类标签上进行学习,学习到一定程度时,在模型学习到的表征重新聚类,再做一次BERT的学习。

图2:HuBERT的模型架构

既然对比学习可以学习语音的语义表征,BERT的MLM也可以,那将二者结合起来,会不会有互补的效果呢?w2v-BERT[3]做的就是这个事情。注意到:HuBERT中语音的离散token不是端到端获得的,需要用KMeans算法对特征进行离线聚类,而wav2vec 2.0又正好提供了音频帧的量化离散表征,HuBERT和wav2vec 2.0很容易就能缝合在一起。缝合的方法也是显然的:前面若干层做类似wav2vec 2.0的对比学习,学习出HuBERT要用的离散表征,然后在后面若干层做类似HuBERT的MLM训练。

图3:w2v-BERT的模型架构

声学token:压缩+离散

上一部分介绍的预训练模型做的是上下文关系的预训练,学习到的表征主要包含与上下文相关的语义信息。要想将语音的token还原成为真正具有真人表现力的信号,还需要有包含音色、韵律、语速等副语言信息的声学特征。声学特征的学习在很大程度上参考了图像领域的工作,用到的主要是类似于VQVAE[4]、VQGAN等的离散化压缩方法,并针对语音数据的特性做了优化。这一部分比较经典的工作就是SoundStream[5]和Encodec[6],二者的工作高度类似,我们放在一起来看。

说到压缩,最先想到的模型当然就是AutoEncoder(自编码器)。为提升压缩效率,有利于数字传输和存储,以及离散化建模的要求,压缩模型中还需要包含量化(quantization),将连续的音频信号转换为离散的数值。基于上述考虑,模型大体上应该是VQVAE[4]的结构。为了平衡VQ(Vector Quantization,向量量化)与音频实时高保真传输的矛盾,通常采用多个残差连接的codebook来进行量化,这个就是所谓的RVQ(具体分析过程可以参见知乎文章)。采用RVQ的好处主要有两个:其一,区分不同quantization block的分工,第一个block包含最重要的语义信息,后续的block包含还原语音的副语言信息;第二,模型训练时可随机采样前面若干个block来训练,保持一定精度,实现对比特率的动态适应。

总而言之,SoundStream[5]/Encodec[6]其实就是一个RVQ-VAE,它们所建模的语音离散化token包含了层次化的语义信息和声学信息。

图4:Encodec的模型架构

语音的统一表征?

不难发现,虽然说SoundStream[5]和Encodec[6]这样的基于RVQ-VAE的压缩建模方法包含了语音的声学特征,但其中也不可避免地带入了语义特征。二者提取的实际上更像是一种语义特征和声学特征的混合体。基于此,SpeechTokenizer[7]在二者的基础上,引入了语义引导信息来解耦语义特征和声学特征。语义特征和声学特征的解耦对于最终的语音合成有着相当的重要性。SpeechTokenizer的具体做法是:使用HuBERT[2]的特征对RVQ1的特征做语义蒸馏,其余部分保留声学信息。

图5:SpeechTokenizer的模型架构


语音的其他表征:MEL依旧有用!

上述的语音离散表征,不管是基于HuBERT[2]的语义token,还是基于Encodec[6]的声学token,它们都是直接基于原始的音频波形抽取的。除此之外,也可以基于语音的中间表征来抽取。最典型的语音中间表征就是梅尔谱(MEL spectrogram,下文简称MEL)。梅尔谱本身就对语音进行了压缩,将梅尔谱类比于图像,使用单码本的VQ也可以达到与SoundStream和Encodec那样类似的压缩程度。这种MEL+VQ的做法在各种语音合成模型中也相当常见。我们在语音合成部分会详细介绍。

让LLM理解语音token!

有了上面所说的语义token和声学token之后,其实就可以利用它们来构建语音层面的语言模型了。比较经典的工作有:谷歌的AudioLM[8]和AudioPaLM[9]、字节的SALMONN[10]、复旦的SpeechGPT[11]/SpeechGPT-Gen[12]/SpeechAlign[13]、阿里的LauraGPT[14]和新加坡国立大学的NextGPT[15]。它们的做法其实都大差不差,我们看几个就知道是怎么回事了。

AudioLM:最初的SLM

见名知义,AudioLM[8]构建的是语音层面的语言模型——给定一段语音,模型预测后续的语音。输入侧和输出侧都只有语音模态。这个任务形式和GPT-4o非常类似,不会经历ASR->LM->TTS的过程,而是直接从语音上下文中推理语义信息,再结合声学信息合成贴合上下文的高表现力语音。而上文所述的语义token和声学token正好就能满足这个任务的要求。

AudioLM的具体做法是:用SoundStream[5]提取声学token,用w2v-BERT[3]提取语义token,模型主体就是一个常规的GPT,词表包含所有的声学token和语义token。它的建模过程也相当有意思,有很大的参考意义:先做最重要的语义建模,然后先预测SoundStream的前若干层特征,建模粗糙的声学特征,在预测SoundStream的剩余层特征,建模声音的细节信息,最后基于所有的声学token还原为语音。这种层次化的建模在诸如VALL-E[16]这样的语音合成模型中也非常常见。

图6:AudioLM的tokenizer

图7:AudioLM的建模流程

当然,AudioLM[8]仅仅关注语音模态,LM也很常规,不具备如同GPT-4o一样强悍的指令遵循能力和对话能力,语音对话的连贯性和表现力都相当弱。但这一工作仍然具有相当的启发性和开拓性,证明了:即使是常规的LM,照样也能理解语音token。

AudioPaLM[9]:整合LLM

这个就是AudioLM的后续了,谷歌将常规的LM替换成已经训练好的、具有强大文本理解能力和生成能力的大语言模型——PaLM-2[17],既继承了AudioLM保留副语言的能力,又融合了PaLM-2强大的语义理解能力和推理能力。而且,该模型的词表同时包含大语言模型的token和语音token,可以同时做语音理解任务和合成生成任务,第一将这些任务整合在一个模型中进行解决。

不过,需要指出地是,文中的语音token embedding是直接输入到Transformer中的,并没有使用音频编码器做一次转换。而且,AudioPaLM的训练更加接近文本多任务的T5,并未用到复杂的、丰富多样的指令来表达任务的意图,还不能算是真正严格的instruction fine-tuning。

图8:AudioPaLM的模型架构

SALMONN[10]:让LLM理解语音

这是字节跳动和清华大学电子系(也是我们实验室)的合作成果。虽然这个工作的目的是让LLM能够理解语音,还不能生成语音,但它的训练方法和LLM比较接近,而且在诸多语音相关的任务上都显示出了涌现性,可以用作universal的特征提取器,这对于构建高质量的、包含语音-文本多模态的指令微调数据集具有相当大的意义。

图9:SALMONN的模型架构

SpeechGPT/SpeechGPT-Gen/SpeechAlign:向LLM的训练方法看齐

这算是复旦大学邱锡鹏组在这个领域一个成系列的工作,我们一个一个来看。

SpeechGPT[11]做的也是兼具语音理解能力和语音生成能力的多模态模型。在模型的训练上,SpeechGPT大幅度向LLM看齐,使用了三段式的训练方法:第一阶段先做模态适应的预训练,其实就是拿ASR的语音数据来做预训练;第二阶段和第三阶段都是指令微调,不过根据指令模态的不同,细分为了跨模态的指令微调和模态链指令微调。指令微调的数据集都是来自ASR数据集。描述任务需求的指令由GPT-4生成。

在我看来,这个工作还是相当偏学术化的作品,文中有不少点都有值得商榷的地方:第一,语音的离散化仅仅用了HuBERT[2],模型只能看到语音的语义特征,这对模型合成语音的音质和表现力有非常大的影响,demo的语音也验证了我的判断;第二,指令微调数据集的构造上有问题。他们用的是ASR数据集,其实更好的选择应该是TTS数据集,可惜高质量的TTS数据集实在是太少了。ASR数据集中的文本和语音可能并不是严格对齐的,GPT-4产生的meta-prompt和语音本身的特征也有可能是对不上的,比如prompt要求大声朗读,但语音本身可能是特定低沉的。meta-prompt本身就无法做到足够复杂丰富,不能描述到语音的一些细粒度信息。

这一部分,最好要有像诸如SALMONN[10]这样的多模态语音理解模型的介入,像DALLE3一样丰富指令的多样性。至于语音方面,可以考虑引入zero-shot的语音合成模型或者变声模型来做合成数据。第三,文中的训练方法也没有与人类偏好做对齐。

图10:SpeechGPT的模型架构

对于上面的第一个问题,作者在其后的SpeechGPT-Gen[12]中做了解决。解决思路的核心点就是:让模型不仅看到语音的语义token,也要看到语音的声学token。具体做法是:SpeechGPT的HuBERT特征替换成了SpeechTokenizer[7]中的语义特征,用SpeechGPT这一LLM来自回归地建模语义特征,有了语义特征之后,再使用Flow-Matching这样的扩散模型来建模声学特征。这里选用Flow-Matching扩散模型,可能是受了SD3和Voicebox/Audiobox的影响。为了增强两阶段建模的依赖关系,作者将语义特征的先验信息注入到第二阶段扩散模型的先验分布中。可以看到,这里语音的解码其实也是一种层次化渐进式解码。

图11:SpeechGPT-Gen的模型架构

SpeechAlign[13]做的则是SLM与人类偏好的对齐,彻底地向LLM的训练方法看齐。该工作构建了对比gold token和合成token的encodec数据集,然后进行偏好优化来进行改进。使用的偏好优化方法包括RLHF和Chain of Hindsight。

图12:SpeechAlign的流程图

简单总结一下上面这些工作中值得关注的点:

  1. 要想让LLM输出上下文连贯的高表现力语音,必须要让LLM看到语义token和声学token,只有语义token,那语音就会显得呆板机械,只有声学token,那语音就不知所云;
  2. LLM的指令微调同样可以迁移到语音-文本多模态领域中,LLM的指令微调同样可以带来如同NLP一样的涌现性;
  3. 高质量指令微调数据集的构建应该是最大的瓶颈!一下子让LLM同时做语音理解和语音生成,难度非常大。不如分步进行。
  4. 如果要分步进行的话,要先实现一个类似于SALMONN[10]那样的多模态理解模型和一个强大的Zero-shot TTS模型。前者用于给语音数据打上丰富的标签,可以是情感情绪、韵律、音高、语速,也可以是口音、意图和说话环境;后者则用于生成高质量的语音数据。毕竟,高质量的、文本和语音严格对齐的TTS数据实在是太少了,尤其是中文领域。有了这两个模型的加持,我们其实就能够构造出高质量的指令微调数据集。我不知道OpenAI是否有SALMONN这样的模型,但OpenAI的OpenVoice模型应该足够为其提供高质量的语音数据了。

既然我们在上面的篇幅中论述了语音理解多模态模型的构建,那我们在下一部分就重点关注zero-shot TTS模型,它对高质量指令微调数据集的构建同样至关重要。同时,LLM解码语音的方法也能从zero-shot TTS方案中得到不少的启发。

LLM如何合成语音:Zero-shot TTS

前面说到,SLM词表中包含了语音的语义token和声学token。语义token保证生成语音与对话上下文的连贯性,声学token保证了合成语音的质量和表现力。要想做到合成上下文连贯的高自然度语音,有两个问题必须要解决:

  1. 语音既有语义token,又有声学token,应该要如何解码成语音?
  2. SLM在合成语音的过程中是否能够遵循多轮对话中的文本指令和语音指令?这个很重要!这允许模型根据用户的即时要求来生成语音回复。比如说,OpenAI演示视频中出现的:“将语速提高两倍”、“采用更加机械化的语气”这样的要求。

对于第一个问题,以VALL-E[16]为代表的诸多zero-shot TTS模型给出了不同的解决方案,这些方案虽有不同,但也有不可忽视的共同点;对于第二个问题,以VoiceLDM[18]和ParlerTTS[19]为代表的text/prompt-guided zero-shot TTS工作给出了肯定的答案。简单解释一下text/prompt-guided zero-shot TTS是怎么回事,通常的语音合成就是将文本(transcription)转换成声音,该任务在transcription之外,又增加了description的输入,来描述合成语音的情感情绪、口音、语气、语速、音高、说话环境、氛围等等信息。我们逐个来看这些工作。

Zero-shot TTS

2023年以来,学术界和工业界出了不少具备in-context learning(zero-shot/few-shot)能力的TTS模型。这些TTS模型通常会将低信息密度、长序列的连续语音数据压缩为高信息密度的tokens或者latents(其实就是码本中具体的token embedding)。这些模型本质上做的事情就是:如何高效实现语音tokens/latents到音频波形的映射。

这些模型给出的解决方案基本上都遵循一个准则:语义token和声学token层次化解码,先语义后声学,或者先解码成MEL再后接声码器,并且非必要不做自回归(毕竟自回归上线虽高,但太吃数据了)!我们一个个来看。

基于声学token或语义token的工作

先是微软的VALL-E[16]。这是zero-shot TTS的开山之作,首次在TTS任务上采用了上万小时的数据。它采用Encodec将语音转换为离散的token,然后用GPT在token上做语言模型的任务。但是,语音毕竟不是文本,如果直接在语音的所有特征上都做自回归的话,那训练的成本会相当高。考虑到Encodec RVQ特征的层次性,低层特征表示语义内容这样的重要特征,高层特征则表征声学细节。前者具有比较强的上下文依赖关系,适合用自回归来建模,后者诸如音色这样的特征,具有全局性,用非自回归特征也可以搞定,所以就有了VALLE中自回归+非自回归的层次建模方式。

图13:VALL-E的模型架构

尽管VALL-E[16]在用GPT建模token的上下文关系的时候,基于token的层次化特性做了分治处理,可能是限于当前语音数据集的规模(几万小时可能不够),这种GPT自回归的难度还是相当大的,解码过程存在常见的错误传播现象,鲁棒性非常差,极其不稳定。根据Ilya Sutskever此前对于自回归的论述,GPT自回归相比于BERT这种双向结构是非常data-hungry的,万小时的数据可能不够。根据本人以及一些同行的经验,VALL-E模型这一类的自回归模型,也包括tortoise-tts[20]和xtts v2,要想显出威力,至少要有十几万小时的数据才行。

既然GPT自回归的难度这么大,就有不少人想方设法地来降低GPT学习的难度了。他们的解决方案也非常类似:给GPT提供额外的条件信息不就行了。比较典型的工作就是微软的RALL-E[21]和吉利的HAM-TTS[22]。RALL-E先生成了时长信息和音高信息,作为GPT自回归的先验,之所以会补充时长和音高,这大概是受到FastSpeech2[23]这样的非自回归模型的启发,这两个指标的引入,有助于提升合成的鲁棒性;HAM-TTS则是补充了基于HuBERT的语义信息。值得注意地是,HAM-TTS将模型的训练数据扩充到了65万小时,其中有50万小时的数据是合成数据。合成数据也能大幅度提升合成语音的音质。

图14:RALL-E的模型架构,框出来的就是辅助信息

图15:HAM-TTS的模型架构

说到VALL-E的后续改进,VoiceCraft不得不提。我愿意称之为“优雅的VALL-E”。它的优雅主要体现在两个方面:casual masking和delayed stacking。所谓的causal masking,是为了用自回归GPT架构来做语音编辑任务,就是把被mask的部分移动到序列末尾去预测,一套架构同时做合成和编辑任务;所谓的delay stacking,是为了适配自回归和RVQ,通过delay错位让当前码本的token预测正好可以利用前面那些token的预测结果,比起VALL-E那样自回归和非自回归缝合在一起的结构要优雅不少。

图16:VoiceCraft的建模流程

基于声学/语义latents的工作

我们通常所说的语音token是离散的。如果使用对应码本中的embedding来表示语音的话,它也可以是连续的低维度的latent变量。既然是低维度的连续latent变量,那图像合成领域中大火的LDM(latent diffusion model,其实就是stable diffsion 1&2采用的模型)模型[]自然也可以用到语音的合成上。这方面的经典工作有很多,比如说:NaturalSpeech 2&3[25, 26]、AudioLDM 2[27]、VoiceLDM[18]。但这里面只有NaturalSpeech2用到了语音离散化部分提及的声学/语义token,NaturalSpeech3的属性分解形式的VQ更像是另一种形式的RVQ。我们先来看NaturalSpeech 2&3,其他的工作后面再来看。

首先是NaturalSpeech 2[26],它基本上就是VALL-E的连续版本。它用的latent也是来自Encodec,对其中不同层次的latent做了求和,然后将其作为扩散模型的训练目标。值得注意地是,扩散模型和FastSpeech2一样也用了时长和音高作为合成的先验条件。这一点也被后来的RALL-E采用。该工作中的扩散模型采用WaveNet实现,同时预测不加噪的latent和后验均值,和图像合成领域的扩散模型在实现方式上还是有所不同的。

图17:NaturalSpeech2的模型架构

然后是NaturalSpeech 3[26],还是非自回归的,而且非自回归的正统性味道更加浓厚,借用了不少FastSpeech2和megatts1&2(后面会讲)[27, 28]的设计思想。像megatts 1&2一样,同样采用(自)监督信号对语音token编码的内容做了限制,而不再像是VALL-E/NaturalSpeech2那样一把抓。相应地,语音token化的方法也用VQ就行。具体而言,文章将语音信号分解为时长、内容、韵律和细节四个部分,然后每个部分用离散化的扩散模型来建模。不过,原文使用GRL来促进语音属性的分解,这一点的靠谱程度存疑。我也尝试过文章的FACodec,但效果很差。三级扩散模型级联的结构,预测起来似乎也非常麻烦。

图18:NaturalSpeech3的模型架构

基于MEL谱+VQ的TOKEN的工作

当然,也有不少工作用了MEL谱作为中间特征,然后在梅尔谱的基础上,或是用VQ提供离散token,或是用CNN来提取连续latent。对于MEL+VQ的工作,有tortoise-tts[20]、xtts 1&2、megatts1&2[28, 29]、base TTS[30]。对于MEL+latents的工作,有:AudioLDM 1&2[27]、StyleTTS 1&2[31, 32]。我们来简单看看是它们是怎么做的。

Tortoise-tts[20]。该工作是著名的开源英文TTS模型。其作者目前在OpenAI就职,同时也是GPT-4o的重要Contributor(他自个儿在博客中说的)。Tortoise-tts使用MEL+VQVAE的方法得到语音的MEL token,然后对MEL token以及text token做GPT自回归建模。对于语音的解码,自然也是分为两步:先是用扩散模型将MEL token转换为MEL谱,这一步和文生图很像,用扩散模型是很自然的选择;然后用声码器将MEL谱转换为音频波形。tortoise-tts和VALL-E的主体都是自回归建模,二者的不同主要在于token的不同。

图19:tortoise-tts的模型架构

MegaTTS 1&2[28, 29]。字节跳动的MegaTTS系列对语音token编码信息做了显式的信息压缩处理,让语音token仅编码上下文依赖强的韵律信息,然后用GPT自回归来建模语音的韵律。对于其他方面的信息,模型的处理显得较为常规:音色一般具有全局性,使用单一的音色编码器从参考音频中提取就性;对于文本语义内容的处理,模型在很大程度上参考了非自回归的FastSpeech 2。

对于语音的解码,也是分为两步:先通过MEL decoder还原为MEL谱,然后通过声码器解码为音频波形。MegaTTS 2和1总体上类似,在音色编码(音素级编码、多条参考音频)、语音提示长度(扩展同speaker语音上下文长度硬train,音频prompt长度更长)和时长建模(也用GPT自回归)上做了改进,同时堆了更大规模的数据。剪映的后端TTS模型用的就是megatts2。该工作在各论文的评测中表现也都不错。

图20:megatts1的模型架构

基于MEL谱+VAE的latents的工作

AudioLDM 1&2[27]。AudioLDM 1&2使用的语音latents是一致的,均通过MEL+VAE获得。既然是连续的latents,使用扩散模型来建模也合情合理。解码过程也相当简单:VAE decoder获得梅尔谱,然后用声码器转换为音频波形。该系列工作的核心创新点是利用多模态模型统一了扩散模型条件输入侧的信息:AudioLDM 1用CLAP统一了文本模态和音频模态,用单模态的音频数据就能完成模型的训练;AudioLDM 2则包含了图像、文本、转录文本等更多模态,模型泛用性也更强,既能做语音合成,也能做音乐生成、音频事件生成。

图21:AudioLDM 1的模型架构

图22:AudioLDM2的模型架构

StyleTTS 1&2[31, 32]。StyleTTS系列的模型一众zero-shot TTS模型显得比较老派,整体结构基本上沿袭了非自回归的FastSpeech 2,不同之处在于增加了基于参考音频抽取的风格信息。说是风格,其实跟megatts的音色很像。StyleTTS 2的工作则将风格进一步拆分成声学风格和韵律风格。训练时的风格信息由音频提供,推断时的风格信息则由扩散模型提供。StyleTTS 2通过一个扩散模型桥接了文本韵律和语音风格之间的联系,摆脱推断时对参考音频的依赖。不用参考音频其实对产品的意义还挺大的,要都用现实世界中真人尤其是名人的声音作为参考音频,那这势必会引起版权纠纷。这种纠纷在国内国外都有相关的事件。最近寡姐投诉OpenAI的事件就是一例。

图23:StyleTTS 1的模型架构

图24:StyleTTS 2的模型架构

TTS对指令的遵循

SLM不仅要合成合乎上下文语义的高表现力语音,合成的语音还要符合用户的即时要求。一些text-guided zero-shot TTS的工作值得参考。这些工作一般都是在已有的zero-shot TTS模型或者text-to-audio模型上改造而来,同时吸收transcription和description两路条件。其中的重点还是在于数据集的构建。这方面的工作有:PromptTTS[33]、InstructTTS[34]、ParlerTTS[19]、VoiceLDM[18]和Audiobox[35]。我们主要谈谈ParlerTTS和VoiceLDM。

ParlerTTS[19]。VALL-E/VoiceCraft的增强版,通过T5编码器和cross-attention旁路引入了描述性文本的信息。该工作的目的是想使用自然语言prompt来指定说话风格和环境信息,摆脱对参考音频的依赖。描述性标签文本的收集过程也显得相当朴素:通过定制化的监督式模型获取语音数据的口音特征、录音质量特征、音高语速特征。然后用LLM将这些特征转换为自然语言的描述。在我看来,这个工作有这么几点局限性吧:其一,缺乏情绪标签;其二,语音描述性标签的收集并不具备通用性,较为繁琐,远不如一个强大的多模态语音理解模型来得实在。文章demo虽然达到了预期的效果,但场景似乎局限在朗读的情景中。

图25:ParlerTTS的模型架构

VoiceLDM[18]。在VoiceLDM1的基础上增加了转录文本的输入。这个工作和AudioLDM 1很像,同样使用CLAP注入语音的描述性信息。不同地是,为了做TTS任务,该工作通过cross-attention旁路增加了transcription的信息。

图26:VoiceLDM的模型架构

TTS总结

林林总总说了这么多zero-shot的TTS方法,我想说明的结论有这么几点:

  1. 在LLM大行其道、scaling law大显神威的时代,TTS模型的训练数据规模已经突破了万小时,甚至达到了数十万小时的级别。在大数据的加持下,TTS任务上也涌现出了in-context learning能力。
  2. 语音信息的解码通常都要层次化或者多步进行,不能一步到位。自回归、扩散模型和流匹配都能在TTS中发挥作用;
  3. 借鉴NLP instruction fine-tuning和文生图的经验,TTS模型同样可以遵循文本指令或者语音指令,合成符合用户即时要求的语音,摆脱对参考音频的依赖,这或许也能规避一些知识产权的困扰(比如最近有名的寡姐投诉OpenAI事件)。同时,用户也能在对话过程中随时切换语音回复的风格,这一点在OpenAI的demo中有很明确的体现。另外,不知道大家有没有注意,GPT-4o合成的语音是可以是放映所处的声学环境的:有一段语音背后似乎是有钢琴声的。
  4. text-guided zero-shot TTS在模型架构上和zero-shot TTS有非常大的相似性。但训练数据可能较为缺乏。先开发zero-shot TTS,再用类似SALMONN那样的多模态理解模型来打标签(类似DALLE3的做法),这样数据集构造方式,可能会是更好的选择。

另外,对于语音的解码方案,我倾向于是这样的:

  1. 如果要做流式推理,外接类似HIFIGAN这样的声码器的方式可能不是好的选择。HIFIGAN并不天然支持流式解码。相反地,诸如SoundStream和Encodec这样的方法,同时有流式变体和非流式变体;
  2. 先做语义token的解码,这个解码大概率是自回归解码。语义token毕竟是建模上下文依赖关系,自回归方法已经在NLP上证明了这一点;
  3. 然后做声学token的解码,扩散或者flow-matching可能是更好的选择。扩散模型或者流匹配可以很好地修补语音的细节;

当然,除了上面讲到的,zero-shot TTS还有很多值得研究的方法。限于篇幅,仅列举于此,不再详述:HierSpeech++[36]、base TTS[30]、Voicebox/Audiobox[35]、UniAudio[37]、Make-a-Voice[38]等等。

其他问题

对于GPT-4o模型,如果仅仅聚焦于语音多模态,还有下面的问题值得关注:

  1. 语音交互如何做到低延迟?大概率要求流式切片处理,主要工作在于工程优化,用C++重写算子。推理框架的话,用tensorrt、mnn这些都行。上下文所述的音频离散化方法,诸如SoundStream和Encodec,其实也支持流式处理。
  2. 语音对话中的打断如何实现?个人认为有两种可能的方案:turn-based和流式处理。所谓的turn-based方案,是比较工程化的,简答概括一下就是:检测是否有停顿,如果一段时间内没有声音,模型就开始返回语音回复。另一种流式方案,则是:模型一直在接受用户的流式语音输入,判断是否应该输出语音回复,一个充分训练的模型应该是能够准确预测出语音词表中的[START]和[END]的。

对游戏配音业务的思考

text/prompt-guided zero-shot TTS方法对游戏的AI配音意义重大。主要体现在:

  1. 用自然语言提示去合成音色稳定的语音,摆脱对参考音频的依赖,在业务中能够更加灵活,至少比克隆已有人物/角色的语音的方式更加方便,更不容易出戏。举个例子,在开放世界剧情类游戏的研发阶段,我们会设定一些profile赋予NPC,让玩家跟NPC聊天。我们曾经用克隆《原神》、《崩坏:星穹铁道》已有角色的方式赋予这些NPC角色语音,但放在那些欧美背景的NPC中,就是很有违和感,没有现实世界中的accent,不够decent。
  2. 剧情任务中的配音会更加真人化、更有沉浸感。过年期间过《崩坏:星穹铁道》花火和黑天鹅的同行任务的时候,部分NPC角色会有六公主的翻译腔,这是花火行于欢愉命途的恶趣味,空气中顿时充满了快活的味道。如果走bv2、gsv的语音克隆方案,应该是很难有这种效果的。而且,玩家在剧情任务中势必会经过不同的地势地貌,至少室内、室外的声音听起来是有不同的。室内的声音至少会有回响、混响的吧。这种感觉语音克隆方案也是无法做到的。

全文总结

总结一下本文说谈的内容,我认为GPT-4o语音多模态的实现可能是走了以下的技术路线:

  1. audio & text tokenizer的实现应该是语音离散化部分所用的技术,例如SoundStream、Encodec、SpeechTokenizer,或者是MEL+VQ最后配合声码器来解码;参考zero-shot TTS、AudioLM/AudioPaLM、SpeechGPT-Gen等工作的结果,LLM中语音token的解码应该是要走层次化或者多步的方法,先解码语义特征,再解码声学特征,或者是先解码MEL,再加一个HIFIGAN这样的声码器。另外,如果做audio/speech/music这样的通用声合成的话,可能也能通过prompt来控制。AudioLDM2虽然做了这方面的工作,但audio/music和speech的参数其实是不一样的,说到底还不是同一个模型。
  2. 对于指令微调,数据集的构造非常重要,大概率要用到合成数据。其一,网络上高质量语音数据的量级远远不及文本,直接拿ASR数据来做肯定会影响模型合成语音的音质;其二,大语言模型合成的instruction往往触及不到语音的细粒度特征,这样的instruction其实无法准确详尽地描述text和speech之间的关系。因而,需要引入强大的zero-shot TTS模型合成高质量语音,然后用多模态语音理解模型来为合成语音打标签,当然也可以评分做筛选什么的。
  3. 最后是要让大模型的输出对齐人类的偏好。这方面的方法有很多,有DPO、PPO什么的,都可以用。

图27:全文总结,可能的roadmap

参考文献

[1] Baevski A, Zhou Y, Mohamed A, et al. wav2vec 2.0: A framework for self-supervised learning of speech representations[J]. Advances in neural information processing systems, 2020, 33: 12449-12460.

[2] Hsu W N, Bolte B, Tsai Y H H, et al. Hubert: Self-supervised speech representation learning by masked prediction of hidden units[J]. IEEE/ACM Transactions on Audio, Speech, and Language Processing, 2021, 29: 3451-3460.

[3] Chung Y A, Zhang Y, Han W, et al. W2v-bert: Combining contrastive learning and masked language modeling for self-supervised speech pre-training[C]//2021 IEEE Automatic Speech Recognition and Understanding Workshop (ASRU). IEEE, 2021: 244-250.

[4] Van Den Oord A, Vinyals O. Neural discrete representation learning[J]. Advances in neural information processing systems, 2017, 30.

[5] Zeghidour N, Luebs A, Omran A, et al. Soundstream: An end-to-end neural audio codec[J]. IEEE/ACM Transactions on Audio, Speech, and Language Processing, 2021, 30: 495-507.

[6] Défossez A, Copet J, Synnaeve G, et al. High fidelity neural audio compression[J]. arXiv preprint arXiv:2210.13438, 2022.

[7] Zhang X, Zhang D, Li S, et al. Speechtokenizer: Unified speech tokenizer for speech large language models[J]. arXiv preprint arXiv:2308.16692, 2023.

[8] Borsos Z, Marinier R, Vincent D, et al. Audiolm: a language modeling approach to audio generation[J]. IEEE/ACM Transactions on Audio, Speech, and Language Processing, 2023.

[9] Rubenstein P K, Asawaroengchai C, Nguyen D D, et al. Audiopalm: A large language model that can speak and listen[J]. arXiv preprint arXiv:2306.12925, 2023.

[10] Changli Tang, Wenyi Yu, Guangzhi Sun, Xianzhao Chen, Tian Tan, Wei Li, Lu Lu, Zejun Ma, Chao Zhang. SALMONN: Towards Generic Hearing Abilities for Large Language Models

[11] Zhang D, Li S, Zhang X, et al. Speechgpt: Empowering large language models with intrinsic cross-modal conversational abilities[J]. arXiv preprint arXiv:2305.11000, 2023.

[12] Zhang D, Zhang X, Zhan J, et al. SpeechGPT-Gen: Scaling Chain-of-Information Speech Generation[J]. arXiv preprint arXiv:2401.13527, 2024.

[13] Zhang D, Li Z, Li S, et al. SpeechAlign: Aligning Speech Generation to Human Preferences[J]. arXiv preprint arXiv:2404.05600, 2024.

[14] Chen Q, Chu Y, Gao Z, et al. Lauragpt: Listen, attend, understand, and regenerate audio with gpt[J]. arXiv preprint arXiv:2310.04673, 2023.

[15] Wu S, Fei H, Qu L, et al. Next-gpt: Any-to-any multimodal llm[J]. arXiv preprint arXiv:2309.05519, 2023.

[16] Wang C, Chen S, Wu Y, et al. Neural codec language models are zero-shot text to speech synthesizers[J]. arXiv preprint arXiv:2301.02111, 2023.

[17] Anil R, Dai A M, Firat O, et al. Palm 2 technical report[J]. arXiv preprint arXiv:2305.10403, 2023.

[18] Lee Y, Yeon I, Nam J, et al. VoiceLDM: Text-to-Speech with Environmental Context[C]//ICASSP 2024-2024 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2024: 12566-12571.

[19] Lyth D, King S. Natural language guidance of high-fidelity text-to-speech with synthetic annotations[J]. arXiv preprint arXiv:2402.01912, 2024.

[20] Betker J. Better speech synthesis through scaling[J]. arXiv preprint arXiv:2305.07243, 2023.

[21] Xin D, Tan X, Shen K, et al. RALL-E: Robust Codec Language Modeling with Chain-of-Thought Prompting for Text-to-Speech Synthesis[J]. arXiv preprint arXiv:2404.03204, 2024.

[22] Wang C, Zeng C, Zhang B, et al. HAM-TTS: Hierarchical Acoustic Modeling for Token-Based Zero-Shot Text-to-Speech with Model and Data Scaling[J]. arXiv preprint arXiv:2403.05989, 2024.

[23] Ren Y, Hu C, Tan X, et al. Fastspeech 2: Fast and high-quality end-to-end text to speech[J]. arXiv preprint arXiv:2006.04558, 2020.

[24] Rombach R, Blattmann A, Lorenz D, et al. High-resolution image synthesis with latent diffusion models[C]//Proceedings of the IEEE/CVF conference on computer vision and pattern recognition. 2022: 10684-10695.

[25] Shen K, Ju Z, Tan X, et al. Naturalspeech 2: Latent diffusion models are natural and zero-shot speech and singing synthesizers[J]. arXiv preprint arXiv:2304.09116, 2023.

[26] Ju Z, Wang Y, Shen K, et al. NaturalSpeech 3: Zero-shot speech synthesis with factorized codec and diffusion models[J]. arXiv preprint arXiv:2403.03100, 2024.

[27] Liu H, Tian Q, Yuan Y, et al. AudioLDM 2: Learning holistic audio generation with self-supervised pretraining[J]. arXiv preprint arXiv:2308.05734, 2023.

[28] Jiang Z, Ren Y, Ye Z, et al. Mega-tts: Zero-shot text-to-speech at scale with intrinsic inductive bias[J]. arXiv preprint arXiv:2306.03509, 2023.

[29] Jiang Z, Liu J, Ren Y, et al. Mega-tts 2: Zero-shot text-to-speech with arbitrary length speech prompts[J]. arXiv preprint arXiv:2307.07218, 2023.

[30] Łajszczak M, Cámbara G, Li Y, et al. BASE TTS: Lessons from building a billion-parameter text-to-speech model on 100K hours of data[J]. arXiv preprint arXiv:2402.08093, 2024.

[31] Li Y A, Han C, Mesgarani N. Styletts: A style-based generative model for natural and diverse text-to-speech synthesis[J]. arXiv preprint arXiv:2205.15439, 2022.

[32] Li Y A, Han C, Raghavan V, et al. Styletts 2: Towards human-level text-to-speech through style diffusion and adversarial training with large speech language models[J]. Advances in Neural Information Processing Systems, 2024, 36.

[33] Guo Z, Leng Y, Wu Y, et al. Prompttts: Controllable text-to-speech with text descriptions[C]//ICASSP 2023-2023 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP). IEEE, 2023: 1-5.

[34] Yang D, Liu S, Huang R, et al. Instructtts: Modelling expressive TTS in discrete latent space with natural language style prompt[J]. arXiv preprint arXiv:2301.13662, 2023.

[35] Vyas A, Shi B, Le M, et al. Audiobox: Unified audio generation with natural language prompts[J]. arXiv preprint arXiv:2312.15821, 2023.

[36] Lee S H, Choi H Y, Kim S B, et al. HierSpeech++: Bridging the Gap between Semantic and Acoustic Representation of Speech by Hierarchical Variational Inference for Zero-shot Speech Synthesis[J]. arXiv preprint arXiv:2311.12454, 2023.

[37] Yang D, Tian J, Tan X, et al. Uniaudio: An audio foundation model toward universal audio generation[J]. arXiv preprint arXiv:2310.00704, 2023.

[38] Huang R, Zhang C, Wang Y, et al. Make-a-voice: Unified voice synthesis with discrete representation[J]. arXiv preprint arXiv:2305.19269, 2023.

语音信号基本概念– 采样率、采样深度和比特率

(1) 采样率/采样频率

我们经常听到的第一个术语是采样率或采样频率,两者指的是同一件事。你可能遇到过的一些数值是8kHz、44.1kHz和48kHz。究竟什么是音频文件的采样率?

采样率是指每秒钟记录的音频样本数。它是以每秒的样本或赫兹(缩写为Hz或kHz,1kHz为1000Hz)来衡量。一个音频样本只是一个数字,代表在一个特定时间点的测量声波值。非常重要的一点是,这些样本是在一秒钟内时间上相等的时刻采集的。例如,如果采样率是8000赫兹,那么在一秒钟内有8000个采样是不够的;它们必须在一秒钟的1/8000时间内准确地被采集。在这种情况下,1/8000的数字被称为采样间隔(以秒为单位),而采样率只是该间隔的乘法倒数。

采样率类似于视频的帧率或FPS(每秒帧数)测量。视频只是一系列的图片,在这里通常称为 “帧”,非常快速地背对背显示,给人以连续不间断运动或移动的错觉(至少对我们人类来说)。

虽然音频采样率和视频帧率是相似的,但在每一个中保证可用性的通常的最低数字是非常不同的。对于视频来说,为了保证运动的准确描述,每秒至少需要24帧;少于这个数字,运动可能会显得不流畅,连续不间断运动的错觉也无法保持。这一点在帧与帧之间发生的运动越多时尤其适用。此外,每秒1或2帧的视频可能会有 “瞬间 “事件,保证在帧之间被错过。

对于音频来说,要明确地表示英语语音,每秒的最小采样数是8000赫兹。由于各种原因,使用低于这个数字的采样率会导致语音无法被理解,其中一个原因是相似的话语将无法相互区分。较低的采样率会混淆音素或语言中的声音,这些声音具有显着的高频能量;例如,在5000赫兹下,很难将/s/与/sh/或/f/区分开来。

既然我们提到了视频帧,另一个值得详细说明的术语是音频帧。虽然音频样本和音频帧都是以赫兹为单位,但它们并不是一回事。一个音频帧是来自一个或多个音频通道的一个时间实例的音频样本组。

最常见的采样率值是前面提到的8kHz(最常见于电话通信)、44.1kHz(最常见于音乐CD)和48kHz(最常见于电影的音轨)。较低的采样率意味着每秒钟的采样数较少,这反过来又意味着较少的音频数据,因为有较少的采样点来表示音频的数量。采样率的选择取决于需要采集哪些声学伪影。一些声学人工制品如语音语调需要的采样率比声学人工制品如音乐CD中的音乐曲调要低。值得注意的是,更高的采样率需要更多的存储空间和处理能力来处理,尽管这在过去数字存储和处理能力是首要考虑的情况下,现在可能不是那么大的问题。

(2) 采样深度/采样精度/采样大小

除了采样率,也就是我们有多少个音频的数据点,还有采样深度。以每个样本的比特为单位,样本深度(也称为样本精度或样本大小)是音频文件或音频流的第二个重要属性,它代表了每个样本的细节水平,或 “质量”。正如我们上面提到的,每个音频样本只是一个数字,虽然有很多数字有助于表示音频,但你也需要每个单独数字的范围或 “质量 “足够大,以准确表示每个样本或数据点。“质量 “是什么意思?对于一个音频样本来说,它只是意味着该音频样本可以代表更高的振幅范围。8比特的采样深度意味着我们有2^8=256个不同的振幅,而16比特的采样深度意味着我们有2^16=65,536个不同的振幅,以此类推,采样深度更高。电话音频最常见的采样深度是16比特和32比特。在数字录音中,有越多不同的振幅,数字录音听起来就越接近原声事件。

同样,这也类似于我们可能听到的关于图像质量的8位或16位数字。对于图像或视频,图像或视频帧中的每个像素也有一定数量的比特来表示颜色。像素中的比特深度越高,产生的像素颜色就越准确,因为像素有更多的比特来 “描述 “屏幕上要表现的颜色,而且像素或图像总体上看起来更符合人们在现实生活中的样子。从技术上讲,一个像素的比特深度表明该像素可以代表多少种不同的颜色。如果你允许R、G和B中的每一个用8位数字表示,那么每个像素就用3 x 8 = 24位表示。这意味着有2^24~1700万种不同的颜色可以由该像素表示。

(3) 比特率 =(每秒的样本数)x(每个样本的比特数)

将采样率和采样深度联系在一起的是比特率,它是两者的简单乘积。由于采样率是以每秒的样本数来衡量的,而采样深度是以每个样本的比特数来衡量的,因此它是以(每秒的样本数)x(每个样本的比特数)=每秒比特数来衡量的,缩写为bps或kbps。值得注意的是,由于采样深度和比特率是相关的,它们经常被交换使用,但也是错误的。

音频中的比特率因应用而异。要求高音频质量的应用,如音乐,通常有一个更高的比特率,产生更高的质量,或 “更清晰 “的音频。电话音频,包括呼叫中心的音频,不需要高比特率,因此普通电话的比特率通常比音乐CD的比特率低得多。无论是采样率还是比特率,较低的数值可能听起来更糟糕,但同样,根据应用,较低的数值可以节省存储空间和/或处理能力。

总而言之,当涉及到音频时,压缩到底意味着什么?压缩的音频格式,如AAC或MP3,其比特率比采样率和采样深度的真正乘积小一些。这些格式是通过 “外科手术 “从比特流中去除信息来实现的,这意味着在动态情况下那些由于生物原因人耳听不到的频率或振幅不会被存储,从而导致整体文件大小变小。

ffmpeg音频处理-截取、查看、修改采样率

截取音频:

ffmpeg -i input.wav -ss 00:00:05 -t 00:00:10 output.wav

-ss为开始时间 -t为持续时间

查看音频格式:

ffprobe input.wav

修改音频文件采样率:

ffmpeg -i input.wav -ar 16000 output.wav

多通道变单通道

ffmpeg -i input.wav -ac 1 output.wav

转换格式

ffmpeg -i input.mp3 outpit.wav

提取一个通道并重采样

ffmpeg -i input.wav -ac 1 -ar 16000 output.wav

修改采样精度(位数)

ffmpeg -y -i input.wav -acodec pcm_f32le -ac 1 -ar 16000 -vn output.wav

转换音频格式

ffmpeg -i input.flac output.wav

EnCodec: High Fidelity Neural Audio Compression

GitHub:https://github.com/facebookresearch/encodec

Paper:https://arxiv.org/abs/2210.13438

高保真神经网络音频编码器:

本文介绍了meta推出的音频AI Codec,其整体风格深受Google的SoundStream的影响。在其影响下改进了原有的鉴别器,引入语言模型进一步降低码率,并提出了一种提升稳定性的训练策略。

  • 与之前的AI Codec的动机相同,本文同样希望借助深度学习设计一款端到端多码率立体声音频编码器,实现对语音和音乐的低码率压缩并高质量还原。
  • 神经网络天然的抽象特征提取能力使其具有相比传统编码器更强的信号表征压缩能力,低码率的问题相对并不困难;
  • 难点主要有两点:1. 音频的动态范围过大;2. 模型效率问题(计算复杂度和参数量)

本文贡献:

  • 为解决音频动态范围过大的问题,使用庞大多样的训练集以及用鉴别器作为感知损失(这点似乎相比SoundStream)也并未见有什么突破;
  • 限制在单核CPU上实时运行,并采用残差矢量量化(Residual Vector Quantization, RVQ)提高编码效率;
  • 提出了语言模型进一步降低码率;
  • 鉴别器采用多分辨率复数谱STFT鉴别器;
  • 提出了一种balancer以保证GAN训练的稳定性

模型采用的基于GAN的模型,生成器采用时域编码器-量化器-解码器结构,鉴别器采用多分辨率的STFT鉴别器。

编解码器:编解码器采用SEANET,编码器由一层一维卷积对时域波形进行特征提取后经过B个用于降采样的残差单元(即convolurion blocks),而后加入了两层LSTM用于序列建模,最后经过一层卷积得到音频的潜在表征。解码器则是编码器的镜像,其中残差单元的卷积被替换为反卷积用于上采样。根据文中采用的下采样因子(通过卷积的stride实现){2,4,5,8},其编码器将音频下采样320倍(2x4x5x8=320),即传输的一帧中压缩了320倍采样点,因此在采样率为24kHz时1s的音频经编码器输出的时间维数为24000/320=75,48kHz时为48000/320=150。通过卷积的Padding和调整Nomalization去设置模型是否流式。

量化器量化器采用残差矢量量化RVQ,关于RVQ的详细介绍参看[1]和[2]。每个码书包含1024个向量(entries),对于采样率为24kHz的音频,最多使用32个码书,即最大码率为32xlog_2(1024)/13.3=24kbps。为了支持多码率,训练过程中码书数量被设置为{2,4,8,16,32},分别对应1.5kbps,3kbps,6kbps,12kbps,24kbps;且每个码率在训练时所使用的鉴别器是不同的。

语言模型和熵编码:此部分可选,使用Transormer语音模型对RVQ得到的索引映射到新隐藏空间的概率分布,对对应概率密度函数的累积分布函数进行Range Coder熵编码,从而进一步降低码率。

鉴别器:短时傅立叶变换(STFT)。采用多分辨率复数STFT鉴别器,而非TTS中常见的多分辨率Mel谱鉴别器,也没加Multiple-period 鉴别器MPD(消融实验显示多分辨率复数STFT鉴别器性能更优,额外引入MPD有少量性能提升,但考虑训练时长舍弃)。每个分辨率的鉴别器有二维卷积组成,结构如图所示(注意:其中正文和图中的卷积核尺寸不一致,3×8 v.s. 3×9)。

鉴别器采用hinge loss训练,为保证生成器和鉴别器训练平衡稳定,鉴别器以2/3的概率更新其参数

生成器的损失函数:包括重构损失、感知损失(实为对抗损失)以及RVQ的commitment loss三部分,重构损失包括时域和频域两部分,时域损失是波形的L1损失,,频域损失是多时间尺度的Mel谱损失,对抗损失采用hinge loss和特征匹配损失。commitment loss用于使VQ选择的向量满足量化后的变量与未量化的变量间最相近,采用欧式距离度量

数据增广策略:多数据源混合;加混响;音量标准化并随机化增益-10~6 dB;无clip

Demo界面:

1、 https://github.com/facebookresearch/encodec

2、https://ai.honu.io/papers/encodec/samples.html

torchaudio

官网:https://pytorch.org/audio/stable/torchaudio.html

Torchaudio is a library for audio and signal processing with PyTorch. It provides I/O, signal and data processing functions, datasets, model implementations and application components.

读取音频:

使用 torchaudio.load 加载音频数据。torchaudio.load 支持类路径对象和类文件对象。返回值是波形(tensor)和采样率(int)的元组。默认情况下,生成的 tensor 对象的类型为 torch.float32,其值在[−1.0,1.0][−1.0,1.0]内标准化。
waveform, sr = torchaudio.load(filepath, frame_offset=0 , num_frames=-1, normalize=True, channels_first=True)
参数:

filepath (str): 原始音频文件路径;
frame_offset (int): 在此之后开始读取,默认为0,以帧为单位;
num_frames (int): 读取的最大帧数。默认是-1,则表示从frame_offset直到末尾。如果给定文件中没有足够的帧,这个函数可能会返回实际剩余的帧数。
normalize (bool): 当为True时,该函数总是返回float32,并且所有的值被归一化到[-1,1]。如果输入文件是wav,且是整形,若为False时,则会输出int类型。需要注意的是,该参数仅对wav类型的文件起作用, 默认是True;
channels_first (bool)—当为True时,返回的Tensor的维度是[channel, time]。否则,维数为[time, channel], 默认是True。
返回:

waveform (torch.Tensor): 如果输入文件是int类型的wav,且normalization为False,则waveform的数据就为int类型的,否则是float32;如果channel_first=True,则waveform.shape=[channel, time]。
sr (int): 采样率
重采样
waveform = torchaudio.transforms.Resample(orig_freq=16000, new_freq=16000)(waveform)
参数:

orig_freq (int, optional): 原始采样率,默认:16000;
new_freq (int, optional): 转换后的采样率,默认:16000;
resampling_method (str, optional) – 重采样方法,默认: ‘sinc_interpolation’;
waveform (torch.Tensor): 输入音频维度可以是[channel,time],也可以是[time, channel];
返回:

waveform (torch.Tensor): 输出音频维度和输入音频相同,但由于重采样了,time的数值会不同;
保存音频
torchaudio.save(filepath, src, sample_rate, channels_first)
参数:

firepath (str or pathlib.Path): 保存路径;
src (torch.Tensor): 音频数据,必须是二维的;(注:需要转到cpu下的tensor)
sample_rate(int): 采样率;
channels_first (bool): If True, 维度必须是[channel, time],否则是[time, channel]。

The NSynth Dataset

A large-scale and high-quality dataset of annotated musical notes.( 一个大规模、高质量的注释音符数据集。)

下载地址:https://magenta.tensorflow.org/datasets/nsynth#files

Motivation

Recent breakthroughs in generative modeling of images have been predicated on the availability of high-quality and large-scale datasebts such as MNIST, CIFAR and ImageNet. We recognized the need for an audio dataset that was as approachable as those in the image domain.

Audio signals found in the wild contain multi-scale dependencies that prove particularly difficult to model, leading many previous efforts at data-driven audio synthesis to focus on more constrained domains such as texture synthesis or training small parametric models.

We encourage the broader community to use NSynth as a benchmark and entry point into audio machine learning. We also view NSynth as a building block for future datasets and envision a high-quality multi-note dataset for tasks like generation and transcription that involve learning complex language-like dependencies.

Description

NSynth is an audio dataset containing 305,979 musical notes, each with a unique pitch, timbre, and envelope. For 1,006 instruments from commercial sample libraries, we generated four second, monophonic 16kHz audio snippets, referred to as notes, by ranging over every pitch of a standard MIDI pian o (21-108) as well as five different velocities (25, 50, 75, 100, 127). The note was held for the first three seconds and allowed to decay for the final second.

Some instruments are not capable of producing all 88 pitches in this range, resulting in an average of 65.4 pitches per instrument. Furthermore, the commercial sample packs occasionally contain duplicate sounds across multiple velocities, leaving an average of 4.75 unique velocities per pitch.

We also annotated each of the notes with three additional pieces of information based on a combination of human evaluation and heuristic algorithms:

  • Source: The method of sound production for the note’s instrument. This can be one of acoustic or electronic for instruments that were recorded from acoustic or electronic instruments, respectively, or synthetic for synthesized instruments. See their frequencies below.
  • Family: The high-level family of which the note’s instrument is a member. Each instrument is a member of exactly one family. See the complete list and their frequencies below.
  • Qualities: Sonic qualities of the note. See the quality descriptions and their co-occurrences below. Each note is annotated with zero or more qualities.

Format

Files

The NSynth dataset can be download in two formats:

The full dataset is split into three sets:

  • Train [tfrecord | json/wav]: A training set with 289,205 examples. Instruments do not overlap with valid or test.
  • Valid [tfrecord | json/wav]: A validation set with 12,678 examples. Instruments do not overlap with train.
  • Test [tfrecord | json/wav]: A test set with 4,096 examples. Instruments do not overlap with train.

Below we detail how the note features are encoded in the Example protocol buffers and JSON files.

Example Features

Each Example contains the following features.

FeatureTypeDescription
noteint64A unique integer identifier for the note.
note_strbytesA unique string identifier for the note in the format <instrument_str>-<pitch>-<velocity>.
instrumentint64A unique, sequential identifier for the instrument the note was synthesized from.
instrument_strbytesA unique string identifier for the instrument this note was synthesized from in the format <instrument_family_str>-<instrument_production_str>-<instrument_name>.
pitchint64The 0-based MIDI pitch in the range [0, 127].
velocityint64The 0-based MIDI velocity in the range [0, 127].
sample_rateint64The samples per second for the audio feature.
audio*[float]A list of audio samples represented as floating point values in the range [-1,1].
qualities[int64]A binary vector representing which sonic qualities are present in this note.
qualities_str[bytes]A list IDs of which qualities are present in this note selected from the sonic qualities list.
instrument_familyint64The index of the instrument family this instrument is a member of.
instrument_family_strbytesThe ID of the instrument family this instrument is a member of.
instrument_sourceint64The index of the sonic source for this instrument.
instrument_source_strbytesThe ID of the sonic source for this instrument.

Note: the “audio” feature is ommited from the JSON-encoded examples since the audio data is stored separately in WAV files keyed by the “note_str”.