语音识别引擎不是Windows服务中的触发事件

时间:2012-04-30 01:53:11

标签: c# windows-services speech-recognition

所以我有一个使用system.speech识别引擎实现语音识别的Windows服务。当我启动服务时,我的语音识别代码运行良好,但没有语音事件识别出来。奇怪的是,如果我运行完全相同的代码,但在控制台或WPF应用程序中,语音识别的事件触发工作正常。
我已经在我的服务进程中附加了一个调试器,以检查幕后发生了什么。似乎语音识别引擎正确加载语法,将其模式设置为连续收听,并正确设置语音识别事件。没有异常被抛出,所以我不太清楚这里有什么问题。有什么想法吗?

4 个答案:

答案 0 :(得分: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时也遇到了类似的问题。 以上是一个很好的用法示例+它在另一个线程中监听事件。 p.s:我从一篇好文章中得到了参考: Speech recognition, speech to text, text to speech, and speech synthesis in C#有 乐趣:))

答案 1 :(得分:2)

您使用麦克风还是处理WAV文件?如果您尝试使用默认音频设备,我不确定音频管道如何在服务中工作。如果您尝试从音频文件或流转换,请确保使用的是InProc识别器。

如果您要创建服务器应用程序,则可能应考虑使用Microsoft.Speech API和服务器识别器。请参阅What is the difference between System.Speech.Recognition and Microsoft.Speech.Recognition?和Microsoft Speech Platform 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

答案 2 :(得分:1)

您是否尝试过设置服务以允许与桌面交互?

Image

我认为此设置涵盖了与麦克风等用户接口设备的交互。

答案 3 :(得分:1)

如果@Robocide答案对您不起作用,例如在我的情况下,您所要做的就是将SpeechRecognitionEngine声明为字段,而不是Main方法中的局部变量。

示例:

    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,因为它在无法识别语音的情况下不允许某些进程运行。