前篇文章用 Balabolka 搞定自製英文單字朗讀 MP3,但老讀者們都猜到接下來會發生什麼事... 是的,C# 整合 SAPI 讓電腦講話的練習來了!
原本以為要裝什麼 SDK 或套件,沒想到 .NET 已內建,專案只需參照 System.Speech 就好。
開始前先看一下你的 Windows 裝了哪些語音以及其支援語系:
static void ListInstalledVoices()
{
var voice = new System.Speech.Synthesis.SpeechSynthesizer();
voice.GetInstalledVoices()
.ToList().ForEach((v) =>
{
Console.WriteLine(
v.VoiceInfo.Name + " " +
v.VoiceInfo.Culture.DisplayName);
});
Console.Read();
}
在我的 Windows 10 繁體中文專業版執行結果如下:
Microsoft Hanhan Desktop 中文 (繁體,台灣)
Microsoft Zira Desktop 英文 (美國)
Microsoft Tracy Desktop 中文 (繁體,香港特別行政區)
Microsoft David Desktop 英文 (美國)
依據文件,Windows 10 2018 4 月更新有增加其他語音選項,國語部分加入了 Zhiwei(志偉?) 跟 Yating (雅婷?)。
來個最基本的應用示範,其中包含前篇文章提到的某段文字用不同語音朗讀。要加入 <voice> 標籤有兩種做法,第一種是自己組 SSML再呼叫 SpeakSsml(),但得自己處理 XML namespace 比較繁瑣,另一種做法是使用 PromptBuilder,透過 AppendText() 加入純文字,用 AppendSsmlMarkup() 加入包含 <voice> 等標籤的 SSML 片段,最後將 PromptBuilder 當成參數交給 Speak() 執行,比拼湊 XML 省事也易讀一些。
static void SayHi()
{
var voice = new System.Speech.Synthesis.SpeechSynthesizer();
//美語 男聲
voice.SelectVoice("Microsoft David Desktop");
voice.Speak("Hi there, I am darkthread.");
//美語 女聲
voice.SelectVoice("Microsoft Zira Desktop");
voice.Speak("Hi there, I am darkthread.");
//國語
var pb = new PromptBuilder();
pb.StartVoice("Microsoft Hanhan Desktop");
pb.AppendText("大家好,我是黑暗執行緒");
//https://msdn.microsoft.com/zh-tw/library/hh378418(v=office.14).aspx
pb.AppendSsmlMarkup("<voice name=\"Microsoft David Desktop\">darkthread</voice>");
pb.EndVoice();
voice.Speak(pb);
//廣東話
voice.SelectVoice("Microsoft Tracy Desktop");
voice.Speak("大家好,我是黑暗執行緒");
}
PromptBuilder除了加入 SSML 標籤,還有其他好用的控制選項,例如:
- AppendAudio()
插入外部聲音檔(WMA) - AppendBreak()
插入停頓 - StartParagraph()/EndParagraph()/StartSentence()/EndSentence()
形成段落跟句子,模擬自然說話的停頓效果,使語音更逼真 - StartVoice()/EndVoice()
指定語音名稱,或指定語系、性別、年齡,由 SAPI 挑選適用的語音
除了前面介紹過的 <voice>,SSML 還有一些有用標籤,可做到精細調控:
(參考:Speech Synthesis Markup Language Reference)
- emphasis
強調,加重語氣 - p、s
標註段落跟句子,讓說話效果更自然逼真 - phoneme
可使用特殊音標指定特定字語的發音,例如指定 Zhou 要唸成「趙」
His name is Mike <phoneme alphabet=""x-microsoft-ups"" ph=""JH AU"">Zhou</phoneme>
參考:發音標示符號表 Phonetic Alphabet Reference - prosody
指定範圍內文字的音調(pitch)、速度(rate)、音量(volume)
Your order for <prosody pitch=""+1st"" rate=""-10%"" volume=""50""> eight books </prosody> - voice
指定範圍內文字使用不同語音
想將語音輸出轉成 WAV 檔也很簡單,在 voice.Speak() 之前先加上 voice.SetOutputToWaveFile("x:\\filename.wav"),一行搞定! 如果要轉成 MP3,則需要整合第三方程式庫或直接用 lame.exe 將 .wav 檔轉 .mp3,lame.exe x:\filename.mav x:\filename.mp3,一樣一行搞定最省事。
又到了久違的呼口號時間: