Непрерывная диктовкаContinuous dictation

Узнайте, как записать и распознать длительный непрерывный речевой ввод.Learn how to capture and recognize long-form, continuous dictation speech input.

Важные API-интерфейсы: SpeechContinuousRecognitionSession, ContinuousRecognitionSessionImportant APIs: SpeechContinuousRecognitionSession, ContinuousRecognitionSession

В разделе Распознавание речи вы узнали, как записать и распознать относительно короткий речевой ввод с помощью методов RecognizeAsync или RecognizeWithUIAsync объекта SpeechRecognizer, например при составлении сообщения 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.

Чтобы записывать более длительные сеансы распознавания речи, например диктовку или сообщение электронной почты, используйте свойство ContinuousRecognitionSessionSpeechRecognizer для получения объекта 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. Для компьютеров и ноутбуков поддерживается только 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:

  • экземпляр объекта SpeechRecognizer;An instance of a SpeechRecognizer object.
  • ссылка на диспетчера пользовательского интерфейса для обновления пользовательского интерфейса во время диктовки;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. Ваше приложение должно сохранить ссылку в любом другом месте, если непрерывная диктовка должна продолжиться дальше отдельной XAML-страницы.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, ваше приложение должно использовать диспетчер для обновления пользовательского интерфейса в ответ на события распознавания.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.

Здесь мы объявляем закрытое поле, которое будет инициализировано позже с помощью диспетчера пользовательского интерфейса.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:

  • Получить диспетчер для потока пользовательского интерфейса, если пользовательский интерфейс приложения обновляется в обработчиках событий непрерывных речи.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. Примечание    . Для распознавания речи требуется по крайней мере одно ограничение, определяющее распознаваемый словарь.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. Поскольку события, создаваемые распознавателем речи, возникают в фоновом потоке, создайте ссылку на диспетчер для обновления потока пользовательского интерфейса.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 всегда вызывается в потоке пользовательского интерфейса.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 или RecognizeWithUIAsync.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.

Два события являются особенно важными.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 предоставляет два таких свойства: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. Если значение уверенности равно Medium или выше, мы добавляем текст в StringBuilder.If the value of Confidence is Medium or better, we append the text to the StringBuilder. Также мы обновляем пользовательский интерфейс по мере сбора ввода.We also update the UI as we collect input.

    Примечание    . событие ресултженератед возникает в фоновом потоке, который не может напрямую обновить пользовательский интерфейс.Note  the ResultGenerated event is raised on a background thread that cannot update the UI directly. Если обработчику необходимо обновить пользовательский интерфейс (в качестве [ примера речевого ввода и преобразования речи ] ), необходимо отправить обновления в поток пользовательского интерфейса с помощью метода RunAsync диспетчера.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.

    Примечание    . событие ресултженератед возникает в фоновом потоке, который не может напрямую обновить пользовательский интерфейс.Note  the ResultGenerated event is raised on a background thread that cannot update the UI directly. Если обработчику необходимо обновить пользовательский интерфейс (в качестве [ примера речевого ввода и преобразования речи ] ), необходимо отправить обновления в поток пользовательского интерфейса с помощью метода RunAsync диспетчера.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. Например, сами по себе слова «кот» и «код» неразличимы, пока за счет других слов в предложении или фразе не будет понятен контекст.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 окончательным результатом Result, предоставленным в событии ResultGenerated.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.

После проверки состояния распознавателя речи мы начинаем сеанс, вызвав метод StartAsync свойства ContinuousRecognitionSession распознавателя речи.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();
}

Распознавание может быть остановлено двумя способами: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.

После проверки состояния распознавателя речи мы останавливаем сеанс, вызвав метод CancelAsync свойства ContinuousRecognitionSession распознавателя речи.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();
}

Примечание

Событие ResultGenerated может возникнуть после вызова CancelAsync.A ResultGenerated event can occur after a call to CancelAsync.
Из-за многопоточности событие ResultGenerated может по-прежнему оставаться в стеке при вызове CancelAsync.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