我正在执行一些文字转语音,我想在词典文件中指定一些特殊的发音。我已经逐字地运行了MSDN's AddLexicon example,它说的是句子,但不使用给定的词典,似乎有些东西被打破了。
以下是提供的示例:
using System;
using Microsoft.Speech.Synthesis;
namespace SampleSynthesis
{
class Program
{
static void Main(string[] args)
{
// Initialize a new instance of the SpeechSynthesizer.
using (SpeechSynthesizer synth = new SpeechSynthesizer())
{
// Configure the audio output.
synth.SetOutputToDefaultAudioDevice();
PromptBuilder builder = new PromptBuilder();
builder.AppendText("Gimme the whatchamacallit.");
// Append the lexicon file.
synth.AddLexicon(new Uri("c:\\test\\whatchamacallit.pls"), "application/pls+xml");
// Speak the prompt and play back the output file.
synth.Speak(builder);
}
Console.WriteLine();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
}
和词典文件:
<lexicon version="1.0"
xmlns="http://www.w3.org/2005/01/pronunciation-lexicon"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2005/01/pronunciation-lexicon
http://www.w3.org/TR/2007/CR-pronunciation-lexicon-20071212/pls.xsd"
alphabet="x-microsoft-ups" xml:lang="en-US">
<lexeme>
<grapheme> whatchamacallit </grapheme>
<phoneme> W S1 AX T CH AX M AX K S2 AA L IH T </phoneme>
</lexeme>
</lexicon>
控制台打开,说出文字,但不使用新发音。我当然按规定将文件保存到c:\test\whatchamacallit.pls
。
我尝试过Uri和文件位置的变体(例如@"C:\Temp\whatchamacallit.pls"
,@"file:///c:\test\whatchamacallit.pls"
),绝对和相对路径,将其复制到构建文件夹等等。
我运行了Process Monitor,文件未被访问。如果它是一个目录/文件权限问题(它不是),我仍然会看到访问被拒绝的消息,但是我没有记录任何引用,除了偶尔从我的文本编辑器。我确实在尝试File.OpenRead
时看到了该文件。
不幸的是,使用垃圾Uri时没有错误消息。
在进一步调查中,我意识到这个例子来自Microsoft.Speech.Synthesis,而我在这里使用System.Speech.Synthesis。但是从我可以看出它们是相同的,除了一些额外的信息和示例,并且两者都指向相同的规范。这仍然是问题吗?
我确认该项目已设置为使用正确的.NET Framework 4。
我将MSDN中的示例与examples from the referenced spec进行了比较,并尝试了这些,但它没有帮助。考虑到文件似乎没有被访问,我并不感到惊讶。
(我可以正常使用PromptBuilder.AppendTextWithPronunciation
,但对于我的用例来说,这是一个不好的选择。)
MSDN上的示例是否已损坏?如何在SpeechSynthesizer中使用词典?
答案 0 :(得分:10)
经过大量的研究和陷阱,我可以向你保证,你的假设是完全错误的。
出于某种原因System.Speech.Synthesis.SpeechSynthesizer.AddLexicon()
将词典添加到内部列表中,但根本不使用它。
似乎之前没有人尝试使用它,这个错误被忽视了。
Microsoft.Speech.Synthesis.SpeechSynthesizer.AddLexicon()
(属于Microsoft Speech SDK)按预期工作(它将词典传递给COM对象,该对象将其解释为广告)。
请参阅本指南,了解如何安装SDK:http://msdn.microsoft.com/en-us/library/hh362873%28v=office.14%29.aspx
注意:
答案 1 :(得分:1)
最近我在Windows 10上对此进行了研究。
我发现了两件事。
您使用的任何语音都必须与Lexicon文件中的语言匹配。 在词典中,您具有以下语言:
<lexicon version="1.0"
xmlns="http://www.w3.org/2005/01/pronunciation-lexicon"
alphabet="x-microsoft-ups" xml:lang="en-US">
我发现我可以将Lexicon命名为“ blue.en-US.pls”,并使用“ blue.en-GB.pls”进行复制。里面会有xml:lang =“ en-GB”
在您要使用的代码中:
string langFile = Path.Combine(_appPath, $"blue.{synth.Voice.Culture.IetfLanguageTag}.pls");
synth.AddLexicon(new Uri(langFile), "application/pls+xml");
我发现的另一件事是,它根本不适用于“ Microsoft Zira Desktop-English(United States)”。我不知道为什么 这似乎是Windows 10上的默认声音。
在此处访问并更改您的默认语音: %windir%\ system32 \ speech \ SpeechUX \ SAPI.cpl
否则,您应该可以通过代码进行设置:
var voices = synth.GetInstalledVoices();
var voice = voices.First(v => v.VoiceInfo.Name.Contains("David")); // US. David, Hazel, Zira
synth.SelectVoice(voice.VoiceInfo.Name);
我有David(美国)和Hazel(英国),并且与其中任何一个都可以正常工作。
答案 2 :(得分:1)
您可以使用System.Speech.Synthesis.SpeechSynthesizer.SpeakSsml()
代替词典。
此代码将“ blue”的发音更改为“ yellow”,将“ dog”的发音更改为“ fish”。
SpeechSynthesizer synth = new SpeechSynthesizer();
string text = "This is a blue dog";
Dictionary<string, string> phonemeDictionary = new Dictionary<string, string> { { "blue", "jelow" }, { "dog", "fyʃ" } };
foreach (var element in phonemeDictionary)
{
text = text.Replace(element.Key, "<phoneme ph=\"" + element.Value + "\">" + element.Key + "</phoneme>");
}
text = "<speak version=\"1.0\" xmlns=\"http://www.w3.org/2001/10/synthesis\" xml:lang=\"en-US\">" + text + "</speak>";
synth.SpeakSsml(text);