Este artigo foi traduzido por máquina.

Windows Phone

Habilitação da fala em um aplicativo do Windows Phone 8, parte 2: Caixa de diálogo no aplicativo

F Avery Avery

Baixar o código de exemplo

No mês passado, na parte 1 (msdn.microsoft.com/magazine/jj721592) desta série de duas partes, discutido que permite comandos de voz em um aplicativo do Windows Phone 8. Aqui, falarei sobre diálogo com o usuário em um aplicativo de execução usando o discurso de entrada e saída.

Uma vez que um aplicativo foi lançado, muitos cenários podem beneficiar da interação entre o usuário e o telefone usando o discurso de entrada e saída. Um natural é na app-diálogo. Por exemplo, o usuário pode iniciar o aplicativo de magia Memo (Ver artigo anterior) para ir para a página principal e, em seguida, usar o reconhecimento de fala para inserir um novo memorando, receber feedback áudio e confirmar as alterações. Supondo que não há equívocos, o usuário pode completamente entrar e salvar vários memorandos sem tocar o telefone (excepto o primeiro longo empurre o botão de Start).

Você pode imaginar muitos outros cenários usando o diálogo de discurso, começando no app. Por exemplo, uma vez que o usuário navegou para uma página que mostra uma lista de favoritos guardados como memorandos, filmes ou recordações, ela poderia usar reconhecimento para escolher um e tomar uma ação: editar, tocar, ordem, remover, e assim por diante. Saída de discurso seria então ler a seleção de volta e pedir a confirmação.

Nas seções a seguir eu vou expor exemplos usando o discurso para entrada e saída, começando com exemplos simples e trabalhando até exemplos mais complexos. Eu vou mostrar como é fácil implementar os casos simples e mostrar algumas das funcionalidades mais rica disponível para cenários avançados.

Comunicando-se para o usuário: Síntese de voz API

Saída de voz gerada por computador é chamada vària texto para fala (TTS) ou síntese de fala (embora estritamente falando, TTS abrange mais do que a síntese de fala). Usos comuns incluem notificação e confirmação, como mencionado anteriormente, mas também é essencial para outros casos de uso como leitores ou leitores de tela.

Um exemplo simples de síntese de fala em sua forma mais simples, seu aplicativo pode traduzir uma seqüência de caracteres de texto para áudio falado em apenas duas linhas de código. Aqui está um exemplo usando o código extraído da amostra de magia Memo:

// Instantiate a speech synthesizer
private SpeechSynthesizer speechOutput = 
  new SpeechSynthesizer();
// ...
// Private method to get a new memo
private async void GetNewMemoByVoice()
{
  await speechOutput.SpeakTextAsync("Say your memo");
  // Other code for capturing a new memo
}

Quando o usuário toques no botão do microfone, ela vai ouvir "Dizer o memorando" falado do atual dispositivo de áudio. Nas seções a seguir eu vou expandir este exemplo adicionando código que aceita entrada do usuário usando o reconhecimento de fala.

Recursos de TTS para cenários avançados aplicativos que dependem muito da saída de discurso podem ter casos de uso que exigem alterar o volume, densidade ou taxa de língua durante a fala de saída. Para cobrir essas avançadas casos, existem dois métodos adicionais: SpeakSsmlAsync e SpeakSsmlFromUriAsync. Esses métodos presumem que a entrada é no formato de linguagem de marcação de síntese de fala (SSML), uma World Wide Web Consortium (W3C) XML padrão para a incorporação de propriedades do áudio e o mecanismo de sintetizador no texto para ser falado. Não incluí código de amostra para SSML neste artigo ou o download de código memorando de magia, mas você pode descobrir mais sobre SSML no artigo de referência da biblioteca MSDN em bit.ly/QwWLsu (ou a especificação do W3C em bit.ly/V4DlgG).

A classe de sintetizador também tem eventos para SpeakStarted e BookmarkReached, e há sobrecargas para cada método de falar que levam a um objeto de estado genérico como um segundo parâmetro para ajudá-lo a manter o controle de qual instância do método Speak gerado um evento específico. Usando SSML e manipulando os eventos, seu código pode fornecer recursos como realce de texto falado ou reiniciar uma chamada de voz no meio de um parágrafo.

Entrada de fala: API de reconhecimento de fala

As duas grandes classes de casos de uso para reconhecimento de fala em um app são a entrada de texto e comando e controle. No primeiro caso de uso, entrada de texto, o aplicativo simplesmente captura enunciado do usuário como texto; Isso é útil quando o usuário poderia dizer quase nada, como a "nova nota" recurso de código de exemplo.

No segundo caso de uso, comando e controle, o usuário manipula o app por enunciado falado em vez de bater os botões ou deslizando o dedo no rosto do telefone. Este caso de uso é especialmente útil em cenários de mãos-livres, como dirigir ou cozinhar.

Um exemplo simples de reconhecimento de fala antes de entrar em detalhes sobre os recursos de reconhecimento de fala em um app, vamos dar uma olhada no caso mais simples: texto de entrada em algumas linhas de código.

Figura 1 mostra o GetNewMemo­ByVoice método mostrado anteriormente, mas com linhas adicionadas para inicializar um objeto reconhecedor, inicie uma sessão de reconhecimento e manipular o resultado.

Figura 1 inicializar um objeto reconhecedor, iniciar uma sessão de reconhecimento e manipulação do resultado

private SpeechRecognizerUI speechInput = 
  new SpeechRecognizerUI();
// Set text to display to the user when recognizing
speechInput.Settings.ExampleText = 
  "Example: \"Buy roses\"";
speechInput.Settings.ListenText = "Say your memo";
// ...
// Private method to get a new memo
private async void GetNewMemoByVoice()
{
  await speechOutput.SpeakTextAsync("Say your memo"); // TTS prompt
  var recoResult =
    await speechInput.RecognizeWithUIAsync();
      // Uses default Dictation grammar
  Memo_TB.Text =
    recoResult.RecognitionResult.Text; // Do something with the result
}

Naturalmente, em código real nunca é tão simples quanto isso, e se você olhar no exemplo de memorando de magia, você verá um bloco try/catch e um cheque para o reconhecimento do sucesso.

Se você tentar fazer isso no aplicativo de exemplo batendo o ícone do microfone, você vai notar que depois que você falou o memorando, uma tela de "pensamento" aparece, seguido por uma confirmação da interface do usuário, após o qual o resultado é inserido na caixa de texto do memorando. Nos bastidores, que muita coisa está acontecendo, não menos do que é o uso de uma "gramática" em um servidor remoto para reconhecer sua fala. Uma gramática é essencialmente um conjunto de regras que especificam quais entradas lexicais ("palavras") o motor precisa reconhecer e em que ordem. Nas próximas seções, explorarei o API de reconhecimento de fala e como ele é usado com gramáticas de reconhecimento.

Visão geral da API de reconhecimento de fala antes de eu entrar em detalhes de codificação para reconhecimento de fala, vamos dar uma olhada de alto nível em classes da API e seus papéis. Figura 2 mostra o layout básico da API. A primeira coisa que você notará é que as duas caixas têm discurso­reconhecedor no nome.


Visão geral do Design de API de reconhecimento de fala Figura 2

Se seu aplicativo não precisa exibir um interface do usuário com o reconhecimento de fala, ou se você deseja exibir seu próprio interface do usuário personalizada, você deve criar uma cópia da classe SpeechRecognizer mostrado no canto esquerdo médio de Figura 2. Acho que deste objeto como base operacional unidade de reconhecimento de voz dentro desta API. Isto é onde o app adiciona qualquer gramáticas exige. Após a inicialização, você pode chamar RecognizeAsync para fazer o reconhecimento real. Porque SpeechRecognizer implementa IAsyncOperation <SpeechRecognitionResult>, status e um objeto de resultado estão disponíveis na função de retorno de chamada concluída. Assim, não há nenhum eventos separados para reconhecimento concluído ou rejeitado como em outra fala gerenciada APIs.

Como o nome implica, a classe de SpeechRecognizerUI nível superior fornece reconhecimento de fala com um GUI padrão que é consistente com o discurso global do telefone UI para feedback, desambiguação e confirmação. Para manter a compatibilidade com o discurso global da interface do usuário e simplificar a codificação, a maioria dos aplicativos devem usar essa classe, em vez da classe de interface de usuário não mencionado anteriormente. Quando você instancia um objeto SpeechRecognizerUI, ele vem com dois objetos importantes: um objeto de configurações, onde você definir o texto de interface do usuário para exibir para o usuário; e um objeto SpeechRecognizer, onde você pode especificar gramáticas conforme descrito nas seções a seguir. Uma vez inicializado, você deve chamar RecognizeWithUIAsync no objeto pai SpeechRecognizerUI para iniciar uma sessão de reconhecimento. Se você usar RecognizeAsync no objeto SpeechRecognizer filho, ele vai reconhecer como se o objeto SpeechRecognizer estavam sendo usado de forma autônoma, ou seja, sem uma interface de usuário. Daqui em diante, os termos SpeechRecognizer e reconhecer­Async são compreendidos para ser referências genéricas para os objetos e métodos com e sem uma interface de usuário, conforme o caso.

Passos para reconhecimento de fala usando existem quatro etapas básicas para usar o reconhecimento de fala em um aplicativo do Windows Phone 8:

  1. Crie gramáticas para ser usado no processo de reconhecimento (não necessário se usando uma gramática predefinida).
  2. Inicialize o objeto SpeechRecognizer definindo propriedades e adicionando gramáticas conforme necessário.
  3. Iniciar a sessão de reconhecimento, chamando o discurso­Recognizer.RecognizeAsync ou SpeechRecognizer­- interface do usuário.RecognizeWithUIAsync.
  4. Processar o resultado do reconhecimento e tomar a ação apropriada.

Figura 1 mostra todas essas etapas exceto n º 1, Criar gramáticas. A gramática de ditado predefinida é a gramática padrão, então não há nenhuma necessidade de criar ou adicioná-lo para a coleção de gramáticas.

O código para implementar estas etapas em grande parte depende do tipo de gramática usado no reconhecimento de fala. A próxima seção descreve o conceito e o uso das gramáticas de reconhecimento de fala no Windows Phone 8.

Introdução para gramáticas de reconhecimento de fala

Reconhecimento de fala modernos motores todos usam gramáticas para restringir o conjunto de frases, através do qual o mecanismo de reconhecimento deve procurar (doravante chamado o espaço de"busca") para localizar uma correspondência ao enunciado do usuário e, assim, melhorar a precisão do reconhecimento. Regras gramaticais podem permitir o reconhecimento das frases tão simples como uma lista de números ou tão complexo como o texto de conversação geral.

Na API de fala do Windows Phone 8 você pode especificar uma gramática de três formas, conforme descrito nas seções a seguir. Para cada caso, você pode adicionar a gramática para uma coleção de gramáticas no objeto SpeechRecognizer.

Simples lista de gramática a maneira mais fácil para especificar uma gramática personalizada para um aplicativo é fornecer uma lista de todas as frases, para o qual o reconhecedor deve ouvir em uma matriz de cadeia de caracteres simples. Estas gramáticas de lista são manipuladas pelo mecanismo de reconhecimento de fala no dispositivo. O código para criar e adicionar uma gramática de lista pode ser tão simples como o seguinte para uma lista de nomes de botão reconhecer contra estática:

 

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

O exemplo de memorando de magia faz algo um pouco mais sofisticado: Baseia-se a lista de frases, encontrando o atributo Content de todos os controles de botão na página e adicionar o conteúdo texto para uma lista de cadeia de caracteres. Consulte o método InitCommandGrammar em MainPage.xaml.cs para detalhes.

Para processar o resultado de uma sessão de reconhecimento, utilizando uma gramática de lista, você lê a propriedade de texto em SpeechRecognitionUIResult (ou SpeechRecognitionResult), se usando a versão sem um interface do usuário. Você poderia fazer isso, por exemplo, em uma instrução switch, como mostrado na Figura 3.

Figura 3, o resultado de uma sessão de reconhecimento de processamento

switch (result.RecognitionResult.Text.ToLower())
{
  case "cancel":
  // Cancel code
    break;
  case "save":
  // Save memo code
    break;
  case "quit":
    break;
  default:
    break;
}

Um exemplo mais detalhado encontra-se o retorno de chamada CommandCompleted em MainPage.xaml.cs.

Predefinidos gramática o API de fala no Windows Phone 8 fornece duas gramáticas predefinidas: Ditado e WebSearch. Ditado também é chamado de curta mensagem de ditado e emprega a mesma gramática como usado na built-in app de mensagens de texto. Em contraste, WebSearch é otimizado para as frases usadas para pesquisar online. O comando Find/Pesquisar interno usa a mesma gramática WebSearch.

O espaço de busca para ambos gramáticas predefinidos é vasto, exigindo a capacidade de processamento disponível através de reconhecimento de voz remota usando o Microsoft speech serviço Web. Em geral essas gramáticas não são adequadas para comando e controle por causa da possibilidade de reconhecimento e a vasta gama de resultados possíveis.

Uma grande vantagem das gramáticas predefinidas é que eles são fáceis de implementar em um aplicativo. Por exemplo, para usar a gramática WebSearch em vez de gramática padrão ditado em Figura 1, basta adicionar esta linha antes da chamada para RecognizeWithUIAsync:

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

Processar o resultado de reconhecimento de uma gramática predefinido acessando-se o resultado da propriedade de texto, como mostrado na Figura 1.

Gramáticas em formato de especificação de gramática de reconhecimento fala o discurso reconhecimento gramática especificação (SRGS) é um padrão W3C no formato XML. Para detalhes sobre o formato e o uso, consulte o artigo da biblioteca MSDN, "Referência XML SRGS gramática," em bit.ly/SYnAu5; a especificação do W3C em bit.ly/V4DNeS; ou qualquer número de páginas de Web tutorial que você encontrará pesquisando on-line "Gramática SRGS." Gramáticas SRGS oferecem funcionalidade rica como referencia a capacidade de especificar itens opcionais e repetir itens, regras, regra, regras especiais e semântica — à custa de esforço extra para criar, testar e depurar a gramática. No Windows Phone 8, gramáticas SRGS são usadas apenas no mecanismo de reconhecimento de local no telefone, ou seja, não no serviço remoto.

Para adicionar uma gramática SRGS, você faz referência a URI de arquivo de gramática no caminho de instalação do aplicativo, como segue:

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

Uma das principais vantagens das gramáticas SRGS é que eles permitem que você especifique valores semânticos para simplificar o processamento de uma ampla gama de respostas do usuário sem acessar o enunciado reconhecido (que está disponível na Propriedade RecognitionResult.Text, como sempre).

Semântica SRGS é objetos (que, na prática, muitas vezes são cadeias de caracteres) que você atribuir às variáveis em sua gramática SRGS usando um <tag> elemento e um subconjunto do ECMAScript. Eles têm duas vantagens usando o texto reconhecido diretamente:

  1. Processamento simplificado: Você pode determinar a intenção do usuário sem analisar o texto reconhecido, que pode assumir múltiplas formas para o mesmo significado. Por exemplo, usando semântica, você pode mapear todas as declarações que significam afirmativa — "Sim" "sim", "afirmativas", "OK" ou "ya" — o único valor semântico "sim".
  2. Facilidade de localização: Você pode usar o code-behind mesmo processar expressões em qualquer língua falada com suporte se você usar um conjunto uniforme de valores semânticos entre todas as línguas.

Para ilustrar estes conceitos, o exemplo de memorando de magia usa uma gramática simples ViewMemos.grxml para controlar a página de ViewMemos.xaml; excertos do que arquivo de gramática com as tags semânticas são mostrados em Figura 4. A função micImage_Tap em ViewMemos.xaml.cs (extraído em Figura 5) demonstra a utilização de valores semânticos no enunciado do usuário de mapeamento para uma ação.

Figura 4 trechos de gramática 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">
<!-- the default grammar language is 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>
      <!--The 'process' semantic can be one of 'clear',
        'save', 'new', or 'select'-->
      <item>
        <!--Reference to the internal rule "scope" below-->
        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> <!-- Optional words -->
        <item repeat="0-1">number</item>
        <!--Reference to the internal rule "number" below -->
        <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> <!-- Can be "all", "selected" or a number from the
      'number' rule -->
      <item>
        all <tag>out.scope="all";</tag>
      </item>
      <item>
        selected <tag>out.scope="selected";</tag>
      </item>      <item>
        <item repeat="0-1">memo</item> <!-- Optional words -->
        <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>
    <!-- See ViewMemos.grxml for the remainder
      of the items in this block -->
  </rule>
</grammar>

Figura 5 manipulação um resultado do reconhecimento usando Propriedades semânticas

// micImage Tap handler, excerpted from 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))
    {
      // In general a semantic property can be any object,
      // but in this case it's a string
      switch (process.Value as string)
      {
        // For this grammar the "process" semantic more or less
        // corresponds to a button on the page
        case "select":
        // Command was "Select memo number 'num'"
          break;
        case "clear":
        // Command was "Clear memo number 'num,'" "Clear all"
        // or "Clear Selected"
          break;
        case "save":
        // Command was "Save" or "Save Changes"
          break;
        case "new":
        // Command was "Enter new"
          break;
        default:
          break;
      }
    }
  }
}

Este exemplo apenas arranhões na superfície do que é possível com a semântica. Para explorar mais, começar com o artigo da biblioteca MSDN, "Usando a tag do elemento," em bit.ly/PA80Wp. O padrão do W3C para a semântica é no bit.ly/RyqJxc.

Você pode experimentar essa gramática na amostra magia Memo navegando até a página ViewMemos e batendo o ícone do microfone. O arquivo ViewMemos.xaml.cs tem o code-behind, incluindo código sob um #define a seção que você pode ativar (usando #define SemanticsDebug) para exibir e depurar os valores semânticos retornados o resultado de reconhecimento.

Usando várias gramáticas sobre o mesmo objeto de reconhecedor uma pergunta natural a fazer neste momento é se você pode usar mais de uma gramática em um objeto SpeechRecognizer. A resposta é sim, com algumas restrições. Aqui estão algumas diretrizes e técnicas de codificação para usar várias gramáticas:

  1. Se você adicionar uma gramática predefinida, você não pode adicionar quaisquer outras gramáticas. Além disso, você não pode desabilitar uma gramática predefinida; é aquele e apenas gramática associado com esse objeto de reconhecedor para sua vida.
  2. Você pode adicionar várias gramáticas personalizadas (lista gramáticas e gramáticas SRGS) para um objeto único reconhecedor e habilitar ou desabilitar as gramáticas, conforme necessário para diferentes cenários em seu aplicativo:
    1. Para acessar uma gramática específica, use o nome de gramática (o parâmetro de seqüência de caracteres passado na chamada para o método de AddGrammar) como uma chave sobre a coleção de gramáticas.
    2. Para habilitar ou desabilitar uma gramática particular, como seu habilitado booleano true ou false. Por exemplo, o seguinte irá desativar a gramática chamada "buttonNames":
myRecognizer.Grammars["buttonNames"].Ativado = false;
  1. Quando você chamar qualquer um dos métodos AddGrammar, a gramática é colocada em uma fila para aguardar o processamento, mas não é analisada ou carregada. A gramática é compilada e carregada na primeira chamada para RecognizeAsync ou em uma chamada opcional para PreLoad­GrammarsAsync. Chamando este último método uso real pode reduzir a latência em retornar um resultado de RecognizeAsync e, portanto, é recomendado para a maioria dos casos de uso.

O próximo 'Killer App'

As características de discurso para apps no Windows Phone 8 representam, entre todas as ofertas de smartphone, a primeira plataforma do desenvolvedor totalmente funcional para fala com dois serviços de reconhecimento no dispositivo e remoto. Usando comandos de voz e o diálogo em app, você pode abrir seu aplicativo para muitos cenários atraentes que irá deliciar os seus usuários. Com esses recursos de fala, seu aplicativo poderia pegar o zumbido e ser o próximo "killer app" no mercado.

F Bispo de Avery tem trabalhado no desenvolvimento de software para mais de 20 anos, com 12 anos passados na Microsoft, onde é gerente de programas para a plataforma de discurso. Ele publicou diversos artigos sobre o suporte ao idioma natural em aplicativos, incluindo tópicos como o suporte a scripts complexos, aplicativos multilíngues e reconhecimento de fala.

Agradecemos aos seguintes especialistas técnicos pela revisão deste artigo: Eduardo Billo, Rob Chambers, Gabriel Ghizila, Michael Kim e Brian Mouncer