2012-02-24 7 views
1

WindowsフォームとSystem.Speechを使用してC#アプリケーションを作成して、WAVファイルをテキストに変換しようとしています。私はこれを行う方法のサンプルをオンラインでたくさん見てきましたが、どれも非常に堅牢ではありません。私は、BackgroundWorkerスレッドを使用して大きなWAVファイルの小さな部分を解析できるアプリケーションを作成したいと考えていましたが、engine.Recognize()を呼び出すときに、スレッドのDoWork関数で次の例外が発生し続けます。BackgroundWorkerのSpeechRecognitionEngine

"マイクがシステムに接続されている場合はSetInputToDefaultAudioDeviceメソッドを使用し、そうでなければSetInputToWaveFile、SetInputToWaveStreamまたはSetInputToAudioStreamを使用して事前録音されたオーディオから音声認識を実行します。 "

ここで私のDoWork関数:

SpeechRecognitionEngine engine = new SpeechRecognitionEngine(new System.Globalization.CultureInfo("en-US")); 
engine.SetInputToWaveFile(fname); 
engine.LoadGrammar(new DictationGrammar()); 
engine.BabbleTimeout = TimeSpan.FromSeconds(10.0); 
engine.EndSilenceTimeout = TimeSpan.FromSeconds(10.0); 
engine.EndSilenceTimeoutAmbiguous = TimeSpan.FromSeconds(10.0); 
engine.InitialSilenceTimeout = TimeSpan.FromSeconds(10.0); 

BackgroundWorker w = (BackgroundWorker)sender; 
while (true) 
{  
RecognitionResult data = engine.Recognize(); 
if (data == null) 
    break; 
if (w == null) //our thread died from beneath us 
    break; 
if (!w.IsBusy) //our thread died from beneath us 
    break; 
if (w.CancellationPending) //notice to cancel 
    break; 
w.ReportProgress(0, data.Text); 
} 

私はlこのコードを実行する複数のBackgroundWorkerスレッドを起動します。私が単一のスレッドを使用する場合、私はこの問題は表示されません。

+0

私は年間でSAPIで作業していないが、私の頭の上から、私は彼らが、プロセスのCOMサーバーの外にシングルとして実行することができます覚えているので、あなたが倍数simultanously動作するように取得しようとした場合、それはありませんデフォルトのシナリオでは、オーディオソースとプロセス認識ツールを共有する必要があります。 –

+0

私は、BackgroundWorkerスレッドからSpeechRecognitionEngineクラスを使用しようとすると、この例外が発生することに気付きました。 – user1229658

答えて

1

このアプローチを試すことができます。私はそれをConsoleとWindows Formsのアプリケーションタイプでテストしました。

class Program { 
    public static void Main() { 
     var r1 = new Recognizer(@"c:\proj\test.wav"); 
     r1.Completed += (sender, e) => Console.WriteLine(r1.Result.Text); 

     var r2 = new Recognizer(@"c:\proj\test.wav"); 
     r2.Completed += (sender, e) => Console.WriteLine(r2.Result.Text); 

     Console.ReadLine(); 
    } 
} 

class Recognizer { 
    private readonly string _fileName; 
    private readonly AsyncOperation _operation; 
    private volatile RecognitionResult _result; 

    public Recognizer(string fileName) { 
     _fileName = fileName; 
     _operation = AsyncOperationManager.CreateOperation(null);    
     _result = null; 

     var worker = new Action(Run); 
     worker.BeginInvoke(delegate(IAsyncResult result) { 
      worker.EndInvoke(result); 
     }, null);    
    } 

    private void Run() { 
     try { 
      SpeechRecognitionEngine engine = new SpeechRecognitionEngine(new System.Globalization.CultureInfo("en-US")); 
      engine.SetInputToWaveFile(_fileName); 
      engine.LoadGrammar(new DictationGrammar()); 
      engine.BabbleTimeout = TimeSpan.FromSeconds(10.0); 
      engine.EndSilenceTimeout = TimeSpan.FromSeconds(10.0); 
      engine.EndSilenceTimeoutAmbiguous = TimeSpan.FromSeconds(10.0); 
      engine.InitialSilenceTimeout = TimeSpan.FromSeconds(10.0); 
      _result = engine.Recognize(); 
     } 
     finally { 
      _operation.PostOperationCompleted(delegate { 
       RaiseCompleted(); 
      }, null); 
     } 
    } 

    public RecognitionResult Result { 
     get { return _result; } 
    } 

    public event EventHandler Completed; 

    protected virtual void OnCompleted(EventArgs e) { 
     if (Completed != null) 
      Completed(this, e); 
    } 

    private void RaiseCompleted() { 
     OnCompleted(EventArgs.Empty); 
    } 
} 
+0

クール、ありがとう!私は今朝このコードを使っていましたが、これはうまくいくと思いますが、実際にSpeechRecognitionEngineをマルチスレッド化できないのかどうかは分かりません。私が持っている1つの質問です。Completedイベントハンドラは別のスレッドのコンテキストで実行されるため、UIを更新することはできません。コール(UI)スレッドでコールバックを呼び出すようにサンプルを変更できますか? – user1229658

+0

ここで説明したコードを使用して動作させました。 http://www.codeproject.com/Articles/11848/Another-way-to-Invoke-UI-from-a-Worker-Thread – user1229658

+0

最後の質問 - これらの非同期操作をキャンセルする最良の方法は、Windowsフォーム操作の途中で閉じられていますか? – user1229658