C#调用SAPI实现TTS时无法读取控制面板默认语音设置问询
问题根因
你用到的System.Speech.Synthesis是基于经典SAPI(SAPI v5.x)开发的,本身仅读取旧版SAPI的配置,而Windows 10/11控制面板里的「更改文本转语音设置」默认保存的是新版Windows Speech API的配置,两者的注册表存储路径是分离的:
- 隐藏SAPI.cpl(32位)的配置存于
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Speech\Voices - 控制面板通用TTS设置(对应64位/新版API)的配置存于
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Speech_OneCore\Voices
另外如果你的程序编译目标是32位,默认只会访问32位注册表节点,也会读不到64位控制面板里的配置。
解决方案
方案1:调整编译配置+手动读取新版注册表参数赋值
首先把项目编译目标改为x64(或设置为优先64位运行),避免32位注册表重定向的影响,然后直接从对应注册表路径读取用户在控制面板设置的参数,手动赋值给SpeechSynthesizer实例即可,示例代码如下:
using System; using System.Linq; using System.Speech.Synthesis; using Microsoft.Win32; namespace TTSDemo { class Program { static void Main(string[] args) { SpeechSynthesizer synth = new SpeechSynthesizer(); // 读取控制面板存储的默认TTS配置 using (RegistryKey key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Speech_OneCore\Voices")) { if (key != null) { // 读取并设置默认语音 string defaultVoiceId = key.GetValue("DefaultVoiceId") as string; if (!string.IsNullOrEmpty(defaultVoiceId)) { var matchedVoice = synth.GetInstalledVoices().FirstOrDefault(v => v.VoiceInfo.Id == defaultVoiceId); if (matchedVoice != null) { synth.SelectVoice(matchedVoice.VoiceInfo.Name); } } // 读取并设置语速,取值范围-10到10,和SpeechSynthesizer的Rate属性完全匹配 int defaultRate = (int)key.GetValue("DefaultRate", 0); synth.Rate = defaultRate; // 读取并设置音量,取值范围0到100,和SpeechSynthesizer的Volume属性完全匹配 int defaultVolume = (int)key.GetValue("DefaultVolume", 100); synth.Volume = defaultVolume; } } synth.SetOutputToDefaultAudioDevice(); synth.Speak("测试读取控制面板默认TTS配置"); Console.WriteLine("按任意键退出..."); Console.ReadKey(); } } }
注意:如果必须兼容32位程序运行,读取注册表时指定RegistryView.Registry64参数跳过32位重定向,直接访问64位注册表节点即可。
方案2:替换为新版Windows Speech API
如果你的程序仅面向Windows 10 1709及以上版本运行,可以直接使用Windows.Media.SpeechSynthesis命名空间下的API,这个API默认就会读取控制面板里的用户配置,不需要额外手动读取注册表,适配性更适合无障碍场景。
兼容性补充说明
如果用户安装的第三方语音仅在旧版SAPI中注册,没有在Speech_OneCore节点下注册,上述方案1的注册表读取可能匹配不到对应语音,这时可以加降级逻辑:如果在新版路径读不到有效配置,再回退读取旧版SAPI的配置即可,覆盖所有使用场景。
内容的提问来源于stack exchange,提问作者Eric Blackburn
相关产品推荐
相关产品推荐

