所以我有一个使用 system.speech 识别引擎实现语音识别的 Windows 服务。当我启动服务时,我的语音识别代码运行良好,但没有发生语音识别火灾的事件。奇怪的是,如果我运行完全相同的代码,但在控制台或 WPF 应用程序中,语音识别的事件触发就可以正常工作。
我已经在我的服务进程中附加了一个调试器,以检查幕后发生的事情。似乎语音识别引擎正确加载了语法,将其模式设置为连续收听,并正确设置了语音识别事件。没有抛出异常,所以我不太确定这里出了什么问题。有任何想法吗?
4 回答
SpeechRecognition 应该在单独的线程上运行,并且来自 SpeechRecognitionEngine OOTB,应该是这样的:
static ManualResetEvent _completed = null;
static void Main(string[] args)
{
_completed = new ManualResetEvent(false);
SpeechRecognitionEngine _recognizer = new SpeechRecognitionEngine();
_recognizer.RequestRecognizerUpdate(); // request for recognizer update
_recognizer.LoadGrammar(new Grammar(new GrammarBuilder("test")) Name = { "testGrammar" }); // load a grammar
_recognizer.RequestRecognizerUpdate(); // request for recognizer update
_recognizer.LoadGrammar(new Grammar(new GrammarBuilder("exit")) Name = { "exitGrammar" }); // load a "exit" grammar
_recognizer.SpeechRecognized += _recognizer_SpeechRecognized;
_recognizer.SetInputToDefaultAudioDevice(); // set the input of the speech recognizer to the default audio device
_recognizer.RecognizeAsync(RecognizeMode.Multiple); // recognize speech asynchronous
_completed.WaitOne(); // wait until speech recognition is completed
_recognizer.Dispose(); // dispose the speech recognition engine
}
void _recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
if (e.Result.Text == "test") // e.Result.Text contains the recognized text
{
Console.WriteLine("The test was successful!");
}
else if (e.Result.Text == "exit")
{
_completed.Set();
}
}
当我使用 SpeechRecognition 而不是 SpeechRecognitionEngine 时也有类似的问题。以上是一个很好的用法示例+它在另一个线程中监听事件。ps:我从一篇很棒的文章中得到了参考: Speech recognition, speech to text, text to Speech, and Speech synthesis in C# have Fun :)
您是在使用麦克风还是在处理 WAV 文件?如果您尝试使用默认音频设备,我不确定音频管道将如何在服务中工作。如果您尝试从音频文件或流转换,请确保您使用的是 InProc 识别器。
如果您正在创建服务器应用程序,您可能应该考虑使用 Microsoft.Speech API 和服务器识别器。请参阅System.Speech.Recognition 和 Microsoft.Speech.Recognition 有什么区别?和 Microsoft 语音平台 SDK - http://www.microsoft.com/en-us/download/details.aspx?id=27226
如果您尝试在没有您的应用程序在前台的情况下进行持续识别,我相信共享识别器可能能够满足您的需求。Windows 7 和 Vista 中附带的 Microsoft 桌面识别器可以在两种模式下工作:inproc 或 shared。共享识别器在使用语音命令控制任何打开的应用程序的桌面上很有用。在 System.Speech 中,您可以使用SpeechRecognizer访问共享桌面识别器或SpeechRecognitionEngine为您的应用程序提供专用的 inproc 识别器。即使您的应用程序不在前台,您也可以使用共享识别器为您的应用程序提供持续识别。
几年前在http://msdn.microsoft.com/en-us/magazine/cc163663.aspx上发表了一篇非常好的文章。这可能是迄今为止我发现的最好的介绍性文章。它说:
...识别引擎可以在另一个名为 SAPISVR.EXE 的进程中实例化。这提供了一个可以被多个应用程序同时使用的共享识别引擎。这种设计有很多好处。首先,识别器通常比合成器需要更多的运行时资源,共享识别器是减少开销的有效方法。其次,Windows Vista 的内置语音功能也使用共享识别器。因此,使用共享识别器的应用程序可以从系统的麦克风和反馈 UI 中受益。无需编写额外的代码,也无需用户学习新的 UI。SAPI 5.3 的新功能
您是否尝试将服务设置为允许与桌面交互?
我相信此设置涵盖了与麦克风等用户接口设备的交互。
如果@Robocide 答案对您不起作用,就像我的情况一样,您所要做的就是在 Main 方法中将 SpeechRecognitionEngine 声明为字段而不是局部变量。
例子:
private SpeechRecognitionEngine _recognizer = null; //make the speeach recognition engine a private field
static void Main(string[] args)
{
_recognizer = new SpeechRecognitionEngine();
_recognizer.RequestRecognizerUpdate(); // request for recognizer update
_recognizer.LoadGrammar(new Grammar(new GrammarBuilder("test")) Name = { "testGrammar" }); // load a grammar
_recognizer.RequestRecognizerUpdate(); // request for recognizer update
_recognizer.LoadGrammar(new Grammar(new GrammarBuilder("exit")) Name = { "exitGrammar" }); // load a "exit" grammar
_recognizer.SpeechRecognized += _recognizer_SpeechRecognized;
_recognizer.SetInputToDefaultAudioDevice(); // set the input of the speech recognizer to the default audio device
_recognizer.RecognizeAsync(RecognizeMode.Multiple); // recognize speech asynchronous
_recognizer.Dispose(); // dispose the speech recognition engine
}
void _recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
if (e.Result.Text == "test") // e.Result.Text contains the recognized text
{
Console.WriteLine("The test was successful!");
}
}
如果您注意到,我删除了 ManualResetEvent,因为如果语音未被识别,它不允许某些进程运行。