Coding4Fun–Microsoft Speach API 筆記

前篇文章用 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,一樣一行搞定最省事。

又到了久違的呼口號時間:

SAPI 真酷! .NET 好威呀!

歡迎推文分享:
Published 06 May 2018 10:50 PM 由 Jeffrey
Filed under:
Views: 2,977



意見

# not said on 07 May, 2018 06:18 AM

您好,我想要把產生的語音檔放在iis上,讓使用者下載或是播放,不過把您的範例code放在後端程式呼叫時總是會出現 "非同步作業目前無法開始。" 的錯誤訊息

i.imgur.com/TitLzay.png

我想如果要把檔案存成wav後才要顯示網頁,應該是同步程式比較符合我的需求才對,可是連第一步GetInstalledVoices想看裝了哪些語音都過不去...

可以問問要如何在網頁的環境執行嗎?

# Jeffrey said on 07 May, 2018 08:18 PM

to not, 可參考Stackoverflow的這則範例,stackoverflow.com/.../288936

# 阿強 said on 07 May, 2018 10:05 PM

網頁版這個會不會比較方便,我是沒用過。

https://responsivevoice.org/

# Jeffrey said on 08 May, 2018 12:52 AM

to 阿強,挺方便的。經實測「 948794 狂」,Chinese Female 語音的效果跟卡提諾狂新聞旁白一木一樣啊 XD 感謝分享

# Brad said on 11 June, 2018 06:46 PM

請問有甚麼辦法可以選到Yating 和Zhiwei呢?

因為我已經安裝這兩個聲音,Edge和朗讀程式都可以使用

但是GetInstalledVoices沒有出現,

SelectVoice也會失敗

# Jeffrey said on 13 June, 2018 12:50 AM

to Brad, Edge跟朗讀程式可用但.NET程式找不到,會跟x64/x86有關嗎? 切換.NET平台目標試看看是否結果不同。

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<May 2018>
SunMonTueWedThuFriSat
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789
 
RSS
創用 CC 授權條款
【廣告】
twMVC

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication