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

Узнайте, как записывать и распознавать длинные и непрерывные входные данные речи диктовки.

Важные API: SpeechContinuousRecognitionSession, ContinuousRecognitionSession

В распознавании речи вы узнали, как записывать и распознавать относительно короткие входные данные речи с помощью методов RecognizeAsync или RecognizeWithUIAsync объекта SpeechRecognizer, например при создании короткого сообщения службы сообщений (SMS) или при запросе вопроса.

Для более длительных сеансов непрерывного распознавания речи, таких как диктовка или электронная почта, используйте свойство ContinuousRecognitionSession для получения объекта SpeechContinuousRecognitionSession.

Примечание.

Поддержка языка диктовки зависит от устройства , на котором работает ваше приложение. Для компьютеров и ноутбуков распознается только en-US, в то время как Xbox и телефоны могут распознавать все языки, поддерживаемые распознаванием речи. Дополнительные сведения см. в разделе "Указание языка распознавателя речи".

Настройка

Вашему приложению требуется несколько объектов для управления сеансом непрерывного диктовки:

  • Экземпляр объекта SpeechRecognizer.
  • Ссылка на диспетчер пользовательского интерфейса для обновления пользовательского интерфейса во время диктовки.
  • Способ отслеживания накопленных слов, произнесенных пользователем.

Здесь мы объявляем экземпляр SpeechRecognizer как частное поле класса code-behind. Приложение должно хранить ссылку в другом месте, если требуется, чтобы непрерывная диктовка сохранялась за пределами одной страницы языка разметки приложений (XAML).

private SpeechRecognizer speechRecognizer;

Во время диктовки распознаватель вызывает события из фонового потока. Так как фоновый поток не может напрямую обновить пользовательский интерфейс в XAML, приложение должно использовать диспетчер для обновления пользовательского интерфейса в ответ на события распознавания.

Здесь мы объявляем частное поле, которое будет инициализировано позже с помощью диспетчера пользовательского интерфейса.

// 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;

Чтобы отслеживать то, что говорит пользователь, необходимо обрабатывать события распознавания, вызванные распознавательом речи. Эти события предоставляют результаты распознавания фрагментов речевых фрагментов пользователей.

Здесь мы используем объект StringBuilder для хранения всех результатов распознавания, полученных во время сеанса. Новые результаты добавляются в StringBuilder по мере их обработки.

private StringBuilder dictatedTextBuilder;

Инициализация

Во время инициализации непрерывного распознавания речи необходимо:

  • При обновлении пользовательского интерфейса диспетчера для потока пользовательского интерфейса в обработчиках событий непрерывного распознавания.
  • Инициализировать распознаватель речи.
  • Скомпилируйте встроенную грамматику диктовки. Распознавание речи за примечание требует по крайней мере одного ограничения для определения распознаваемого словаря. Если ограничение не указано, используется предопределенная грамматика диктовки. См. распознавание речи.
  • Настройте прослушиватели событий для событий распознавания.

В этом примере мы инициализируем распознавание речи на странице OnNavigatedTo.

  1. Так как события, вызванные распознавательом речи, происходят в фоновом потоке, создайте ссылку на диспетчер для обновления потока пользовательского интерфейса. OnNavigatedTo всегда вызывается в потоке пользовательского интерфейса.
this.dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
  1. Затем мы инициализируем экземпляр SpeechRecognizer .
this.speechRecognizer = new SpeechRecognizer();
  1. Затем мы добавим и компилируем грамматику, которая определяет все слова и фразы, которые можно распознать с помощью SpeechRecognizer.

    Если грамматика не указана явно, по умолчанию используется предопределенная грамматика диктовки. Как правило, грамматика по умолчанию лучше подходит для общего диктовки.

    Здесь мы вызываем КомпиляциюConstraintsAsync немедленно без добавления грамматики.

SpeechRecognitionCompilationResult result =
      await speechRecognizer.CompileConstraintsAsync();

Обработка событий распознавания

Вы можете записать одно краткое высказывание или фразу, вызвав Распознаваемую или РаспознаваемуюwithUIAsync.

Однако для записи длительного сеанса непрерывного распознавания мы указываем прослушиватели событий, которые будут выполняться в фоновом режиме, так как пользователь говорит и определяет обработчики для создания строки диктовки.

Затем мы используем свойство ContinuousRecognitionSession нашего распознавателя для получения объекта SpeechContinuousRecognitionSession , который предоставляет методы и события для управления сеансом непрерывного распознавания.

В частности, важны два события:

  • ResultGenerated, которая возникает, когда распознаватель создал некоторые результаты.
  • Завершено, возникающее при завершении сеанса непрерывного распознавания.

Событие ResultGenerated вызывается по мере того, как пользователь говорит. Распознаватель постоянно прослушивает пользователя и периодически вызывает событие, которое передает блок входных данных речи. Необходимо проверить входные данные речи с помощью свойства Result аргумента события и выполнить соответствующее действие в обработчике событий, например добавление текста к объекту StringBuilder.

В качестве экземпляра SpeechRecognitionResult свойство Result полезно для определения того, следует ли принимать входные данные речи. Функция SpeechRecognitionResult предоставляет два свойства для этого:

  • Состояние указывает, успешно ли выполнено распознавание. Распознавание может завершиться ошибкой по различным причинам.
  • Уверенность указывает на относительную уверенность в том, что распознаватель понял правильные слова.

Ниже приведены основные шаги по поддержке непрерывного распознавания:

  1. Здесь мы регистрируем обработчик события непрерывного распознавания ResultGenerated в событии страницы OnNavigatedTo.
speechRecognizer.ContinuousRecognitionSession.ResultGenerated +=
        ContinuousRecognitionSession_ResultGenerated;
  1. Затем мы проверяем свойство Confidence . Если значение достоверности — средний или лучше, мы добавим текст к StringBuilder. Мы также обновляем пользовательский интерфейс по мере сбора входных данных.

    Обратите внимание , что событие ResultGenerated вызывается в фоновом потоке, который не может напрямую обновить пользовательский интерфейс. Если обработчику необходимо обновить пользовательский интерфейс (в качестве примера службы "Речь и TTS"), необходимо отправить обновления в поток пользовательского интерфейса через метод RunAsync диспетчера.

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 , которое указывает конец непрерывной диктовки.

    Сеанс заканчивается при вызове методов StopAsync или CancelAsync (описано в следующем разделе). Сеанс также может завершиться при возникновении ошибки или при остановке речи пользователя. Проверьте свойство Status аргумента события, чтобы определить, почему сеанс закончился (SpeechRecognitionResultStatus).

    Здесь мы регистрируем обработчик события непрерывного распознавания завершенного в событии страницы OnNavigatedTo.

speechRecognizer.ContinuousRecognitionSession.Completed +=
      ContinuousRecognitionSession_Completed;
  1. Обработчик событий проверяет свойство Status, чтобы определить, успешно ли выполнено распознавание. Он также обрабатывает ситуацию, когда пользователь перестал говорить. Часто timeoutExceeded считается успешным распознаванием, так как это означает, что пользователь закончил говорить. Этот случай следует обрабатывать в коде для хорошего опыта.

    Обратите внимание , что событие ResultGenerated вызывается в фоновом потоке, который не может напрямую обновить пользовательский интерфейс. Если обработчику необходимо обновить пользовательский интерфейс (в качестве примера службы "Речь и TTS"), необходимо отправить обновления в поток пользовательского интерфейса через метод RunAsync диспетчера.

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";
            });
          }
        }
      }

Предоставление текущих отзывов о распознавании

Когда люди говорят, они часто полагаются на контекст, чтобы полностью понять, что говорится. Аналогичным образом распознаватель речи часто нуждается в контексте, чтобы обеспечить результаты распознавания высокой достоверности. Например, сами по себе слова "вес" и "ожидание" неотличимы, пока больше контекста не удастся получить от окружающих слов. Пока распознаватель не уверен, что слово или слова были распознаны правильно, он не вызовет событие ResultGenerated .

Это может привести к меньше идеальному интерфейсу для пользователя, так как они продолжают говорить, и никакие результаты не предоставляются, пока распознаватель не имеет достаточной уверенности, чтобы вызвать событие ResultGenerated.

Обработайте событие "ГипотезаGenerated", чтобы улучшить это очевидное отсутствие отклика. Это событие возникает всякий раз, когда распознаватель создает новый набор потенциальных совпадений для обрабатываемого слова. Аргумент события предоставляет свойство Гипотезы , содержащее текущие совпадения. Отображение этих данных пользователю по мере того, как они продолжают говорить и успокаивают их, что обработка по-прежнему активна. После определения достоверности и определения результата распознавания замените промежуточные результаты гипотезы окончательным результатом, предоставленным в событии ResultGenerated.

Здесь мы добавим гипотетический текст и многоточие ("...") к текущему значению выходного текстового поля. Содержимое текстового поля обновляется по мере создания новых гипотез и до тех пор, пока конечные результаты не будут получены из события ResultGenerated.

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;
    });
  }

Запуск и остановка распознавания

Перед началом сеанса распознавания проверьте значение свойства распознавания речи. Распознаватель речи должен находиться в состоянии простоя.

После проверки состояния распознавателя речи мы запустите сеанс, вызвав метод StartAsync свойства ContinuousRecognitionSession распознавателя речи.

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

Распознавание можно остановить двумя способами:

  • StopAsync позволяет завершить все ожидающие события распознавания (ResultGenerated продолжает вызываться до завершения всех ожидающих операций распознавания).
  • CancelAsync немедленно завершает сеанс распознавания и удаляет ожидающие результаты.

После проверки состояния распознавателя речи мы остановим сеанс, вызвав метод CancelAsync свойства ContinuousRecognitionSession распознавателя речи.

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

Примечание.

Событие ResultGenerated может произойти после вызова CancelAsync.
Из-за многопотокового события ResultGenerated могут оставаться в стеке при вызове CancelAsync . Если да, событие ResultGenerated по-прежнему запускается.
Если при отмене сеанса распознавания заданы частные поля, всегда подтвердите их значения в обработчике ResultGenerated . Например, не предполагайте, что поле инициализируется в обработчике, если при отмене сеанса их задано значение NULL.

 

Примеры