継続的なディクテーションContinuous dictation

長い形式の継続的なディクテーション音声入力をキャプチャし、認識する方法について説明します。Learn how to capture and recognize long-form, continuous dictation speech input.

重要な API: SpeechContinuousRecognitionSessionContinuousRecognitionSessionImportant APIs: SpeechContinuousRecognitionSession, ContinuousRecognitionSession

音声認識」では、SpeechRecognizer オブジェクトの RecognizeAsync メソッドまたは RecognizeWithUIAsync メソッドを使って、比較的短い音声入力をキャプチャし、認識する方法について説明しました。たとえば、ショート メッセージ サービス (SMS) のメッセージを作成したり、質問したりする場合です。In Speech recognition, you learned how to capture and recognize relatively short speech input using the RecognizeAsync or RecognizeWithUIAsync methods of a SpeechRecognizer object, for example, when composing a short message service (SMS) message or when asking a question.

ディクテーションまたはメールなど、より長い継続的な音声認識セッションの場合は、SpeechRecognizerContinuousRecognitionSession プロパティを使って SpeechContinuousRecognitionSession オブジェクトを取得します。For longer, continuous speech recognition sessions, such as dictation or email, use the ContinuousRecognitionSession property of a SpeechRecognizer to obtain a SpeechContinuousRecognitionSession object.

注意

ディクテーション言語のサポートは、アプリが実行されている デバイス によって異なります。Dictation language support depends on the device where your app is running. Pc とラップトップの場合は en-us のみが認識され、Xbox と携帯電話は音声認識によってサポートされるすべての言語を認識できます。For PCs and laptops, only en-US is recognized, while Xbox and phones can recognize all languages supported by speech recognition. 詳細については、「 音声認識エンジンの言語を指定する」を参照してください。For more info, see Specify the speech recognizer language.

設定Set up

アプリには、継続的なディクテーション セッションを管理するためのオブジェクトがいくつか必要です。Your app needs a few objects to manage a continuous dictation session:

  • 1 インスタンスの SpeechRecognizer オブジェクト。An instance of a SpeechRecognizer object.
  • ディクテーション中の UI を更新するための UI ディスパッチャーへの参照。A reference to a UI dispatcher to update the UI during dictation.
  • ユーザーが発声し、蓄積された単語を追跡する方法。A way to track the accumulated words spoken by the user.

ここでは、SpeechRecognizer インスタンスを、コード ビハインド クラスのプライベート フィールドとして宣言します。Here, we declare a SpeechRecognizer instance as a private field of the code-behind class. 継続的なディクテーションが、1 つの XAML (Extensible Application Markup Language) ページを超えて持続する場合、アプリは、参照を別の場所に格納する必要があります。Your app needs to store a reference elsewhere if you want continuous dictation to persist beyond a single Extensible Application Markup Language (XAML) page.

private SpeechRecognizer speechRecognizer;

ディクテーション中に認識エンジンは、バックグラウンド スレッドからイベントを生成します。During dictation, the recognizer raises events from a background thread. バックグラウンド スレッドは、XAML の UI を直接更新できないため、アプリはディスパッチャーを使って、認識イベントに応答して UI を更新する必要があります。Because a background thread cannot directly update the UI in XAML, your app must use a dispatcher to update the UI in response to recognition events.

ここでは、プライベート フィールドを宣言し、それが後で UI ディスパッチャーで初期化されます。Here, we declare a private field that will be initialized later with the UI dispatcher.

// Speech events may originate from a thread other than the UI thread.
// Keep track of the UI thread dispatcher so that we can update the
// UI in a thread-safe manner.
private CoreDispatcher dispatcher;

ユーザーが発声した内容を追跡するには、音声認識エンジンによって生成された認識イベントを処理する必要があります。To track what the user is saying, you need to handle recognition events raised by the speech recognizer. これらのイベントは、ユーザーの発声のチャンクを認識した結果を提供します。These events provide the recognition results for chunks of user utterances.

ここでは、StringBuilder オブジェクトを使って、セッション中に取得したすべての認識結果を保持します。Here, we use a StringBuilder object to hold all the recognition results obtained during the session. 新しい検索結果は、処理されるに従って StringBuilder に追加されます。New results are appended to the StringBuilder as they are processed.

private StringBuilder dictatedTextBuilder;

初期化Initialization

継続的な音声認識の初期化時には、次の操作を行う必要があります。During the initialization of continuous speech recognition, you must:

  • 連続的な認識のイベント ハンドラーでアプリの UI を更新する場合は、UI スレッドのディスパッチャーを取得します。Fetch the dispatcher for the UI thread if you update the UI of your app in the continuous recognition event handlers.
  • 音声認識エンジンを初期化します。Initialize the speech recognizer.
  • 組み込みのディクテーション文法をコンパイルします。Compile the built-in dictation grammar. メモ   音声認識では、認識可能なボキャブラリを定義するために少なくとも1つの制約が必要です。Note   Speech recognition requires at least one constraint to define a recognizable vocabulary. 制約が指定されていない場合は、定義済みのディクテーション文法が使われます。If no constraint is specified, a predefined dictation grammar is used. 音声認識」をご覧ください。See Speech recognition.
  • 認識イベントのイベント リスナーをセットアップします。Set up the event listeners for recognition events.

この例では、OnNavigatedTo ページ イベントで音声認識を初期化します。In this example, we initialize speech recognition in the OnNavigatedTo page event.

  1. 音声認識エンジンが生成するイベントはバックグラウンド スレッドで発生するため、UI スレッドを更新するためのディスパッチャーへの参照を作成します。Because events raised by the speech recognizer occur on a background thread, create a reference to the dispatcher for updates to the UI thread. OnNavigatedTo は、常に UI スレッド上で呼び出されます。OnNavigatedTo is always invoked on the UI thread.
this.dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
  1. その後、SpeechRecognizer インスタンスを初期化します。We then initialize the SpeechRecognizer instance.
this.speechRecognizer = new SpeechRecognizer();
  1. 次に、 SpeechRecognizerによって認識される可能性のあるすべての単語と語句を定義する文法を追加してコンパイルします。We then add and compile the grammar that defines all of the words and phrases that can be recognized by the SpeechRecognizer.

    文法を明示的に指定しない場合は、既定で定義済みのディクテーション文法が使われます。If you don't specify a grammar explicitly, a predefined dictation grammar is used by default. 通常、一般的なディクテーションには、既定の文法が最適です。Typically, the default grammar is best for general dictation.

    ここでは、文法を追加せずに、すぐに CompileConstraintsAsync を呼び出します。Here, we call CompileConstraintsAsync immediately without adding a grammar.

SpeechRecognitionCompilationResult result =
      await speechRecognizer.CompileConstraintsAsync();

認識イベントの処理Handle recognition events

RecognizeAsyncまたは認識を呼び出すことによって、単一の簡単な (発話)またはフレーズをキャプチャできます。You can capture a single, brief utterance or phrase by calling RecognizeAsync or RecognizeWithUIAsync.

ただし、より長い継続的な認識セッションをキャプチャするには、ユーザーが話す間にバックグラウンドで動作するイベント リスナーを指定し、ディクテーション文字列を作成するためのハンドラーを定義します。However, to capture a longer, continuous recognition session, we specify event listeners to run in the background as the user speaks and define handlers to build the dictation string.

そして、認識エンジンの ContinuousRecognitionSession プロパティを使って、継続的な認識セッションを管理するためのメソッドとイベントを提供する SpeechContinuousRecognitionSession オブジェクトを取得します。We then use the ContinuousRecognitionSession property of our recognizer to obtain a SpeechContinuousRecognitionSession object that provides methods and events for managing a continuous recognition session.

特に、次の 2 つのイベントが重要です。Two events in particular are critical:

  • ResultGenerated。これは、認識エンジンがいくつかの結果を生成したときに発生します。ResultGenerated, which occurs when the recognizer has generated some results.
  • Completed。継続的な認識セッションが終了したときに発生します。Completed, which occurs when the continuous recognition session has ended.

ResultGenerated イベントは、ユーザーが発声すると発生します。The ResultGenerated event is raised as the user speaks. 認識エンジンは、ユーザーの発声を聞き続け、音声入力のチャンクを渡すイベントを定期的に生成します。The recognizer continuously listens to the user and periodically raises an event that passes a chunk of speech input. 音声入力は、イベントの引数の Result プロパティを使って確認し、イベント ハンドラーで適切な処置を行う必要があります。たとえば、StringBuilder オブジェクトにテキストを追加します。You must examine the speech input, using the Result property of the event argument, and take appropriate action in the event handler, such as appending the text to a StringBuilder object.

SpeechRecognitionResult のインスタンスである Result プロパティは、音声入力を受け入れるかどうかを決定するために役立ちます。As an instance of SpeechRecognitionResult, the Result property is useful for determining whether you want to accept the speech input. SpeechRecognitionResult には、このための 2 つのプロパティが用意されています。A SpeechRecognitionResult provides two properties for this:

  • Status は、正常に認識できたかどうかを示します。Status indicates whether the recognition was successful. さまざまな原因により、認識できない場合もあります。Recognition can fail for a variety of reasons.
  • Confidence は、認識エンジンが、正しい単語を理解したことを比較的確信していることを示します。Confidence indicates the relative confidence that the recognizer understood the correct words.

継続的な認識をサポートするための基本的な手順は次のとおりです。Here are the basic steps for supporting continuous recognition:

  1. ここでは、ResultGenerated 継続的認識イベントのハンドラーを OnNavigatedTo ページ イベントに登録します。Here, we register the handler for the ResultGenerated continuous recognition event in the OnNavigatedTo page event.
speechRecognizer.ContinuousRecognitionSession.ResultGenerated +=
        ContinuousRecognitionSession_ResultGenerated;
  1. そして、Confidence プロパティを確認します。We then check the Confidence property. Confidence の値が Medium 以上である場合は、StringBuilder にテキストを追加します。If the value of Confidence is Medium or better, we append the text to the StringBuilder. 入力の収集時に UI も更新します。We also update the UI as we collect input.

    メモ   Resultgeneratedイベントは、UI を直接更新できないバックグラウンドスレッドで発生します。Note  the ResultGenerated event is raised on a background thread that cannot update the UI directly. ハンドラーが UI を更新する必要がある場合 ( [ Speech および TTS サンプルの場合と同様 ] )、ディスパッチャーの runasync メソッドを使用して、ui スレッドに更新プログラムをディスパッチする必要があります。If a handler needs to update the UI (as the [Speech and TTS sample] does), you must dispatch the updates to the UI thread through the RunAsync method of the dispatcher.

private async void ContinuousRecognitionSession_ResultGenerated(
      SpeechContinuousRecognitionSession sender,
      SpeechContinuousRecognitionResultGeneratedEventArgs args)
      {

        if (args.Result.Confidence == SpeechRecognitionConfidence.Medium ||
          args.Result.Confidence == SpeechRecognitionConfidence.High)
          {
            dictatedTextBuilder.Append(args.Result.Text + " ");

            await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
              dictationTextBox.Text = dictatedTextBuilder.ToString();
              btnClearText.IsEnabled = true;
            });
          }
        else
        {
          await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
              dictationTextBox.Text = dictatedTextBuilder.ToString();
            });
        }
      }
  1. その後、Completed イベントを処理します。これが、継続的なディクテーションの終了を示します。We then handle the Completed event, which indicates the end of continuous dictation.

    セッションは、StopAsync メソッドまたは CancelAsync メソッド (次のセクションを参照) を呼び出すと終了します。The session ends when you call the StopAsync or CancelAsync methods (described the next section). セッションは、エラーが発生したときや、ユーザーが発声を停止したときに終了することもあります。The session can also end when an error occurs, or when the user has stopped speaking. イベントの引数の Status プロパティを確認して、セッションが終了した理由を特定してください (SpeechRecognitionResultStatus)。Check the Status property of the event argument to determine why the session ended (SpeechRecognitionResultStatus).

    ここでは、Completed 継続的認識イベントのハンドラーを OnNavigatedTo ページ イベントに登録します。Here, we register the handler for the Completed continuous recognition event in the OnNavigatedTo page event.

speechRecognizer.ContinuousRecognitionSession.Completed +=
      ContinuousRecognitionSession_Completed;
  1. イベント ハンドラーは Status プロパティを確認して、正常に認識できたかどうかを判断します。The event handler checks the Status property to determine whether the recognition was successful. また、ユーザーが発声を停止した場合の処理も行います。It also handles the case where the user has stopped speaking. 多くの場合、TimeoutExceeded によって、正常に認識されたと見なされます。これは、ユーザーの発声が終了したことを意味するためです。Often, a TimeoutExceeded is considered successful recognition as it means the user has finished speaking. 快適に使えるように、このケースをコード内で処理する必要があります。You should handle this case in your code for a good experience.

    メモ   Resultgeneratedイベントは、UI を直接更新できないバックグラウンドスレッドで発生します。Note  the ResultGenerated event is raised on a background thread that cannot update the UI directly. ハンドラーが UI を更新する必要がある場合 ( [ Speech および TTS サンプルの場合と同様 ] )、ディスパッチャーの runasync メソッドを使用して、ui スレッドに更新プログラムをディスパッチする必要があります。If a handler needs to update the UI (as the [Speech and TTS sample] does), you must dispatch the updates to the UI thread through the RunAsync method of the dispatcher.

private async void ContinuousRecognitionSession_Completed(
      SpeechContinuousRecognitionSession sender,
      SpeechContinuousRecognitionCompletedEventArgs args)
      {
        if (args.Status != SpeechRecognitionResultStatus.Success)
        {
          if (args.Status == SpeechRecognitionResultStatus.TimeoutExceeded)
          {
            await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
              rootPage.NotifyUser(
                "Automatic Time Out of Dictation",
                NotifyType.StatusMessage);

              DictationButtonText.Text = " Continuous Recognition";
              dictationTextBox.Text = dictatedTextBuilder.ToString();
            });
          }
          else
          {
            await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
              rootPage.NotifyUser(
                "Continuous Recognition Completed: " + args.Status.ToString(),
                NotifyType.StatusMessage);

              DictationButtonText.Text = " Continuous Recognition";
            });
          }
        }
      }

実行中の認識に対するフィードバックの提供Provide ongoing recognition feedback

人が会話する場合は、話の内容を完全に理解するためにコンテキストが必要であることがよくあります。When people converse, they often rely on context to fully understand what is being said. 同様に、信頼性の高い認識結果を提供するために音声認識エンジンにコンテキストが必要である場合がよくあります。Similarly, the speech recognizer often needs context to provide high-confidence recognition results. たとえば、"weight" および "wait" という単語は、それ自体だけでは区別できないため、周囲の単語からコンテキストをさらに探り出す必要があります。For example, by themselves, the words "weight" and "wait" are indistinguishable until more context can be gleaned from surrounding words. 認識エンジンは、単語や語句を正しく認識したことを、ある程度確信するまでは、ResultGenerated イベントを生成しません。Until the recognizer has some confidence that a word, or words, have been recognized correctly, it will not raise the ResultGenerated event.

したがって、ユーザーが話し続けても、認識エンジンが ResultGenerated イベントを生成できると確信するまでは結果が表示されないため、ユーザーにとって快適とはいえない結果になる場合があります。This can result in a less than ideal experience for the user as they continue speaking and no results are provided until the recognizer has high enough confidence to raise the ResultGenerated event.

この不十分な応答性を改善するには、HypothesisGenerated イベントを処理します。Handle the HypothesisGenerated event to improve this apparent lack of responsiveness. このイベントは、処理中の単語と一致すると思われる新しいセットを認識エンジンが生成するたびに発生します。This event is raised whenever the recognizer generates a new set of potential matches for the word being processed. イベント引数は、現在一致している内容を含む Hypothesis プロパティを提供します。The event argument provides an Hypothesis property that contains the current matches. 話し続けるユーザーに、これらを表示して、処理がまだ続行されていることを知らせます。Show these to the user as they continue speaking and reassure them that processing is still active. 認識エンジンが十分に確信し、認識結果が確定されたら、暫定の Hypothesis 結果を、ResultGenerated イベントで提供される最終的な Result に置き換えます。Once confidence is high and a recognition result has been determined, replace the interim Hypothesis results with the final Result provided in the ResultGenerated event.

ここでは、仮のテキストと省略記号 ("…") を、出力 TextBox の現在の値に追加します。Here, we append the hypothetical text and an ellipsis ("…") to the current value of the output TextBox. テキスト ボックスの内容は、新しい仮の結果が生成されるたびに更新され、最後に、最終的な結果が ResultGenerated イベントから取得されます。The contents of the text box are updated as new hypotheses are generated and until the final results are obtained from the ResultGenerated event.

private async void SpeechRecognizer_HypothesisGenerated(
  SpeechRecognizer sender,
  SpeechRecognitionHypothesisGeneratedEventArgs args)
  {

    string hypothesis = args.Hypothesis.Text;
    string textboxContent = dictatedTextBuilder.ToString() + " " + hypothesis + " ...";

    await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
      dictationTextBox.Text = textboxContent;
      btnClearText.IsEnabled = true;
    });
  }

認識の開始と停止Start and stop recognition

認識セッションを開始する前に、音声認識エンジンの State プロパティの値を確認します。Before starting a recognition session, check the value of the speech recognizer State property. 音声認識エンジンは、Idle 状態である必要があります。The speech recognizer must be in an Idle state.

音声認識エンジンの状態を確認した後、音声認識エンジンの ContinuousRecognitionSession プロパティの StartAsync メソッドを呼び出してセッションを開始します。After checking the state of the speech recognizer, we start the session by calling the StartAsync method of the speech recognizer's ContinuousRecognitionSession property.

if (speechRecognizer.State == SpeechRecognizerState.Idle)
{
  await speechRecognizer.ContinuousRecognitionSession.StartAsync();
}

認識を停止するには、次の 2 つの方法があります。Recognition can be stopped in two ways:

  • StopAsync を使うと、保留中のすべての認識イベントが完了します (ResultGenerated は、保留中のすべての操作が完了するまで、引き続き発生します)。StopAsync lets any pending recognition events complete (ResultGenerated continues to be raised until all pending recognition operations are complete).
  • CancelAsync を使うと、すぐに認識セッションが終了し、保留中の結果はすべて破棄されます。CancelAsync terminates the recognition session immediately and discards any pending results.

音声認識エンジンの状態を確認したら、音声認識エンジンの ContinuousRecognitionSession プロパティの CancelAsync メソッドを呼び出してセッションを停止します。After checking the state of the speech recognizer, we stop the session by calling the CancelAsync method of the speech recognizer's ContinuousRecognitionSession property.

if (speechRecognizer.State != SpeechRecognizerState.Idle)
{
  await speechRecognizer.ContinuousRecognitionSession.CancelAsync();
}

注意

CancelAsync を呼び出した後に ResultGenerated イベントが発生する場合があります。A ResultGenerated event can occur after a call to CancelAsync.
マルチスレッドであるために、CancelAsync を呼び出したときに ResultGenerated イベントがスタックに残っている可能性があります。Because of multithreading, a ResultGenerated event might still remain on the stack when CancelAsync is called. その場合は、ResultGenerated イベントも発生します。If so, the ResultGenerated event still fires.
プライベート フィールドを設定しているときに認識セッションをキャンセルした場合は、その値を常に ResultGenerated ハンドラーで確認してください。If you set any private fields when canceling the recognition session, always confirm their values in the ResultGenerated handler. たとえば、セッションをキャンセルしたときにプライベート フィールドを null に設定している場合はハンドラー内でフィールドが初期化されると想定しないでください。For example, don't assume a field is initialized in your handler if you set them to null when you cancel the session.

 

サンプルSamples