音訊課程文件

文字轉語音的預訓練模型

Hugging Face's logo
加入 Hugging Face 社群

並獲得增強的文件體驗

開始使用

文字轉語音的預訓練模型

與 ASR(自動語音識別)和音訊分類任務相比,可用的預訓練模型檢查點明顯較少。在 🤗 Hub 上,你會發現將近 300 個合適的檢查點。在這些預訓練模型中,我們將重點關注 🤗 Transformers 庫中現成的兩種架構——SpeechT5 和 Massive Multilingual Speech (MMS)。在本節中,我們將探討如何在 Transformers 庫中使用這些預訓練模型進行 TTS。

SpeechT5

SpeechT5 是微軟的 Junyi Ao 等人釋出的一個模型,能夠處理一系列語音任務。雖然在本單元中,我們側重於文字轉語音方面,但該模型可以用於語音轉文字任務(自動語音識別或說話人識別),以及語音轉語音任務(例如語音增強或不同聲音之間的轉換)。這得益於模型的設計和預訓練方式。

SpeechT5 的核心是一個常規的 Transformer 編碼器-解碼器模型。與其他 Transformer 一樣,編碼器-解碼器網路使用隱藏表示對序列到序列的轉換進行建模。這個 Transformer 主幹對於 SpeechT5 支援的所有任務都是相同的。

這個 Transformer 輔以六個特定於模態(語音/文字)的 pre-netspost-nets。輸入語音或文字(取決於任務)透過相應的 pre-net 進行預處理,以獲得 Transformer 可以使用的隱藏表示。然後,Transformer 的輸出被傳遞到 post-net,後者將使用它在目標模態中生成輸出。

這就是該架構的樣子(圖片來自原始論文)

SpeechT5 architecture from the original paper

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 文字轉語音架構的樣子

SpeechT5 architecture for TTS

如您所見,輸出是對數梅爾譜圖,而不是最終的波形。如果您還記得,我們在第 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 是一個高度可控的文字轉語音模型,這意味著您可以使用各種設定,我們將在後面看到。

首先,載入模型及其處理器。

處理器在這裡的作用是雙重的

  1. 它用於對輸入文字進行分詞,即將其切成模型可以理解的小塊。
  2. 它儲存說話人嵌入,即可以影響生成的語音預設。
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 一樣,不需要聲碼器,因為波形是直接生成的。

MMS 模型最近才新增到 🤗 Transformers 中,因此您必須從原始碼安裝庫
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 模型,您需要使用 VitsModelVitsTokenizer。這是因為如前所述,用於文字轉語音的 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 上更新

© . This site is unofficial and not affiliated with Hugging Face, Inc.