Windows 10 TTS的声音没有出现?

时间:2016-11-03 16:29:11

标签: windows-10 text-to-speech

我安装了几个英语语言包(美国,英国和加拿大)及其语音选项,我可以在Windows 10设置中访问它们 - >演讲,但他们没有显示从控制面板可用的文本到语音选项,我不能使用应用程序的声音!

我可以使用David和Zira的默认声音!

知道如何使用其他声音?

3 个答案:

答案 0 :(得分:0)

Windows 10默认安装了两个个不同的TTS引擎。有WinRT speech synthesis APIs(在Windows.Media.SpeechSynthesis命名空间中)和SAPI speech synthesis APIs(在System.Speech.Synthesis命名空间和COM ISpVoice接口中)。

David和Zira是SAPI的声音;语言包安装WinRT语音。

SAPI API和声音是传统的API,尚未进一步开发;所有新的声音和努力都将进入WinRT API和声音。

如果您想使用语言包语音,则需要将应用程序移至WinRT并使用WinRT API。

答案 1 :(得分:0)

我设法通过修改Windows注册表来解决此问题。就我而言,在Windows 10下,我安装了带有TTS软件包的德语,并且安装了女性声音(WinRT和SAPI)加上男性声音(仅WinRT)。我需要用C#制作一个桌面程序(不是通用应用程序),该程序利用了男性声音,但无法通过SAPI使用。因此,我做了这个“ hack”,并且马上就工作了(Windows 10版本1803)。适用于32位和64位程序(本机或WOW)。

在Windows 8+中,有两个语音合成编程接口(如Eric Brown所述)。但是在研究了Windows注册表和其中引用的几个文件后,我注意到这两个API使用相同的数据文件,因此我将注册表项从WinRT API中注册的德语男性语音复制到相应的SAPI部分。

详细说明如下:

  1. 打开“ regedit.exe”。
  2. 导航至键
  

HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Speech_OneCore \ Voices \ Tokens

您将在其中找到每个WinRT语音都在其自己的密钥下注册。在我的情况下,德语男声称为 MSTTS_V110_deDE_StefanM

  1. 最简单的方法是右键单击语音键(MSTTS_V110_deDE_StefanM),然后从上下文菜单中选择导出,以将整个语音结构保存到文件中(稍后将使您轻松如果您想在另一台计算机上执行这些操作,只需将这些步骤复制到几次单击中即可。

  2. 使用记事本或类似工具打开导出的文件。在这里,您会找到两个 键路径。两者都将引用键 Speech_OneCore 。您要做的就是将两个引用都从Speech_OneCore更改为语音

  3. 删除名为 SayAsSupport 的属性的整行,SAPI不需要此行。

  4. 保存文件。经过修改后,它应该看起来像这样(要特别注意关键路径):

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\MSTTS_V110_deDE_StefanM]
@="Microsoft Stefan - German (Germany)"
"407"="Microsoft Stefan - German (Germany)"
"CLSID"="{179F3D56-1B0B-42B2-A962-59B7EF59FE1B}"
"LangDataPath"=hex(2):25,00,77,00,69,00,6e,00,64,00,69,00,72,00,25,00,5c,00,53,\
  00,70,00,65,00,65,00,63,00,68,00,5f,00,4f,00,6e,00,65,00,43,00,6f,00,72,00,\
  65,00,5c,00,45,00,6e,00,67,00,69,00,6e,00,65,00,73,00,5c,00,54,00,54,00,53,\
  00,5c,00,64,00,65,00,2d,00,44,00,45,00,5c,00,4d,00,53,00,54,00,54,00,53,00,\
  4c,00,6f,00,63,00,64,00,65,00,44,00,45,00,2e,00,64,00,61,00,74,00,00,00
"VoicePath"=hex(2):25,00,77,00,69,00,6e,00,64,00,69,00,72,00,25,00,5c,00,53,00,\
  70,00,65,00,65,00,63,00,68,00,5f,00,4f,00,6e,00,65,00,43,00,6f,00,72,00,65,\
  00,5c,00,45,00,6e,00,67,00,69,00,6e,00,65,00,73,00,5c,00,54,00,54,00,53,00,\
  5c,00,64,00,65,00,2d,00,44,00,45,00,5c,00,4d,00,31,00,30,00,33,00,31,00,53,\
  00,74,00,65,00,66,00,61,00,6e,00,00,00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\MSTTS_V110_deDE_StefanM\Attributes]
"Age"="Adult"
"DataVersion"="11.0.2013.1022"
"Gender"="Male"
"Language"="407"
"Name"="Microsoft Stefan"
"SharedPronunciation"=""
"Vendor"="Microsoft"
"Version"="11.0"
  1. 嵌入通过双击文件创建的注册表项。

完成!但是请注意,这将使语音通过SAPI在Windows 10的32位版本(或Windows 10的64位版本)下可用于32位程序,或者在Windows 10的64位版本下可用于64位程序。 Windows 64位版本的位程序,则需要在 WOW6432Node 下嵌入相应的密钥。为此,只需为已编辑的文件制作一个额外的副本,然后将其命名为“ my_voice_WOW.reg”。编辑此新副本,现在在两个键路径中的键 SOFTWARE Microsoft 之间插入另一个名为“ WOW6432Node”的键。保存并嵌入文件,这将在WOW树节点中创建相应的键。您的WOW文件应如下所示(请特别注意关键路径):

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Speech\Voices\Tokens\MSTTS_V110_deDE_StefanM]
@="Microsoft Stefan - German (Germany)"
"407"="Microsoft Stefan - German (Germany)"
"CLSID"="{179F3D56-1B0B-42B2-A962-59B7EF59FE1B}"
"LangDataPath"=hex(2):25,00,77,00,69,00,6e,00,64,00,69,00,72,00,25,00,5c,00,53,\
  00,70,00,65,00,65,00,63,00,68,00,5f,00,4f,00,6e,00,65,00,43,00,6f,00,72,00,\
  65,00,5c,00,45,00,6e,00,67,00,69,00,6e,00,65,00,73,00,5c,00,54,00,54,00,53,\
  00,5c,00,64,00,65,00,2d,00,44,00,45,00,5c,00,4d,00,53,00,54,00,54,00,53,00,\
  4c,00,6f,00,63,00,64,00,65,00,44,00,45,00,2e,00,64,00,61,00,74,00,00,00
"VoicePath"=hex(2):25,00,77,00,69,00,6e,00,64,00,69,00,72,00,25,00,5c,00,53,00,\
  70,00,65,00,65,00,63,00,68,00,5f,00,4f,00,6e,00,65,00,43,00,6f,00,72,00,65,\
  00,5c,00,45,00,6e,00,67,00,69,00,6e,00,65,00,73,00,5c,00,54,00,54,00,53,00,\
  5c,00,64,00,65,00,2d,00,44,00,45,00,5c,00,4d,00,31,00,30,00,33,00,31,00,53,\
  00,74,00,65,00,66,00,61,00,6e,00,00,00

[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Speech\Voices\Tokens\MSTTS_V110_deDE_StefanM\Attributes]
"Age"="Adult"
"DataVersion"="11.0.2013.1022"
"Gender"="Male"
"Language"="407"
"Name"="Microsoft Stefan"
"SharedPronunciation"=""
"Vendor"="Microsoft"
"Version"="11.0"

希望这会有所帮助。

答案 2 :(得分:0)

这是一个 C# 代码示例,用于将 Speech_OnceCore 注册表项复制到语音注册表项(与 System.Speech.Synthesis 一起用作 SAPI 语音):

public List<string> CopySpeechRegistryEntryFromOneCore()
{
    var voices = new List<string>();
    try
    {
        using (RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Speech_OneCore\Voices\Tokens"))
        using (RegistryKey newKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Speech\Voices\Tokens", 
            RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.FullControl))
        {
            if (key != null)
            {
                var keys = key.GetSubKeyNames();
                foreach (var item in keys)
                {
                    if (newKey.OpenSubKey(item) == null)
                    {
                        RegistryKey voice = newKey.CreateSubKey(item);
                        foreach (var subKey in key.OpenSubKey(item).GetValueNames())
                        {
                            var value = key.OpenSubKey(item).GetValue(subKey);
                            if (value is string) value = (value as string).Replace(@"C:\WINDOWS", "%windir%");
                            var kind = key.OpenSubKey(item).GetValueKind(subKey);
                            voice.SetValue(subKey, value, kind);
                        }
                        foreach (var subAttribute in key.OpenSubKey(item).GetSubKeyNames())
                        {
                            RegistryKey attributes = voice.CreateSubKey(subAttribute);
                            foreach (var attribute in key.OpenSubKey(item).OpenSubKey(subAttribute).GetValueNames())
                            {
                                var value = key.OpenSubKey(item).OpenSubKey(subAttribute).GetValue(attribute);
                                var kind = key.OpenSubKey(item).OpenSubKey(subAttribute).GetValueKind(attribute);
                                if (attribute != "SayAsSupport")
                                {
                                    attributes.SetValue(attribute, value, kind);
                                }
                            }
                        }
                        voices.Add(item);
                    }
                }
            }
        }
    }
    catch (Exception ex)
    {
        voices.Add($"Error: {ex.Message}");
        return voices;
    }
    return voices;
}