首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 語音合成與辨識:System.Speech 與 Windows.Media 完整實作

     編輯:關於C#

前言

.NET 提供兩套語音 API:System.Speech (傳統桌面、SAPI 5.x 封裝) 與 Windows.Media.SpeechSynthesis/SpeechRecognition (UWP/WinUI 3、現代語音平台)。本文涵蓋兩套 API 的語音合成 (TTS)、語音辨識 (SR)、中英文混合處理、SSML 標記、離線/線上模式切換。

一、System.Speech (傳統桌面應用)

1.1 語音合成


using System.Speech.Synthesis;

public class SpeechSynthesizerWrapper : IDisposable
{
    private readonly SpeechSynthesizer _synth = new();

    public SpeechSynthesizerWrapper()
    {
        // 列出已安裝語音
        foreach (var voice in _synth.GetInstalledVoices())
        {
            Console.WriteLine($"Voice: {voice.VoiceInfo.Name}, Culture: {voice.VoiceInfo.Culture}, Gender: {voice.VoiceInfo.Gender}");
        }
    }

    public void SetVoice(string cultureName = "zh-TW")
    {
        _synth.SelectVoiceByHints(VoiceGender.NotSet, VoiceAge.NotSet, 0, new System.Globalization.CultureInfo(cultureName));
    }

    public void Speak(string text) => _synth.Speak(text);           // 同步
    public void SpeakAsync(string text) => _synth.SpeakAsync(text); // 非同步

    // SSML 輸出 (支援中文標點、停頓、音調)
    public void SpeakSsml(string ssml)
    {
        var prompt = new PromptBuilder();
        prompt.AppendSsmlMarkup(ssml);
        _synth.Speak(prompt);
    }

    public void Dispose() => _synth.Dispose();
}

// 使用範例
var tts = new SpeechSynthesizerWrapper();
tts.SetVoice("zh-TW"); // 需安裝 Microsoft Tracy (zh-TW) 或 Hanhan (zh-CN)
tts.Speak("你好,歡迎使用 C# 語音合成。");

// SSML 範例
tts.SpeakSsml(@"
    這是  中文測試。
    語速較慢、音調較高。
    English: Hello World.
");

1.2 語音辨識 (共用辨識器 / 進程內辨識器)


using System.Speech.Recognition;

public class SpeechRecognizerWrapper : IDisposable
{
    private readonly SpeechRecognitionEngine _recognizer;

    public SpeechRecognizerWrapper(string culture = "zh-TW")
    {
        _recognizer = new SpeechRecognitionEngine(new System.Globalization.CultureInfo(culture));
        _recognizer.SetInputToDefaultAudioDevice(); // 使用預設麥克風
        
        // 建立文法:指令模式
        var commands = new Choices("開啟", "關閉", "設定", "離開");
        var gb = new GrammarBuilder { Culture = _recognizer.RecognizerInfo.Culture };
        gb.Append(commands);
        var grammar = new Grammar(gb);
        _recognizer.LoadGrammar(grammar);

        // 也可載入系統口述文法 (免費語音輸入)
        // _recognizer.LoadGrammar(new DictationGrammar());

        _recognizer.SpeechRecognized += OnSpeechRecognized;
        _recognizer.RecognizeCompleted += OnRecognizeCompleted;
    }

    public void Start() => _recognizer.RecognizeAsync(RecognizeMode.Multiple);
    public void Stop() => _recognizer.RecognizeAsyncStop();

    private void OnSpeechRecognized(object sender, SpeechRecognizedEventArgs e)
    {
        if (e.Result.Confidence > 0.7f)
        {
            Console.WriteLine($"辨識: {e.Result.Text} (信心度: {e.Result.Confidence:P0})");
            ExecuteCommand(e.Result.Text);
        }
        else
        {
            Console.WriteLine("辨識信心度過低");
        }
    }

    private void ExecuteCommand(string cmd)
    {
        switch (cmd)
        {
            case "開啟": Console.WriteLine("執行開啟..."); break;
            case "關閉": Console.WriteLine("執行關閉..."); break;
        }
    }

    private void OnRecognizeCompleted(object sender, RecognizeCompletedEventArgs e)
    {
        if (!e.Cancelled && e.Error == null)
            Start(); // 重新啟動持續聆聽
    }

    public void Dispose() => _recognizer.Dispose();
}

1.3 中英文混合語音處理策略

System.Speech 單一語音引擎通常只支援單一語系。混合讀法需:

  1. 切換語音引擎:SelectVoiceByHints 切換 zh-TW / en-US
  2. 文本分段:偵測字元範圍 (中文 U+4E00-U+9FFF,英文 A-Za-z)
  3. 分段合成:各段使用對應語音引擎

public class MixedLanguageSpeaker
{
    private readonly SpeechSynthesizer _synth = new();

    public void SpeakMixed(string text)
    {
        var segments = SplitByLanguage(text);
        foreach (var (segment, culture) in segments)
        {
            _synth.SelectVoiceByHints(VoiceGender.NotSet, VoiceAge.NotSet, 0, culture);
            _synth.Speak(segment); // 同步等待上一段結束
        }
    }

    private List<(string Text, CultureInfo Culture)> SplitByLanguage(string text)
    {
        var result = new List<(string, CultureInfo)>();
        var current = new System.Text.StringBuilder();
        CultureInfo currentCulture = null;

        foreach (char c in text)
        {
            var culture = IsChinese(c) ? new CultureInfo("zh-TW") : new CultureInfo("en-US");
            if (currentCulture != culture && current.Length > 0)
            {
                result.Add((current.ToString(), currentCulture));
                current.Clear();
            }
            currentCulture = culture;
            current.Append(c);
        }
        if (current.Length > 0) result.Add((current.ToString(), currentCulture));
        return result;
    }

    private bool IsChinese(char c) => c >= 0x4E00 && c <= 0x9FFF; // 簡易判斷
}

二、Windows.Media.SpeechSynthesis (UWP / WinUI 3 / .NET 6+ Windows App SDK)

2.1 語音合成 (現代 API,支援神經網路語音)


using Windows.Media.SpeechSynthesis;
using Windows.Storage.Streams;

public class ModernSpeechSynthesizer
{
    private readonly SpeechSynthesizer _synth = new();

    public async Task SynthesizeToStreamAsync(string text, string voiceName = null)
    {
        if (!string.IsNullOrEmpty(voiceName))
        {
            var voice = SpeechSynthesizer.AllVoices.FirstOrDefault(v => v.DisplayName.Contains(voiceName));
            if (voice != null) _synth.Voice = voice;
        }
        return await _synth.SynthesizeTextToStreamAsync(text);
    }

    public async Task SpeakAsync(string text)
    {
        using var stream = await SynthesizeToStreamAsync(text);
        var mediaElement = new MediaElement(); // 需 UI 執行緒
        mediaElement.SetSource(stream, stream.ContentType);
        mediaElement.Play();
        await Task.Delay(TimeSpan.FromSeconds(stream.Size / 16000)); // 估算播放時間
    }

    // SSML 支援
    public async Task SynthesizeSsmlToStreamAsync(string ssml)
    {
        return await _synth.SynthesizeSsmlToStreamAsync(ssml);
    }
}

2.2 語音辨識 (Windows.Media.SpeechRecognition)


using Windows.Media.SpeechRecognition;

public class ModernSpeechRecognizer
{
    private readonly SpeechRecognizer _recognizer;

    public ModernSpeechRecognizer(string language = "zh-TW")
    {
        _recognizer = new SpeechRecognizer(new Windows.Globalization.Language(language));
        
        // 限制文法:清單模式
        var listConstraint = new SpeechRecognitionListConstraint(new[] { "開啟", "關閉", "設定" }, "commands");
        _recognizer.Constraints.Add(listConstraint);
        
        // 或主題文法 (網路辨識,需網路)
        // _recognizer.Constraints.Add(new SpeechRecognitionTopicConstraint(SpeechRecognitionScenario.Dictation, "dictation"));

        _recognizer.ContinuousRecognitionSession.ResultGenerated += OnResultGenerated;
    }

    public async Task StartAsync()
    {
        await _recognizer.CompileConstraintsAsync();
        await _recognizer.ContinuousRecognitionSession.StartAsync();
    }

    public async Task StopAsync() => await _recognizer.ContinuousRecognitionSession.StopAsync();

    private void OnResultGenerated(SpeechContinuousRecognitionSession sender, SpeechContinuousRecognitionResultGeneratedEventArgs args)
    {
        if (args.Result.Confidence == SpeechRecognitionConfidence.High || args.Result.Confidence == SpeechRecognitionConfidence.Medium)
        {
            Console.WriteLine($"辨識: {args.Result.Text}");
        }
    }
}

三、Azure Cognitive Services Speech SDK (企業級、雲端神經網路語音)


// NuGet: Microsoft.CognitiveServices.Speech
using Microsoft.CognitiveServices.Speech;
using Microsoft.CognitiveServices.Speech.Audio;

public class AzureSpeechService
{
    private readonly SpeechConfig _config;

    public AzureSpeechService(string subscriptionKey, string region)
    {
        _config = SpeechConfig.FromSubscription(subscriptionKey, region);
        _config.SpeechSynthesisLanguage = "zh-TW";
        _config.SpeechSynthesisVoiceName = "zh-TW-HsiaoChenNeural"; // 神經網路語音
    }

    public async Task SpeakAsync(string text)
    {
        using var synthesizer = new SpeechSynthesizer(_config, AudioConfig.FromDefaultSpeakerOutput());
        var result = await synthesizer.SpeakTextAsync(text);
        if (result.Reason != ResultReason.SynthesizingAudioCompleted)
            throw new Exception($"合成失敗: {result.ErrorDetails}");
    }

    public async Task RecognizeAsync()
    {
        using var recognizer = new SpeechRecognizer(_config, AudioConfig.FromDefaultMicrophoneInput());
        var result = await recognizer.RecognizeOnceAsync();
        if (result.Reason == ResultReason.RecognizedSpeech)
            Console.WriteLine($"辨識: {result.Text}");
    }
}

四、比較與選型建議

特性System.SpeechWindows.MediaAzure Speech SDK
平台.NET Framework / .NET Core (Windows)UWP / WinUI 3 / Windows App SDK跨平台 (Windows/Linux/macOS/iOS/Android)
語音品質傳統 SAPI 語音 (較機械)現代語音 (含神經網路)最佳 (神經網路、可自訂語音)
離線辨識支援 (需安裝語言包)支援 (裝置端)需網路 (或容器部署)
中文支援需安裝 Microsoft 語言包內建完整支援 (多方言、混合)
SSML支援 (PromptBuilder)支援完整支援 (含訊息標記)
授權免費 (Windows 授權)免費依用量付費 (免費額度)

五、總結

  • 傳統 WinForms/WPF:使用 System.Speech,注意安裝正確語言包 (zh-TW 需 Microsoft Tracy,zh-CN 需 Hanhan)
  • 現代 Windows 應用:使用 Windows.Media.SpeechSynthesis/Recognition,獲得更好語音品質與 API 設計
  • 企業級/跨平台:Azure Speech SDK,最佳語音品質、支援自訂關鍵字、語音翻譯、說話人辨識
  • 中英文混合:文本分段 + 切換語音引擎,或使用支援多語言的 Azure 神經網路語音 (如 zh-TW-HsiaoChenNeural 可自然讀出英文)
  • 關鍵配置:麥克風權限、音訊格式 (16kHz/16bit/單聲道)、靜音偵測閾值、信心度過濾
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved