Поиск на сайте: Расширенный поиск


Новые программы oszone.net Читать ленту новостей RSS
CheckBootSpeed - это диагностический пакет на основе скриптов PowerShell, создающий отчет о скорости загрузки Windows 7 ...
Вы когда-нибудь хотели создать установочный диск Windows, который бы автоматически установил систему, не задавая вопросо...
Если после установки Windows XP у вас перестала загружаться Windows Vista или Windows 7, вам необходимо восстановить заг...
Программа подготовки документов и ведения учетных и отчетных данных по командировкам. Используются формы, утвержденные п...
Red Button – это мощная утилита для оптимизации и очистки всех актуальных клиентских версий операционной системы Windows...
OSzone.net Microsoft Разработка приложений Windows Phone Включение поддержки голосовых команд в приложение Windows Phone 8. Часть 2. Диалог внутри приложения RSS

Включение поддержки голосовых команд в приложение Windows Phone 8. Часть 2. Диалог внутри приложения

Текущий рейтинг: 3 (проголосовало 1)
 Посетителей: 1218 | Просмотров: 1538 (сегодня 0)  Шрифт: - +

В первой части статьи в прошлом месяце я рассказал о поддержке голосовых команд в приложении Windows Phone 8. Теперь мы рассмотрим диалог с пользователем в выполняемом приложении с применением голосового ввода и вывода.

Как только приложение запущено, во многих сценариях можно получить выигрыш от взаимодействия пользователя со смартфоном через голосовой ввод и вывод. Один из естественных сценариев — диалог внутри приложения. Например, пользователь может запустить программу Magic Memo (см. предыдущую статью), чтобы попасть на главную страницу, а затем с помощью средств распознавания речи ввести новую заметку, получить голосовой ответ и подтвердить изменения. Если предположить отсутствие случаев неправильного распознавания, то пользователь может полностью ввести и сохранить несколько заметок, не дотрагиваясь до смартфона (кроме первого длительного удерживания кнопки Start).

Можно представить множество других сценариев с использованием речевого диалога, запускаемого в приложении. Так, после перехода на страницу со списком избранного (заметок, фильмов или других элементов) пользователь мог бы выбрать голосом один из элементов, а потом отдать подходящую команду: редактировать, воспроизвести, заказать, удалить и прочее. Механизм голосового вывода сообщал бы о выбранном элементе и запрашивал бы подтверждение.

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

Взаимодействие с пользователем: API синтеза речи

Генерируемый компьютером голосовой вывод называют то преобразованием текста в речь (text to speech, TTS), то синтезом речи (хотя, строго говоря, TTS — понятие более широкое, чем синтез речи). Наиболее распространенные области применения включают уведомления и подтверждения, но эта функциональность важна и во многих других случаях, например в «читалках» и средствах чтения текста с экрана.

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

// Создаем экземпляр синтезатора речи
private SpeechSynthesizer speechOutput =
  new SpeechSynthesizer();
// ...
// Закрытый метод для получения новой заметки
private async void GetNewMemoByVoice()
{
  await speechOutput.SpeakTextAsync("Say your memo");
  // Остальной код для получения новой заметки
}

Когда пользователь касается кнопки микрофона, он слышит приглашение «Say your memo», воспроизводимое текущим аудиоустройством. В следующих разделах я расширю этот пример, добавляя код, который принимает пользовательский ввод через механизм распознавания речи.

TTS-средства для сложных сценариев В приложениях, полагающихся на речевой вывод, возможны ситуации, требующие изменения громкости, тональности или скорости речи в процессе голосового вывода. Для таких сложных случаев существует два дополнительных метода: SpeakSsmlAsync и SpeakSsmlFromUriAsync. В этих методах предполагается, что ввод соответствует формату Speech Synthesis Markup Language (SSML) — стандарту W3C XML для встраивания свойств звука и синтезатора в произносимый текст. Я не включил пример кода для SSML в эту статью или в приложение Magic Memo, но вы можете узнать больше о SSML в справочной статье MSDN Library по ссылке bit.ly/QwWLsu (или в спецификации W3C по ссылке bit.ly/V4DlgG).

В классе синтезатора есть события SpeakStarted и BookmarkReached, а также перегруженные версии для каждого метода Speak, принимающего обобщенный объект состояния в качестве второго параметра, чтобы вам было легче отслеживать, какой из экземпляров метода Speak сгенерировал конкретное событие. Используя SSML и обработку событий, ваш код может поддерживать такие возможности, как выделение произносимого текста или перезапуск вызова Speak посреди абзаца.

Голосовой ввод: API распознавания речи

Две широких категории сценариев распознавания речи в приложении — ввод текста, а также команды и управление. В первом случае (ввод текста) приложение просто захватывает фрагмент активной речи (utterance) пользователя как текст; это полезно, когда пользователь мог бы говорить почти что угодно, как в функции «новая заметка» в примере кода.

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

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

На рис. 1 показан метод GetNewMemoByVoice, представленный ранее, но теперь в него добавлены строки для инициализации объекта распознавателя, запуска сеанса распознавания и обработки результата.

Рис. 1. Инициализация объекта распознавателя, запуск сеанса распознавания и обработка результата

private SpeechRecognizerUI speechInput =
  new SpeechRecognizerUI();
// Указываем отображать распознаваемый текст
speechInput.Settings.ExampleText =
  "Example: \"Buy roses\"";
speechInput.Settings.ListenText = "Say your memo";
// ...
// Закрытый метод для получения новой заметки
private async void GetNewMemoByVoice()
{
  await speechOutput.SpeakTextAsync("Say your memo"); // TTS-приглашение
  var recoResult =
     await speechInput.RecognizeWithUIAsync();
    // Используем грамматическую систему Dictation по умолчанию
  Memo_TB.Text =
    recoResult.RecognitionResult.Text; // Что-то делаем с результатом
}

Конечно, в реальном коде все не так просто, и, если вы посмотрите пример Magic Memo, вы увидите блок try/catch и проверку на успешное распознавание.

Если вы опробуете это в приложении-примере, коснувшись значка микрофона, то заметите, что после того, как вы надиктовали свою заметку, появляется экран «thinking», потом выводится UI подтверждения, а затем подтвержденный результат вставляется в текстовое окно заметки. При этом «за кулисами» происходит много чего, в том числе используется «грамматическая система» на удаленном сервере для распознавания вашей речи. Грамматическая система (grammar) — это фактически набор правил, указывающих, какие лексические элементы («слова») должен распознавать механизм и в каком порядке. В следующих разделах я исследую API распознавания речи и поясню, как он используется с грамматическими системами, применяемыми в распознавании.

Обзор API распознавания речи Теперь я дам высокоуровневый обзор классов в этом API и их ролей. На рис. 2 показана базовая схема API. Первым делом обратите внимание на то, что в названиях двух блоков встречается «SpeechRecognizer».

*
Рис. 2. Обзор архитектуры API распознавания речи

SpeechRecognizerUISpeechRecognizerUI
SpeechRecognizer objectОбъект SpeechRecognizer
UI Settings object: UI text, Booleans to disable featuresОбъект параметров UI: текст UI, булевы параметры для отключения функций
Recognition method: RecognizeWithUIAsyncМетод распознавания: RecognizeWithUIAsync
Settings object: timeout values and moreОбъект Settings: значения времени ожидания и др.
Grammars collection indexed by grammar nameНабор Grammars, индексированный по названиям грамматических систем
Methods: PreLoadGrammarAsync Get/Set Recognizer RecognizeAsyncМетоды: PreLoadGrammarAsync, Get/Set Recognizer, RecognizeAsync
AddGrammar methods: Predefined List SRGSМетоды AddGrammar: предопределенные, список, SRGS


Если в вашем приложении не требуется отображать UI с распознанным голосовым вводом или если вы хотите показывать собственный UI, вы должны создать экземпляр класса SpeechRecognizer, показанного в середине слева на рис. 2. Считайте этот объект базовой операционной единицей распознавания речи в этом API. Именно здесь приложение добавляет любые необходимые ему грамматические системы. После инициализации вы вызываете RecognizeAsync для выполнения реального распознавания. Поскольку SpeechRecognizer реализует IAsyncOperation<SpeechRecognitionResult>, состояние объект результата доступны через функцию обратного вызова Completed. Таким образом, в этом API нет отдельных событий для завершенного или отклоненного распознавания, как в других управляемых речевых API.

Как и предполагает его имя, класс SpeechRecognizerUI верхнего уровня обеспечивает распознавание речи с помощью GUI по умолчанию, который согласуется с глобальным речевым UI смартфона, предназначенным для обратной связи, устранения неоднозначности и подтверждения. Для совместимости с глобальным речевым UI и упрощения кодирования большинство приложений должно использовать этот класс, а не ранее упомянутый класс без UI. Создавая экземпляр объекта SpeechRecognizerUI, вы автоматически получаете еще два важных объекта: Settings (где задается UI-текст, выводимый пользователю) и SpeechRecognizer (где можно указать грамматические системы, как описывается в следующих разделах). После инициализации вы должны вызвать RecognizeWithUIAsync родительского объекта SpeechRecognizerUI, чтобы запустить сеанс распознавания. Если же вы используете RecognizeAsync дочернего объекта SpeechRecognizer, он будет выполнять распознавание так, будто объект SpeechRecognizer используется автономно, т. е. без UI. Следовательно, термины SpeechRecognizer и RecognizeAsync следует понимать как обобщенные названия объектов и методов с UI и без.

Этапы использования распознавания речи Этот процесс в приложении Windows Phone 8 состоит из четырех базовых этапов.

  1. Создание грамматических систем, применяемых в ходе распознавания речи (не требуется при использовании предопределенной грамматической системы).
  2. Инициализация объекта SpeechRecognizer установкой свойств и добавлением грамматических систем, если это нужно.
  3. Запуск сеанса распознавания вызовом SpeechRecognizer.RecognizeAsync или SpeechRecognizerUI.RecognizeWithUIAsync.
  4. Обработки результата распознавания и выполнения соответствующего действия.

На рис. 1 показаны все эти этапы, кроме первого — создания грамматических систем. Предопределенная грамматическая система Dictation используется по умолчанию, поэтому ее нет нужды создавать или добавлять в набор Grammars.

Код, реализующий эти этапы, в основном зависит от типа грамматической системы, применяемой при распознавании речи. В следующем разделе описываются концепция и использование грамматических систем распознавания речи в Windows Phone 8.

Введение в грамматические системы распознавания речи

Все современные механизмы распознавания речи используют грамматические системы для ограничения набора фраз, в котором эти механизмы должны осуществлять поиск (с этого момента я буду называть их пространством поиска), чтобы находить совпадение с фрагментом активной речи пользователя и тем самым повышать точность распознавания. Правила грамматической системы могут обеспечивать распознавание фраз просто по списку или по гораздо более сложному общему разговорному тексту (general conversational text).

В речевом API в Windows Phone 8 вы можете указывать грамматическую систему тремя способами, как описывается в следующих разделах. В каждом случае вы добавляете грамматическую систему в набор Grammars объекта SpeechRecognizer.

Простая списочная грамматическая система Самый легкий способ указать собственную грамматическую систему для какого-либо приложения — предоставить список всех фраз, которые должен слушать механизм распознавания, в виде простого массива строк. Эти списочные грамматические системы обрабатываются аппаратным механизмом распознавания речи. Код, необходимый для создания и добавления списочной грамматической системы, может быть очень простым, как в примере ниже, где предполагается распознавание статического списка названий кнопок:

commandReco.Recognizer.Grammars.AddGrammarFromList(
  "mainPageCommands", new string[] { "cancel", "save", "quit" });

В примере Magic Memo делается не так просто: список фраз формируется поиском атрибута Content всех кнопок на странице и добавлением текста контента в список строк. Детали см. в методе InitCommandGrammar в файле MainPage.xaml.cs.

Чтобы обработать результат сеанса распознавания с помощью списочной грамматической системы, вы считываете свойство Text в SpeechRecognitionUIResult (или SpeechRecognitionResult при использовании версии без UI). Это можно было бы делать, например, в выражении switch, как показано на рис. 3.

Рис. 3. Обработка результата сеанса распознавания

switch (result.RecognitionResult.Text.ToLower())
{
  case "cancel":
  // Код отмены
    break;
  case "save":
  // Код сохранения заметки
    break;
  case "quit":
    break;
  default:
    break;
}

Более подробный пример вы найдете в обратном вызове CommandCompleted в MainPage.xaml.cs.

Предопределенная грамматическая система Речевой API в Windows Phone 8 предоставляет две предопределенные грамматические системы: Dictation и WebSearch. Dictation также называется Short Message Dictation и использует ту же грамматическую систему, что и встроенное приложение Texting. Однако WebSearch, напротив, оптимизирована под фразы, применяемые при онлайновом поиске. Эту грамматику использует встроенная команда Find/Search.

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

Основное преимущество предопределенных грамматических систем в том, что их легко реализовать в приложении. Например, чтобы в коде на рис. 1 задействовать грамматическую систему WebSearch вместо Dictation по умолчанию, вы просто добавляете строку перед вызовом RecognizeWithUIAsync:

speechInput.Recognizer.Grammars.AddGrammarFromPredefinedType(
  "webSearch", SpeechPredefinedGrammar.WebSearch);

Результат распознавания от предопределенной грамматической системы обрабатывается с помощью свойства Text результата, как показано на рис. 1.

Грамматические системы в формате Speech Recognition Grammar Specification (SRGS) SRGS — стандарт W3C в формате XML. Подробные сведения об этом формате и использовании см. в статье MSDN Library «SRGS Grammar XML Reference» по ссылке bit.ly/SYnAu5, в спецификации W3C по ссылке bit.ly/V4DNeS или в любых учебных ресурсах, которые вы найдете поиском по «SRGS grammar». Грамматические системы SRGS предлагают богатую функциональность, например возможность указывать дополнительные элементы и повторять элементы, правила, ссылки правила, специальные правила и семантики, ценой дополнительных усилий в создании, тестировании и отладке грамматической системы. В Windows Phone 8 грамматические системы SRGS применяются только локальным механизмом распознавания в смартфоне, а не удаленным сервисом.

Чтобы добавить грамматическую систему SRGS, вы ссылаетесь на URI файла этой системы в пути установки приложения:

commandReco.Recognizer.Grammars.AddGrammarFromUri(
  "srgsCommands", new Uri("ms-appx:///ViewMemos.grxml"));

Одно из крупных преимуществ грамматических систем SRGS в том, что они позволяют указывать семантические значения для упрощения обработки широкого диапазона ответов пользователя без обращения к распознанному фрагменту активной речи (доступному, как всегда, через свойство RecognitionResult.Text).

Семантики SRGS являются объектами (на практике зачастую строками), которые вы присваиваете переменным в своей грамматической системе SRGS с помощью элемента <tag> и подмножества ECMAScript. Они дают два преимущества перед использованием распознанного текста напрямую.

  1. Упрощенная обработка Вы можете определять намерение пользователя без разбора распознанного текста, который может иметь один и тот же смысл в разных формах. Например, с помощью семантик можно сопоставить все утвердительные фрагменты активной речи («yes», «yup», «affirmative», «OK» или «ya») с одним семантическим значением «yes».
  2. Легкость локализации Вы можете использовать один и тот же отделенный код (codebehind) для обработки фрагментов активной речи, произносимых на любом поддерживаемом языке, если применяете единообразный набор семантических значений во всех языках.

Для иллюстрации этих концепций в примере Magic Memo используется единственная грамматическая система ViewMemos.grxml для управления страницей ViewMemos.xaml; фрагменты кода из этого файла грамматики с семантическими тегами показаны на рис. 4. Функция micImage_Tap в ViewMemos.xaml.cs (см. фрагмент на рис. 5) демонстрирует применение семантических значений в сопоставлении фрагмента активной речи пользователя с неким действием.

Рис. 4. Фрагменты из грамматической системы SRGS в ViewMemos.grxml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE grammar PUBLIC "-//W3C//DTD GRAMMAR 1.0//EN"
  "http://www.w3.org/TR/speech-grammar/grammar.dtd">
<!-- язык грамматики по умолчанию - US English -->
<grammar xmlns="http://www.w3.org/2001/06/grammar"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.w3.org/2001/06/grammar
    http://www.w3.org/TR/speech-grammar/grammar.xsd"
  xml:lang="en-US" version="1.0" tag-format="semantics/1.0"
    root="buttons">
  <rule id="buttons" scope="public">
    <one-of>
      <!-- Семантика 'process' может быть одной из 'clear',
        'save', 'new' или 'select' -->
      <item>
        <!-- Ссылка на внутреннее правило "scope" ниже -->
        Clear <ruleref uri="#scope" type="application/srgs+xml"/>
        <tag>out.process="clear"; out.num = rules.latest();</tag>
      </item>
      <item>
        Save
        <item repeat="0-1">changes</item>
        <tag>out.process="save";</tag>
      </item>
      <item>
        Enter new
        <tag>out.process="new";</tag>
      </item>
      <item>
        Select
        <item repeat="0-1">memo</item> <!-- доп. слова -->
        <item repeat="0-1">number</item>
        <!-- Ссылка на внутреннее правило "number" ниже -->
        <ruleref uri="#number" type="application/srgs+xml"/>
        <tag>out.process="select";out.num =
          rules.latest();</tag>
      </item>
    </one-of>
  </rule>
  <rule id="scope" scope="private">
    <one-of> <!-- может быть "all", "selected" или числом
      из правила 'number' -->
      <item>
        all <tag>out.scope="all";</tag>
      </item>
      <item>
        selected <tag>out.scope="selected";</tag>
      </item>      <item>
        <item repeat="0-1">memo</item> <!-- доп. слова -->
        <item repeat="0-1">number</item>
        <ruleref uri="#number" type="application/srgs+xml"/>
      </item>
    </one-of>
  </rule>
 <rule id="number" scope="public">
      <item>
        1
      </item>
    <!-- См. в ViewMemos.grxml остальные элементы
      в этом блоке -->
  </rule>
</grammar>

Рис. 5. Обработка результата распознавания с помощью семантических свойств

// Обработчик касания micImage, фрагмент из ViewMemos.xaml.cs
private async void micImage_Tap(object sender, GestureEventArgs e)
{
  var commandResult = await commandReco.RecognizeWithUIAsync();
  if (commandResult.ResultStatus ==
    SpeechRecognitionUIStatus.Succeeded)
  {
    var commandSemantics = commandResult.RecognitionResult.Semantics;
    SemanticProperty process = null;
    if (commandSemantics.TryGetValue("process", out process))
    {
      // В принципе, семантическим свойством может быть
      // любой объект, но в данном случае это строка
      switch (process.Value as string)
      {
        // Для этого грамматической системы семантика "process"
        // более-менее соответствует кнопку на странице
        case "select":
        // Команда была "Select memo number 'num'"
          break;
        case "clear":
        // Команда была "Clear memo number 'num,'", "Clear all"
        // или "Clear Selected"
          break;
        case "save":
        // Команда была "Save" или "Save Changes"
          break;
        case "new":
        // Команда была "Enter new"
          break;
        default:
          break;
      }
    }
  }
}

Этот пример лишь поверхностно демонстрирует то, что возможно с помощью семантик. Чтобы узнать больше, начните со статьи в MSDN Library «Using the tag Element» по ссылке bit.ly/PA80Wp. Стандарт W3C для семантик вы найдете по ссылке bit.ly/RyqJxc.

Вы можете опробовать эту грамматическую систему в примере Magic Memo, перейдя на страницу ViewMemos и коснувшись значка микрофона. Отделенный код размещен в файле ViewMemos.xaml.cs, в том числе код в разделе #define, который вы можете активировать (используя #define SemanticsDebug), чтобы отображать и отлаживать семантические значения, возвращаемые в результате распознавания.

Применение нескольких грамматических систем в одном объекте распознавателя К этому моменту напрашивается естественный вопрос насчет того, можно ли использовать в объекте SpeechRecognizer более одной грамматической системы. Ответ — да, но с ограничениями. Вот некоторые правила и методы кодирования при использовании нескольких грамматических систем.

  1. Если вы добавляете предопределенную грамматическую систему, то не можете добавлять никакие другие грамматические системы. Кроме того, предопределенную грамматическую систему нельзя отключить; это единственная грамматическая система, сопоставленная с этим объектом распознавателя на весь срок его существования.
  2. Вы можете добавлять несколько собственных грамматических систем (списочных и SRGS) в один объект распознавателя и включать/отключать их по мере необходимости для разных ситуаций в своем приложении:
    1. чтобы обратиться к определенной грамматической системе, используйте ее имя (строковый параметр, переданный при вызове метода AddGrammar) как ключ в наборе Grammars;
    2. чтобы включить/отключить определенную грамматическую систему, установите ее булево свойство Enabled в true или false. Например, следующий код отключит грамматическую систему с именем buttonNames:
      myRecognizer.Grammars["buttonNames"].Enabled = false;
  3. При вызове любого из методов AddGrammar грамматическая система помещается в очередь, где ожидает обработки, но не разбирается и не загружается. Грамматическая система компилируется и загружается при первом вызове RecognizeAsync или при необязательном вызове PreLoadGrammarsAsync. Вызов последнего метода до реального использования может уменьшить задержку в возврате результата из RecognizeAsync и поэтому рекомендуется к применению в большинстве случаев.

Еще одно «революционное приложение»

Windows Phone 8 представляет, наряду с другими возможностями, первую полностью функциональную платформу разработки для поддержки речевых средств с применением как аппаратных, так и удаленных сервисов распознавания. Используя голосовые команды и диалог внутри приложения, вы можете открыть для своей программы такие области применения, которые приведут в восторг ваших пользователей. Благодаря речевым средствам она вполне может стать еще одним «революционным приложением» в Marketplace.

Автор: Эвери Бишоп  •  Иcточник: MSDN Magazine  •  Опубликована: 03.04.2013
Нашли ошибку в тексте? Сообщите о ней автору: выделите мышкой и нажмите CTRL + ENTER
Теги:   Windows Phone 8.


Оценить статью:
Вверх
Комментарии посетителей
Комментарии отключены. С вопросами по статьям обращайтесь в форум.