Распознование голосовой речи в Windows Phone 8 (speech-to-text)

Помимо синтеза голосовой речи Windows Phone 8 SDK содержит API для распознования голосовой речи и голосовых комманд. В этой статье мы рассмотрим первую часть – каким образом можно распозновать отдельные слова или фразы при помощи данного API.

Чтобы воспользоваться услугами этого API нам необходимо разрешить следующие возможности для нашего WP8 приложения: ID_CAP_NETWORKING, ID_CAP_MICROPHONE, ID_CAP_SPEECH_RECOGNITION.

Разрешение ID_CAP_NETWORKING нужно из-за того, что процесс распознования происходит не на устройстве, а в облаке. Поэтому для пользования этой возможностью вам необходимо иметь подключение к сети.

Список поддерживаемых для распознования языков определен в специальном словаре, который доступен при обращении к свойству InstalledSpeechRecognizers.All. Разместим на странице ListPicker, содержащий все поддерживаемые языки, а также кнопку для запуска распознования текста:

<toolkit:ListPicker x:Name="Recognizers">
  <toolkit:ListPicker.ItemTemplate>
    <DataTemplate>
      <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding DisplayName}"/>
        <TextBlock Text="-" Margin="5,0"/>
        <TextBlock Text="{Binding Language}"/>
      </StackPanel>
    </DataTemplate>
  </toolkit:ListPicker.ItemTemplate>
  <toolkit:ListPicker.FullModeItemTemplate>
    <DataTemplate>
      <StackPanel Margin="0,0,0,20">
        <TextBlock Text="{Binding DisplayName}"/>
        <TextBlock Text="{Binding Language}"/>
      </StackPanel>
    </DataTemplate>
  </toolkit:ListPicker.FullModeItemTemplate>
</toolkit:ListPicker>

<Button Click="OnListenClick">Listen</Button>

Заполним ListPicker информацией о доступных языках:

Recognizers.ItemsSource = InstalledSpeechRecognizers.All;

Простейший код для распознования будет выглядеть вот так:

private async void OnListenClick(object sender, RoutedEventArgs e)
{
  SpeechRecognizerUI recognizer = new SpeechRecognizerUI();
    
  recognizer.Recognizer.SetRecognizer((SpeechRecognizerInformation)Recognizers.SelectedItem);
      
  SpeechRecognitionUIResult result = await recognizer.RecognizeWithUIAsync();
  if (result.ResultStatus == SpeechRecognitionUIStatus.Succeeded)
  {
    MessageBox.Show(result.RecognitionResult.Text);
  }
}

При нажатии на кнопку появится окно операционной системы, указывающее на распознование речи. Это окно имеет ряд настроек, которые можно изменять из кода приложения. Доступны они через свойство Settings объекта SpeechRecognizerUI:

  • ListenText - заголовок окна распознования речи;
  • ExampleText - пример того, что пользователь может сказать устройству (например, "да/нет" на односложный вопрос);
  • ShowConfirmation - устанавливает, необходимо ли отображать подтверждение об успешности распознования (если опция отключена, то приложение должно само взять на себя обязанность об уведомлении пользователя в случае неудачи);
  • ReadoutEnabled - устанавливает, необходимо ли зачитывать фразу после распознования.

Пример кода, в котором задаются параметры диалогового окна распознования:

private async void OnListenClick(object sender, RoutedEventArgs e)
{
  SpeechRecognizerUI recognizer = new SpeechRecognizerUI();
  recognizer.Settings.ExampleText = "Fine";
  recognizer.Settings.ListenText = "How are you?";
  recognizer.Settings.ReadoutEnabled = false;
  recognizer.Settings.ShowConfirmation = false;

  recognizer.Recognizer.SetRecognizer((SpeechRecognizerInformation)Recognizers.SelectedItem);

  SpeechRecognitionUIResult result = await recognizer.RecognizeWithUIAsync();
  if (result.ResultStatus == SpeechRecognitionUIStatus.Succeeded)
  {
    MessageBox.Show(result.RecognitionResult.Text);
  }
}

Если логика приложения не требует отображения системного окна распознования речи можно заменить использование метода RecognizeWithUIAsync на RecognizeAsync, которое доступно через свойство Recognizer.

private async void OnListenWitoutDialogClick(object sender, RoutedEventArgs e)
{
  SpeechRecognizerUI recognizer = new SpeechRecognizerUI();
  recognizer.Settings.ExampleText = "Fine";
  recognizer.Settings.ListenText = "How are you?";
  recognizer.Settings.ReadoutEnabled = false;
  recognizer.Settings.ShowConfirmation = false;

  recognizer.Recognizer.SetRecognizer((SpeechRecognizerInformation)Recognizers.SelectedItem);

  SpeechRecognitionResult result = await recognizer.Recognizer.RecognizeAsync();
  MessageBox.Show(result.Text);
}

Если логика приложения предполагает в качестве результата одну из нескольких заранее предопределенных фраз, то можно определить свой словарь, который будет использоваться при распозновании. Задать собственный словарь можно через свойство Recognizer.Grammars:

SpeechRecognizerUI recognizer = new SpeechRecognizerUI();
// ...
recognizer.Recognizer.Grammars.AddGrammarFromList("MyGrammar", new[] { "fine", "bad" });

SpeechRecognitionUIResult result = await recognizer.RecognizeWithUIAsync();

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