Голосовые команды в Windows Phone 8 (speech-to-text)

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

По умолчанию эта возможность присутствует для всех приложений. Для того, чтобы запустить приложение нужно удерживать аппаратную кнопку Windows и после появления диалога сказать, например: Открыть календарь. Аналогично можно запускать и другие приложения, называя его имя. В большинстве случаев этого достаточно. Тем не менее, разработчики приложений имеют возможность расширить эту функциональность для своего приложения, определяя новые действия при использовании голосовых команд.

Для того, чтобы добавить возможности голосового управления необходимо разрешить следующие возможности: ID_CAP_NETWORKING, ID_CAP_MICROPHONE, ID_CAP_SPEECH_RECOGNITION (как и в случае с простым распознованием речи).

Теперь нам следует определить список команд, которые будет обрабатывать наше приложение. Команда должна содержать имя приложения и последующую фразу для определения необходимого действия. Для того, чтобы добавить обработку команд, необходимо создать словарь команд, который является XML-файлом с определенной схемой. Для создания такого словаря можно воспользоваться готовым шаблоном Voice Command Definition:

<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.0">
  <CommandSet xml:lang="en-US">
    <CommandPrefix>Contoso Rodeo</CommandPrefix>
    <Example> play a new game </Example>

    <Command Name="PlayGame">
      <Example> play a new game </Example>
      <ListenFor> [and] play [a] new game </ListenFor>
      <ListenFor> [and] start [a] new game </ListenFor>
      <Feedback> Starting a new game... </Feedback>
      <Navigate />
    </Command>

    <Command Name="PlayLevel">
      <Example> replay level two </Example>
      <ListenFor> replay level {number} </ListenFor>
      <Feedback> Going to level {number}... </Feedback>
      <Navigate />
    </Command>

    <Command Name="PlayUnknownLevel">
      <Example> replay level two </Example>
      <ListenFor> [and] replay level {*} </ListenFor>
      <Feedback> Unknown level; going to level selection... </Feedback>
      <Navigate Target="LevelSelect.xaml" />
    </Command>

    <PhraseList Label="number">
      <Item> one </Item>
      <Item> two </Item>
      <Item> three </Item>
    </PhraseList>

  </CommandSet>
</VoiceCommands>

Словарь голосовых команд содержит набор элементов CommandSet, каждый из которых описывает соответствующую команду. Элемент CommandSet внутри себя содержит элементы CommandPrefix (фраза, которая произносится перед командой, обычно это – имя приложения), Example (фраза, которая отображается в подсказке) и Command (содержит описание команды). Элемент Command – самый важный, в нем описывается структура голосовой команды. Внутри этого элемента присутствуют элементы Example (подсказка), ListenFor (фраза команды), Feedback (фраза, которая отображается пользователю, когда команда выполняется) и Navigate (адрес страницы, которая будет отображаться, если нужно запускать приложение не с главной страницы).

Элемент ListenFor определяет фразу, которую нужно произнести для выполнения команды. Таких фраз может быть несколько.

Содержимое элемента ListenFor имеет свои особенности. Во-первых, можно определять необязательные слова в фразе. Такие слова заключаются в квадратные скобки. Например, запись [with] show text означает, что слово with может быть произнесено, а может быть и пропущено.

Другой особенностью элемента ListenFor является то, что в конкретном месте фразы мы можем определить словарь допустимых слов. Для этого в тексте команды вставляется имя словаря, заключенного в фигурные скобки {number}. При этом, после элемента Command, мы должны определить элемент PhraseList, где будут указаны допустимые значения.

<Command ...>
  <!-- ... -->
</Command>

<PhraseList Label="number">
  <Item> one </Item>
  <Item> two </Item>
  <Item> three </Item>
</PhraseList>

При необходимости мы можем изменить содержимое этого словаря из кода:

await VoiceCommandService.InstalledCommandSets["myCommandSet"].UpdatePhraseListAsync("number", new[] { "first", "second" });

В данном случае мы выбираем из всех наборов команд (CommandSets) набор с именем myCommandSet. Чтобы задать это имя, необходимо указать атрибут Name в XML-словаре голосовых команд для элемента CommandSet:

<CommandSet xml:lang="en-US" Name="myCommandSet">

Метод UpdatePhraseListAsync выполняет обновление словаря возможных фраз для выбранного CommandSet, при это имя словаря задается первым параметром этого метода.

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

private async void InitializeVoiceCommands()
{
  if (VoiceCommandService.InstalledCommandSets.Any() == false)
  {
    await VoiceCommandService.InstallCommandSetsFromFileAsync(new System.Uri(@"ms-appx:///VoiceCommandDefinition1.xml"));
  }
}

Вызов этого метода можно добавить, например, в метод InitializePhoneApplication, который находится в файле App.xaml.cs. Теперь после первого запуска, можно запускать приложение, используя описанные в словаре команды. Для того, чтобы обработать конкретную команду, можно переопределить метод страницы OnNavigatedTo, при вызове которого прочитать содержимое свойства NavigationContext.QueryString, где и будет находиться обработанная информация.