Partilhar via


Ditado contínuo

Saiba como capturar e reconhecer a entrada de fala de ditado contínuo e de formato longo.

APIs importantes: SpeechContinuousRecognitionSession, ContinuousRecognitionSession

No reconhecimento de fala, você aprendeu a capturar e reconhecer a entrada de fala relativamente curta usando os métodos RecognizeAsync ou RecognizeWithUIAsync de um objeto SpeechRecognizer, por exemplo, ao redigir uma mensagem SMS (serviço de mensagens curtas) ou ao fazer uma pergunta.

Para sessões de reconhecimento de fala contínuas mais longas, como ditado ou email, use a propriedade ContinuousRecognitionSession de um SpeechRecognizer para obter um objeto SpeechContinuousRecognitionSession.

Observação

O suporte ao idioma de ditado depende do dispositivo em que seu aplicativo está sendo executado. Para PCs e laptops, apenas en-US é reconhecido, enquanto o Xbox e os telefones podem reconhecer todos os idiomas suportados pelo reconhecimento de fala. Para obter mais informações, consulte Especificar o idioma do reconhecedor de fala.

Configuração

Seu aplicativo precisa de alguns objetos para gerenciar uma sessão de ditado contínuo:

  • Uma instância de um objeto SpeechRecognizer.
  • Uma referência a um dispatcher de interface do usuário para atualizar a interface do usuário durante o ditado.
  • Uma maneira de rastrear as palavras acumuladas faladas pelo usuário.

Aqui, declaramos uma instância de SpeechRecognizer como um campo privado da classe code-behind. Seu aplicativo precisa armazenar uma referência em outro lugar se você quiser que o ditado contínuo persista além de uma única página XAML (Extensible Application Markup Language).

private SpeechRecognizer speechRecognizer;

Durante o ditado, o reconhecedor gera eventos de um thread em segundo plano. Como um thread em segundo plano não pode atualizar diretamente a interface do usuário em XAML, seu aplicativo deve usar um dispatcher para atualizar a interface do usuário em resposta a eventos de reconhecimento.

Aqui, declaramos um campo privado que será inicializado posteriormente com o dispatcher da interface do usuário.

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

Para acompanhar o que o usuário está dizendo, você precisa lidar com eventos de reconhecimento gerados pelo reconhecedor de fala. Esses eventos fornecem os resultados de reconhecimento para partes de enunciados do usuário.

Aqui, usamos um objeto StringBuilder para manter todos os resultados de reconhecimento obtidos durante a sessão. Novos resultados são acrescentados ao StringBuilder à medida que são processados.

private StringBuilder dictatedTextBuilder;

Inicialização

Durante a inicialização do reconhecimento de fala contínuo, você deve:

  • Busque o dispatcher para o thread da interface do usuário se você atualizar a interface do usuário do seu aplicativo nos manipuladores de eventos de reconhecimento contínuo.
  • Inicialize o reconhecedor de fala.
  • Compile a gramática de ditado integrada. Observação O reconhecimento de fala requer pelo menos uma restrição para definir um vocabulário reconhecível. Se nenhuma restrição for especificada, uma gramática de ditado predefinida será usada. Consulte Reconhecimento de fala.
  • Configure os ouvintes de eventos para eventos de reconhecimento.

Neste exemplo, inicializamos o reconhecimento de fala no evento de página OnNavigatedTo.

  1. Como os eventos gerados pelo reconhecedor de fala ocorrem em um thread em segundo plano, crie uma referência ao dispatcher para atualizações no thread da interface do usuário. OnNavigatedTo é sempre invocado no thread da interface do usuário.
this.dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
  1. Em seguida, inicializamos a instância SpeechRecognizer.
this.speechRecognizer = new SpeechRecognizer();
  1. Em seguida, adicionamos e compilamos a gramática que define todas as palavras e frases que podem ser reconhecidas pelo SpeechRecognizer.

    Se você não especificar uma gramática explicitamente, uma gramática de ditado predefinida será usada por padrão. Normalmente, a gramática padrão é melhor para ditado geral.

    Aqui, chamamos CompileConstraintsAsync imediatamente sem adicionar uma gramática.

SpeechRecognitionCompilationResult result =
      await speechRecognizer.CompileConstraintsAsync();

Manipular eventos de reconhecimento

Você pode capturar um único enunciado ou frase breve chamando RecognizeAsync ou RecognizeWithUIAsync.

No entanto, para capturar uma sessão de reconhecimento mais longa e contínua, especificamos ouvintes de eventos a serem executados em segundo plano enquanto o usuário fala e definimos manipuladores para criar a cadeia de caracteres de ditado.

Em seguida, usamos a propriedade ContinuousRecognitionSession do nosso reconhecedor para obter um objeto SpeechContinuousRecognitionSession que fornece métodos e eventos para gerenciar uma sessão de reconhecimento contínuo.

Dois eventos em particular são críticos:

O evento ResultGenerated é gerado à medida que o usuário fala. O reconhecedor escuta continuamente o usuário e gera periodicamente um evento que passa uma parte da entrada de fala. Você deve examinar a entrada de fala, usando a propriedade Result do argumento de evento, e tomar as medidas apropriadas no manipulador de eventos, como acrescentar o texto a um objeto StringBuilder.

Como uma instância de SpeechRecognitionResult, a propriedade Result é útil para determinar se você deseja aceitar a entrada de fala. Um SpeechRecognitionResult fornece duas propriedades para isso:

  • Status indica se o reconhecimento foi bem-sucedido. O reconhecimento pode falhar por vários motivos.
  • Confiança indica a confiança relativa de que o reconhecedor entendeu as palavras corretas.

Aqui estão as etapas básicas para dar suporte ao reconhecimento contínuo:

  1. Aqui, registramos o manipulador para o evento de reconhecimento contínuo ResultGenerated no evento de página OnNavigatedTo.
speechRecognizer.ContinuousRecognitionSession.ResultGenerated +=
        ContinuousRecognitionSession_ResultGenerated;
  1. Em seguida, verificamos a propriedade Confidence. Se o valor de Confidence for Medium ou melhor, acrescentaremos o texto ao StringBuilder. Também atualizamos a interface do usuário à medida que coletamos entradas.

    Observe que o evento ResultGenerated é gerado em um thread em segundo plano que não pode atualizar a interface do usuário diretamente. Se um manipulador precisar atualizar a interface do usuário (como o [Exemplo de fala e TTS]), você deverá enviar as atualizações para o thread da interface do usuário por meio do método RunAsync do dispatcher.

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. Em seguida, lidamos com o evento Completed , que indica o fim do ditado contínuo.

    A sessão termina quando você chama os métodos StopAsync ou CancelAsync (descritos na próxima seção). A sessão também pode terminar quando ocorre um erro ou quando o usuário para de falar. Verifique a propriedade Status do argumento de evento para determinar por que a sessão foi encerrada (SpeechRecognitionResultStatus).

    Aqui, registramos o manipulador para o evento de reconhecimento contínuo Completed no evento de página OnNavigatedTo.

speechRecognizer.ContinuousRecognitionSession.Completed +=
      ContinuousRecognitionSession_Completed;
  1. O manipulador de eventos verifica a propriedade Status para determinar se o reconhecimento foi bem-sucedido. Ele também lida com o caso em que o usuário parou de falar. Muitas vezes, um TimeoutExceeded é considerado um reconhecimento bem-sucedido, pois significa que o usuário terminou de falar. Você deve lidar com esse caso em seu código para uma boa experiência.

    Observe que o evento ResultGenerated é gerado em um thread em segundo plano que não pode atualizar a interface do usuário diretamente. Se um manipulador precisar atualizar a interface do usuário (como o [Exemplo de fala e TTS]), você deverá enviar as atualizações para o thread da interface do usuário por meio do método RunAsync do dispatcher.

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

Forneça feedback de reconhecimento contínuo

Quando as pessoas conversam, muitas vezes confiam no contexto para entender completamente o que está sendo dito. Da mesma forma, o reconhecedor de fala geralmente precisa de contexto para fornecer resultados de reconhecimento de alta confiança. Por exemplo, por si só, as palavras "peso" e "esperar" são indistinguíveis até que mais contexto possa ser obtido das palavras ao redor. Até que o reconhecedor tenha alguma confiança de que uma palavra, ou palavras, foram reconhecidas corretamente, ele não gerará o evento ResultGenerated.

Isso pode resultar em uma experiência menos do que ideal para o usuário à medida que ele continua falando e nenhum resultado é fornecido até que o reconhecedor tenha confiança alta o suficiente para gerar o evento ResultGenerated.

Manipule o evento HypothesisGenerated para melhorar essa aparente falta de capacidade de resposta. Esse evento é gerado sempre que o reconhecedor gera um novo conjunto de possíveis correspondências para a palavra que está sendo processada. O argumento event fornece uma propriedade Hypothesis que contém as correspondências atuais. Mostre-os ao usuário enquanto ele continua falando e assegure-o de que o processamento ainda está ativo. Depois que a confiança for alta e um resultado de reconhecimento tiver sido determinado, substitua os resultados provisórios da Hipótese pelo Resultado final fornecido no evento ResultGenerated.

Aqui, acrescentamos o texto hipotético e uma reticência ("...") ao valor atual do TextBox de saída. O conteúdo da caixa de texto é atualizado à medida que novas hipóteses são geradas e até que os resultados finais sejam obtidos do evento 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;
    });
  }

Iniciar e parar o reconhecimento

Antes de iniciar uma sessão de reconhecimento, verifique o valor da propriedade State do reconhecedor de fala. O reconhecedor de fala deve estar em um estado ocioso.

Depois de verificar o estado do reconhecedor de fala, iniciamos a sessão chamando o método StartAsync da propriedade ContinuousRecognitionSession do reconhecedor de fala.

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

O reconhecimento pode ser interrompido de duas maneiras:

  • StopAsync permite que todos os eventos de reconhecimento pendentes sejam concluídos (ResultGenerated continua a ser gerado até que todas as operações de reconhecimento pendentes sejam concluídas).
  • CancelAsync encerra a sessão de reconhecimento imediatamente e descarta todos os resultados pendentes.

Depois de verificar o estado do reconhecedor de fala, paramos a sessão chamando o método CancelAsync da propriedade ContinuousRecognitionSession do reconhecedor de fala.

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

Observação

Um evento ResultGenerated pode ocorrer após uma chamada para CancelAsync.
Devido ao multithreading, um evento ResultGenerated ainda pode permanecer na pilha quando CancelAsync é chamado. Nesse caso, o evento ResultGenerated ainda é acionado.
Se você definir campos privados ao cancelar a sessão de reconhecimento, sempre confirme seus valores no manipulador ResultGenerated . Por exemplo, não suponha que um campo seja inicializado em seu manipulador se você defini-lo como nulo ao cancelar a sessão.

 

Amostras