.NET Framework 早期版本對中文語音合成(TTS)支援有限。透過安裝 Microsoft Speech SDK 5.1 (SAPI 5.1) 及對應語言包,可在 C# 中調用 COM 元件 SpeechLib 實現高品質中英混合朗讀。本文採用單例模式封裝核心類別,支援:語音切換(中/英)、音量/語速調節、異步播放、暫停/繼續/停止、中英混合文本智能分段朗讀。
SpeechLib 互操作組件)using SpeechLib;
using System;
using SpeechLib;
public class SpeechSynthesizer
{
private static SpeechSynthesizer _instance;
private SpVoiceClass _voice;
private SpeechSynthesizer() { BuildVoice(); }
public static SpeechSynthesizer Instance {
get {
if (_instance == null) _instance = new SpeechSynthesizer();
return _instance;
}
}
private void BuildVoice() {
if (_voice == null) _voice = new SpVoiceClass();
}
// 語音選擇:GetVoices() 返回 Token 列表,索引 0 通常為中文,1+ 為英文口音
private void SetChineseVoice() {
_voice.Voice = _voice.GetVoices("", "").Item(0);
}
private void SetEnglishVoice() {
_voice.Voice = _voice.GetVoices("", "").Item(1);
}
// 核心發聲方法(異步)
private void Speak(string text) {
try {
_voice.Speak(text, SpeechVoiceSpeakFlags.SVSFlagsAsync);
}
catch (Exception ex) {
throw new Exception("語音播放失敗: " + ex.Message);
}
}
// 中文朗讀
public void SpeakChinese(string text) {
SetChineseVoice();
Speak(text);
}
// 英文朗讀
public void SpeakEnglish(string text) {
SetEnglishVoice();
Speak(text);
}
// 智能分段:依字符 Unicode 範圍判斷中英,分段呼叫對應語音
public void SpeakMixed(string text) {
if (string.IsNullOrEmpty(text)) return;
int chStart = 0, enStart = 0;
bool inChinese = true;
for (int i = 0; i < text.Length; i++) {
char c = text[i];
bool isAsciiLetter = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
if (inChinese) {
if (isAsciiLetter) { // 切換到英文
SpeakChinese(text.Substring(chStart, i - chStart));
enStart = i;
inChinese = false;
}
} else { // 在英文段
if (!isAsciiLetter) { // 切換回中文
SpeakEnglish(text.Substring(enStart, i - enStart));
chStart = i;
inChinese = true;
}
}
}
// 處理尾段
if (inChinese)
SpeakChinese(text.Substring(chStart));
else
SpeakEnglish(text.Substring(enStart));
}
// 音量 (0-100)
public int Volume {
get => _voice.Volume;
set => _voice.Volume = (ushort)Math.Max(0, Math.Min(100, value));
}
// 語速 (-10 到 10)
public int Rate {
get => _voice.Rate;
set => _voice.Rate = Math.Max(-10, Math.Min(10, value));
}
// 控制方法
public void Stop() {
_voice.Speak("", SpeechVoiceSpeakFlags.SVSFPurgeBeforeSpeak);
}
public void Pause() => _voice.Pause();
public void Resume() => _voice.Resume();
}
class Program {
static void Main() {
var tts = SpeechSynthesizer.Instance;
tts.Volume = 80;
tts.Rate = 0;
// 純中文
tts.SpeakChinese("歡迎使用語音合成系統");
// 純英文
tts.SpeakEnglish("Welcome to the speech synthesis system");
// 中英混合
tts.SpeakMixed("你好 World,這是一個 Test 範例");
Console.WriteLine("按任意鍵停止...");
Console.ReadKey();
tts.Stop();
}
}
SpVoiceClass 建立成本高、資源佔用大,全程複用單一實例Speak 立即返回,不阻塞呼叫執行緒(UI 應用關鍵)GetVoices("", "") 返回所有已安裝語音 Token,Item(0) 通常為系統預設中文語音(如 Microsoft Simplified Chinese),Item(1...n) 為英文口音(Microsoft Sam, Mike, Mary 等)CharUnicodeInfo.GetUnicodeCategory 精確識別 CJK 統一表意文字SVSFPurgeBeforeSpeak 清空隊列並立即停止| 問題 | 原因 | 解決 |
|---|---|---|
| 無聲音/例外 | 未安裝 SDK 或語言包 | 重新安裝 Speech SDK 5.1 + Language Pack |
| 中文唸成英文 | Voice Token 選錯 | 列舉 GetVoices 列印 Description 確認索引 |
| 異步播放重疊 | 連續呼叫 Speak 且未停止 | 需求疊加用隊列管理,或呼叫 Stop 後再 Speak |
| 64 位元專案編譯失敗 | SpeechLib 為 32 位元 COM | 專案屬性 → Build → 勾選 "Prefer 32-bit" 或目標平台 x86 |
Speak 接受 SSML 標記,可控制停頓、音調、重音SpSharedRecoContext 實現中文語音輸入System.Speech.Synthesis (Windows) 或第三方 Azure Cognitive Services Speech SDK、eSpeak-NG、Festival透過 SAPI 5.1 COM 互操作,C# 可輕鬆獲得企業級語音合成能力。單例封裝 + 異步播放 + 智能中英分段,構成實用 TTS 元件的核心。理解 COM 物件生命週期、執行緒模型、語音 Token 管理,是避坑關鍵。下篇將挑戰更複雜的中文語音辨識,敬請期待。