2019 年 6 月
第 34 卷,第 6 期
[語音]
.NET 中的文字轉換語音合成
藉由Ilia Smirnov |2019 年 6 月
我常飛抵芬蘭連我媽媽。每次平面會落在 Vantaa 機場中,我驚訝的機場的幾家乘客標頭結束。大部分為 off,連接到跨越所有中部和加拿大東部歐洲的目的地的航班。它的難怪,然後,當平面開始其下降時,沒有相關連接航班公告的。「 如果您的目的地是塔林,閘道 123,尋找 「"聖堡至航班 XYZ,前往 [閘道 234,"等等。當然,飛行應答不通常會說數十個語言,讓它們使用英文,不是大部分的乘客的原生語言。考慮公開金鑰的宣告 (PA) 的品質上 airliners,再加上引擎雜訊,哭泣嬰兒和其他於,系統如何可以任何資訊會有效地傳達?
每個基座,配備耳機。許多,不是全部,內部的遠距平面今天有個別的畫面 (和本機的項目必須至少要有不同的音訊聲道)。如果乘客可能選擇公告的語言和上架的電腦系統允許飛行語音應答,若要建立和傳送動態 (亦即不預先錄製) 語音訊息?這裡的主要挑戰是訊息的動態本質。它很容易預先記錄安全性的指示,再根據等選項,因為它們很少更新。但是,我們要即時建立訊息解譯為常值。
所幸還有成熟的技術,可協助: 文字轉換語音合成 (text-to-speech,TTS)。我們很少注意到這類系統,但它們是非常普遍: 公用宣布,話務中心、 導航裝置、 遊戲、 智慧型裝置和其他應用程式中的提示,則所有的範例,其中預先錄製的提示不足,或是否使用數位化的波形因為記憶體限制 (TTS 引擎所讀取的文字是遠小於儲存數位化的波形) 禁止。
電腦為基礎的語音合成是不太新。電信公司投資 TTS 來克服這些限制的預先錄製的訊息和軍事單位地研究人員已實驗語音提示和警示,以簡化複雜的控制項介面。可攜式合成同樣所開發的行動不便人士使用。針對這類裝置為何 25 年多前能夠了解,聆聽 」 持續交談"1994年粉紅色 Floyd 唱片 「 除法鈴鐺 」 上的追蹤該處 Stephen Hawking 指示他的著名列:「 我們只需要是要確定我們持續交談 」。
TTS Api 以及其 「 反之亦然 」 通常是 — 語音辨識。當您需要有效的人機互動的時這項探索著重於特別語音合成。我將使用 Microsoft.NET TTS API 來建置原型的 airliner PA 系統。我也將討論追根究底去了解 TTS 」 單位的選擇 」 方法的基本概念。我將逐步的桌面應用程式建構,而原則適用於直接與雲端式解決方案。
回復語音系統
之前建立原型進行中的通知系統,讓我們來探索一個簡單的程式與 API。啟動 Visual Studio 並建立主控台應用程式。將參考加入 System.Speech 和實作中的方法**[圖 1**。
[圖 1 System.Speech.Synthesis 方法
using System.Speech.Synthesis;
namespace KeepTalking
{
class Program
{
static void Main(string[] args)
{
var synthesizer = new SpeechSynthesizer();
synthesizer.SetOutputToDefaultAudioDevice();
synthesizer.Speak("All we need to do is to make sure we keep talking");
}
}
}
現在請編譯並執行。只需要幾行程式碼,且您已複寫著名的 Hawking 片語。
當您正在輸入此程式碼時,IntelliSense 就會開啟視窗與所有公用方法和 SpeechSynthesizer 類別的屬性。如果您錯過了,使用 「 控制項空間 」 或 「 點 」 鍵盤快速鍵 (或看看bit.ly/2PCWpat)。有趣的是這裡?
首先,您可以設定不同的輸出目標。它可以是音訊檔案或資料流或甚至是 null。第二,您有 (如同上例) 同步和非同步的輸出。您也可以調整磁碟區和的語音速率、 暫停和繼續,並接收事件。您也可以選取語音。這項功能很重要,因為您將使用它來產生輸出,以不同的語言。但何種語音可用嗎?讓我們找出使用中的程式碼**[圖 2**。
[圖 2 語音資訊的程式碼
using System;
using System.Speech.Synthesis;
namespace KeepTalking
{
class Program
{
static void Main(string[] args)
{
var synthesizer = new SpeechSynthesizer();
foreach (var voice in synthesizer.GetInstalledVoices())
{
var info = voice.VoiceInfo;
Console.WriteLine($"Id: {info.Id} | Name: {info.Name} |
Age: {info.Age} | Gender: {info.Gender} | Culture: {info.Culture}");
}
Console.ReadKey();
}
}
}
在使用 [Windows 10 家用電腦上所產生的輸出**[圖 2**是:
Id: TTS_MS_EN-US_DAVID_11.0 | Name: Microsoft David Desktop |
Age: Adult | Gender: Male | Culture: en-US
Id: TTS_MS_EN-US_ZIRA_11.0 | Name: Microsoft Zira Desktop |
Age: Adult | Gender: Female | Culture: en-US
有可用的只有兩個英文版的語音,和其他語言呢?每個語音都需要部分磁碟空間,因此預設不會安裝它們。若要加入它們,請瀏覽到 [開始 |設定 |時間與語言 |區域和語言,並且按一下 [新增語言,務必要選取選用功能中的語音。雖然 Windows 支援 100 個以上的語言,只有約 50 支援 TTS。您可以檢閱在支援的語言的清單bit.ly/2UNNvba。
之後重新啟動電腦,應該使用新的語言套件。在本例中,新增俄文之後, 我的新安裝的語音:
Id: TTS_MS_RU-RU_IRINA_11.0 | Name: Microsoft Irina Desktop |
Age: Adult | Gender: Female | Culture: ru-RU
現在您可以返回第一個程式,並新增下列兩行,而不是合成。將呼叫:
synthesizer.SelectVoice("Microsoft Irina Desktop");
synthesizer.Speak("Всё, что нам нужно сделать, это продолжать говорить");
如果您想要切換語言,您可以插入 SelectVoice 呼叫一點。但更好的方法是將某些結構加入至語音。為此,我們使用 PromptBuilder 類別,如中所示**[圖 3**。
圖 3 PromptBuilder 類別
using System.Globalization;
using System.Speech.Synthesis;
namespace KeepTalking
{
class Program
{
static void Main(string[] args)
{
var synthesizer = new SpeechSynthesizer();
synthesizer.SetOutputToDefaultAudioDevice();
var builder = new PromptBuilder();
builder.StartVoice(new CultureInfo("en-US"));
builder.AppendText("All we need to do is to keep talking.");
builder.EndVoice();
builder.StartVoice(new CultureInfo("ru-RU"));
builder.AppendText("Всё, что нам нужно сделать, это продолжать говорить");
builder.EndVoice();
synthesizer.Speak(builder);
}
}
}
請注意,您必須呼叫 EndVoice,否則您會收到執行階段錯誤。此外,我使用 CultureInfo 作為指定語言的另一種方式。PromptBuilder 有很多有用的方法,但我想要強調您 AppendTextWithHint。嘗試此程式碼:
var builder = new PromptBuilder();
builder.AppendTextWithHint("3rd", SayAs.NumberOrdinal);
builder.AppendBreak();
builder.AppendTextWithHint("3rd", SayAs.NumberCardinal);
synthesizer.Speak(builder);
結構,輸入,並指定如何讀取它的另一種方式是使用語音合成標記語言 (SSML),也就是國際的語音瀏覽器工作小組所開發的跨平台建議 (w3.org/TR/speech-synthesis).Microsoft TTS 引擎提供完整支援 SSML。這是如何使用它:
string phrase = @"<speak version=""1.0""
http://www.w3.org/2001/10/synthesis""
xml:lang=""en-US"">";
phrase += @"<say-as interpret-as=""ordinal"">3rd</say-as>";
phrase += @"<break time=""1s""/>";
phrase += @"<say-as interpret-as=""cardinal"">3rd</say-as>";
phrase += @"</speak>";
synthesizer.SpeakSsml(phrase);
請注意它會採用不同的呼叫 SpeechSynthesizer 類別上。
現在您已準備好可原型。此時會建立新的 Windows Presentation Foundation (WPF) 專案。在兩個不同的語言中加入表單和幾個提示的按鈕。然後加入 click 處理常式,在 XAML 中所示**[圖 4**。
[圖 4 的 XAML 程式碼
using System.Collections.Generic;
using System.Globalization;
using System.Speech.Synthesis;
using System.Windows;
namespace GuiTTS
{
public partial class MainWindow : Window
{
private const string en = "en-US";
private const string ru = "ru-RU";
private readonly IDictionary<string, string> _messagesByCulture =
new Dictionary<string, string>();
public MainWindow()
{
InitializeComponent();
PopulateMessages();
}
private void PromptInEnglish(object sender, RoutedEventArgs e)
{
DoPrompt(en);
}
private void PromptInRussian(object sender, RoutedEventArgs e)
{
DoPrompt(ru);
}
private void DoPrompt(string culture)
{
var synthesizer = new SpeechSynthesizer();
synthesizer.SetOutputToDefaultAudioDevice();
var builder = new PromptBuilder();
builder.StartVoice(new CultureInfo(culture));
builder.AppendText(_messagesByCulture[culture]);
builder.EndVoice();
synthesizer.Speak(builder);
}
private void PopulateMessages()
{
_messagesByCulture[en] = "For the connection flight 123 to
Saint Petersburg, please, proceed to gate A1";
_messagesByCulture[ru] =
"Для пересадки на рейс 123 в Санкт-Петербург, пожалуйста, пройдите к выходу A1";
}
}
}
很明顯地,這只是小型的原型。在現實生活中,PopulateMessages 可能會讀取來自於外部資源。比方說,飛行服務員可以產生訊息的檔案以多種語言使用的應用程式,會呼叫服務,例如 Bing 翻譯 (bing.com/translator)。表單將會更複雜且動態產生根據可用的語言。將會有錯誤處理,依此類推。但重點是要說明的核心功能。
解構元語音
到目前為止,我們也已達到我們的目標與令人驚訝的小型程式碼基底。讓我們看一探究竟,並深入了解如何 TTS 引擎工作的機會。
有許多方法來建構 TTS 的系統。在過去,研究人員嘗試探索一組在其上建置演算法的發音規則。如果您曾經已研究外國語言,您已熟悉像是規則 」 字母 'c','e' 前的 'i','y' 會明顯,因為的 ' 'city',但之前 ',' 'o' 'u' 以 'k' 與 'cat'。 」可惜的是,有這麼多的例外狀況和特殊的情況下,喜歡在連續的文字的發音變更 — 建構一組完整的規則,是很困難。此外,大部分這類系統通常會產生不同的 「 電腦 」 語音 — imagine 初學者說 word-依-字母外國語言中的。
更自然發音語音、 研究已轉移朝上錄製的語音片段的大型資料庫為基礎的系統,這些引擎現在支配市場區隔。通常稱為串連單位選擇 TTS,這些引擎選取語音的範例 (單位) 根據輸入的文字,並將它們串連成片語。通常,引擎會使用兩階段處理密切類似於編譯器:首先,剖析輸入的內部清單或樹狀結構-類似的結構,具有注音錄音和其他中繼資料,並接著合成聲音這個結構為基礎。
因為我們使用自然語言處理,剖析器會比的更為複雜的程式設計語言。因此之外 (尋找句子和單字的界限) 的 token 化,剖析器必須修正錯字、 識別詞性、 分析標點符號,以及解碼縮寫、 縮寫和特殊符號。剖析器的輸出通常由片語或句子分割成描述文字的集合組成該群組和執行中繼資料,例如詞性和發音的壓力,依此類推。
剖析器會負責解決模稜兩可的輸入中。比方說,「 Dr 」 是什麼?。它是 「 醫生 」 與 「 Dr 嗎?。Smith,」 或者 「 磁碟機 」 與 「 Privet 磁碟機嗎? 」 而是 「 Dr."句子,因為它以大寫的字母開頭,並以句號結尾嗎?名詞和動詞,請為 「 專案 」?這很重要了,因為位於不同的音節的壓力。
這些問題不一定容易回答,而且許多 TTS 的系統有不同的剖析器特定的網域: 數字、 日期、 縮寫、 首字母縮略字、 地理名稱、 特殊形式的 Url 等等之類的文字。它們也是特定語言和區域。幸運的是,這類問題已研讀長的時間,我們有開發完整的架構和依賴的程式庫。
下一個步驟產生發音的形式,例如標記音效符號的樹狀目錄 (例如將 [學校] 轉換為"s k 糟糕 l")。這是特殊的簇-音素演算法。西班牙文等語言,可以套用一些相當簡單的規則。但對於其他人,像英文發音完全不同的書寫形式。然後會採用統計的方法,以及針對已知的字組的資料庫。在那之後,會需要額外的後置語彙處理,因為在句子中結合時,可以變更文字的發音所示。
雖然剖析器嘗試從文字中擷取所有可能的資訊時,有一點,因此難以捉摸不解壓縮: 韻律或聲調。時,我們會使用韻律來強調特定的單字,表達情緒,以及指出肯定句子、 命令和問題。但是書寫的文字不一定表示韻律的符號。當然,標點符號會提供一些內容:逗號會表示稍微暫停一段表示一個較長而問號表示引發您聲調到句子的結尾。但如果您看過您的子系睡覺劇本,您就會知道多久這些規則是實際的讀取。
此外,兩個不同的人通常讀取相同的文字以不同的方式 (詢問您的子系是誰在讀取睡覺劇本更好-您或您的配偶)。基於這個原因無法可靠地使用統計方法因為不同的專家將會產生不同的標籤,受監督之學習。這個問題是複雜,儘管大量參考資料、 遠離所要解決。最佳程式設計做法是使用 SSML,有一些標記韻律。
在 [TTS 的類神經網路
統計或機器學習方法年已套用 TTS 處理的所有階段中。比方說,隱藏的 Markov 模型用來建立產生最可能的剖析,剖析器或執行語音範例資料庫的標記方式。決策樹使用,而在單位選取項目或簇-音素的演算法,類神經網路和深度學習問世 TTS 研究 bleeding 邊緣。
我們可以視為波形取樣時間序列的音訊範例。藉由建立的自動迴歸模型,就可以預測下一個範例。如此一來,模型會產生語音種類事件反昇,例如學習對談的模仿音效 baby。如果我們進一步條件此模型對於音訊文稿] 或 [從現有的 TTS 系統前置處理的輸出,我們會取得語音的參數化的模型。模型的輸出會描述用於產生實際的波形 vocoder spectrogram。此程序不會依賴資料庫與記錄的範例,但富有生產力,因為模型有較小的記憶體耗用量,並允許調整參數。
因為模型訓練自然的談話,輸出會保留它所有的特性,包括呼吸學科和聲調 (因此類神經網路可能可以解決韻律問題)。它可能也是要調整的字幅、 建立完全不同的語音和甚至是模擬簽署。
在撰寫本文時,Microsoft 提供的類神經網路 TTS 其預覽版本 (bit.ly/2PAYXWN)。增強的品質,並幾近即時的效能,它會提供四個語音。
語音產生
既然我們已經與中繼資料樹狀結構時,我們會開啟至語音層代。藉由結合 sinusoids 合成訊號嘗試原始 TTS 的系統。另一個有趣的方法所建構微分方程描述人力的關切這個合約為不同的墊片和長度的數個連接管的系統。這類解決方案非常簡潔,但不幸的是聽起來很機械化。因此,如同音樂合成,焦點逐漸向需要顯著的空白字元,但基本上聽起來自然的樣本為基礎的解決方案。
若要建置這類系統,您必須有許多小時的高畫質錄製的專業的動作項目讀取特別建構的文字。此文字會分割成單位、 標示為和儲存到資料庫。語音產生會變成選取適當的單位,並結合在一起的工作。
因為您不由合成語音,您不能大幅調整執行階段中的參數。如果您需要男性和女性聲音,或必須提供地區重音符號 (比方說,蘇格蘭或愛爾蘭文),他們必須個別記錄。必須以涵蓋所有可能的聲音單位,您必須建構的文字。動作項目必須中性的音,才能讓串連更容易閱讀。
分割和標記也是重要的工作。它用來手動完成,花費數週的冗長乏味的工作。幸好,機器學習服務現在正在套用至此。
單位大小可能是 TTS 系統的最重要參數。很明顯地,藉由使用整個句子,我們可以進行的最自然的音效,即使使用正確的韻律,但錄製和儲存的資料量不可能。可以我們將它分割為文字?也許吧,但是多久才會讀取整個字典動作項目嗎?以及資料庫大小限制為何我們面臨嗎?另一方面,我們只是無法錄製字母 —,便只會針對拼字比賽競賽。因此通常為三個字母的兩個群組選取單位。它們不一定音節,如跨距音節框線會的群組在一起黏附好多了。
現在最後一個步驟。有語音單位的資料庫,我們需要處理串連。可惜的是,不論如何中性聲調已在原始記錄中,連接單元仍然需要調整,以避免在磁碟區、 頻率和階段中的跳躍點。做法是使用數位訊號處理 (DSP)。也可用來將某些聲調新增至片語,例如提高或降低產生的語音的判斷提示或問題。
總結
在本文中我將討論.NET API。其他平台提供類似的功能。MacOS NSSpeechSynthesizer Cocoa 中的具有類似的功能,而且大多數的 Linux 散發套件包含 eSpeak 引擎。所有這些 Api 是透過原生程式碼,可存取的因此您必須使用C#或C++或 [Swift。Python 等跨平台生態系統,某些橋接器等 Pyttsx,但它們通常會有某些限制。
雲端廠商,相反地,目標寬的對象,並提供服務的最受歡迎的語言及平台。雖然各廠商間比較功能,支援的 SSML 標記各有不同,因此請查看前選擇解決方案的文件。
Microsoft 認知服務的一部分提供的文字轉換語音服務 (bit.ly/2XWorku)。它不僅可讓您 75 語音 45 國語言,但也可讓您建立您自己的語音。為此,服務必須具有對應的文字記錄的音訊檔案。您可以首先書寫您的文字,然後讓其他人讀取,或使用現有的記錄並且撰寫其文字記錄。之後將這些資料集上傳至 Azure,機器學習演算法會模型為您自己唯一 「 語音 」 字型。 良好的逐步指南,請參閱bit.ly/2VE8th4。
若要存取認知語音服務非常方便的方式是使用語音軟體開發套件 (bit.ly/2DDTh9I)。它支援語音辨識和語音合成,而且是適用於所有主要的桌上型電腦和行動裝置平台與最受歡迎的語言。它有清楚的記載,並在 GitHub 上有許多程式碼範例。
TTS 仍然是極大的說明有特殊需求的人員。例如,請瀏覽 linka.su,以協助使用者使用語音和 musculoskeletal 製劑、 autism,或從筆劃復原那些洋溢智力 paralysis 與程式設計師所建立的網站。了解個人的經驗時所面臨的哪些限制作者建立各種應用程式的人員無法為一般鍵盤上輸入、 可以只能選取一個字母,一次,或只要碰觸平板電腦上的圖片。由於 TTS,他實際上提供語音沒有訂用帳戶的任何人。我想,我們全部都是程式設計人員而言,可能是其他人也很有用。
Ilia Smirnov有 20 年以上的開發上主要的平台,主要是在 Java 和.NET 企業應用程式的經驗。如過去十年來,他有專屬的財務風險模擬中。他會保留三個主要的度數為單位,方式與其他專業人員的認證。
感謝下列 Microsoft 技術專家來檢閱這篇文章:不要小看它們 Zhao (Sheng.Zhao@microsoft.com)
不要小看它們 Zhao 是主體群組軟體工程,以在北京 STCA 語音