Partager via


Dictée continue

Découvrez comment capturer et reconnaître une entrée vocale de dictée continue et de longue forme.

API importantes : SpeechContinuousRecognitionSession, ContinuousRecognitionSession

Dans reconnaissance vocale, vous avez appris à capturer et à reconnaître des entrées vocales relativement courtes à l’aide des méthodes RecognizeAsync ou RecognizeWithUIAsync d’un objet SpeechRecognizer, par exemple lors de la composition d’un message sms (short message service) ou lors de la pose d’une question.

Pour des sessions de reconnaissance vocale plus longues, telles que la dictée ou l’e-mail, utilisez la propriété ContinuousRecognitionSession d’un SpeechRecognizer pour obtenir un objet SpeechContinuousRecognitionSession.

Remarque

La prise en charge du langage Dictée dépend de l’appareil sur lequel votre application est en cours d’exécution. Pour les PC et les ordinateurs portables, seul en-US est reconnu, tandis que Xbox et les téléphones peuvent reconnaître toutes les langues prises en charge par la reconnaissance vocale. Pour plus d’informations, consultez Spécifier la langue du module de reconnaissance vocale.

Configurer

Votre application a besoin de quelques objets pour gérer une session de dictée continue :

  • Instance d’un objet SpeechRecognizer .
  • Référence à un répartiteur d’interface utilisateur pour mettre à jour l’interface utilisateur pendant la dictée.
  • Un moyen de suivre les mots accumulés prononcés par l’utilisateur.

Ici, nous déclarons une instance SpeechRecognizer en tant que champ privé de la classe code-behind. Votre application doit stocker une référence ailleurs si vous souhaitez que la dictée continue persiste au-delà d’une seule page XAML (Extensible Application Markup Language).

private SpeechRecognizer speechRecognizer;

Pendant la dictée, le module de reconnaissance déclenche des événements à partir d’un thread d’arrière-plan. Étant donné qu’un thread en arrière-plan ne peut pas mettre directement à jour l’interface utilisateur en XAML, votre application doit utiliser un répartiteur pour mettre à jour l’interface utilisateur en réponse aux événements de reconnaissance.

Ici, nous déclarons un champ privé qui sera initialisé ultérieurement avec le répartiteur d’interface utilisateur.

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

Pour suivre ce que l’utilisateur dit, vous devez gérer les événements de reconnaissance déclenchés par le module de reconnaissance vocale. Ces événements fournissent les résultats de reconnaissance pour les blocs d’énoncés utilisateur.

Ici, nous utilisons un objet StringBuilder pour contenir tous les résultats de reconnaissance obtenus pendant la session. Les nouveaux résultats sont ajoutés à StringBuilder au fur et à mesure qu’ils sont traités.

private StringBuilder dictatedTextBuilder;

Initialisation

Lors de l’initialisation de la reconnaissance vocale continue, vous devez :

  • Récupérez le répartiteur pour le thread d’interface utilisateur si vous mettez à jour l’interface utilisateur de votre application dans les gestionnaires d’événements de reconnaissance continue.
  • Initialisez le module de reconnaissance vocale.
  • Compilez la grammaire de dictée intégrée. La reconnaissance vocale nécessite au moins une contrainte pour définir un vocabulaire reconnaissable. Si aucune contrainte n’est spécifiée, une grammaire de dictée prédéfinie est utilisée. Voir reconnaissance vocale.
  • Configurez les écouteurs d’événements pour les événements de reconnaissance.

Dans cet exemple, nous initialisons la reconnaissance vocale dans l’événement de page OnNavigatedTo .

  1. Étant donné que les événements déclenchés par le module de reconnaissance vocale se produisent sur un thread d’arrière-plan, créez une référence au répartiteur pour les mises à jour du thread d’interface utilisateur. OnNavigatedTo est toujours appelé sur le thread d’interface utilisateur.
this.dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
  1. Nous initialisons ensuite l’instance SpeechRecognizer .
this.speechRecognizer = new SpeechRecognizer();
  1. Nous ajoutons et compileons ensuite la grammaire qui définit tous les mots et expressions qui peuvent être reconnus par SpeechRecognizer.

    Si vous ne spécifiez pas explicitement de grammaire, une grammaire de dictée prédéfinie est utilisée par défaut. En règle générale, la grammaire par défaut est la meilleure pour la dictée générale.

    Ici, nous appelons CompileConstraintsAsync immédiatement sans ajouter de grammaire.

SpeechRecognitionCompilationResult result =
      await speechRecognizer.CompileConstraintsAsync();

Gérer les événements de reconnaissance

Vous pouvez capturer un énoncé unique, bref ou une expression en appelant RecognizeAsync ou RecognizeWithUIAsync.

Toutefois, pour capturer une session de reconnaissance continue plus longue, nous spécifions les écouteurs d’événements à exécuter en arrière-plan, car l’utilisateur parle et définit des gestionnaires pour générer la chaîne de dictée.

Nous utilisons ensuite la propriété ContinuousRecognitionSession de notre module de reconnaissance pour obtenir un objet SpeechContinuousRecognitionSession qui fournit des méthodes et des événements pour la gestion d’une session de reconnaissance continue.

Deux événements en particulier sont essentiels :

  • ResultGenerated, qui se produit lorsque le module de reconnaissance a généré des résultats.
  • Terminé, qui se produit lorsque la session de reconnaissance continue a pris fin.

L’événement ResultGenerated est déclenché lorsque l’utilisateur parle. Le module de reconnaissance écoute en permanence l’utilisateur et déclenche régulièrement un événement qui transmet un bloc d’entrée vocale. Vous devez examiner l’entrée vocale, à l’aide de la propriété Result de l’argument d’événement et prendre les mesures appropriées dans le gestionnaire d’événements, telles que l’ajout du texte à un objet StringBuilder.

En tant qu’instance de SpeechRecognitionResult, la propriété Result est utile pour déterminer si vous souhaitez accepter l’entrée vocale. Un SpeechRecognitionResult fournit deux propriétés pour ceci :

  • L’état indique si la reconnaissance a réussi. La reconnaissance peut échouer pour diverses raisons.
  • La confiance indique la confiance relative que le module de reconnaissance a compris les mots corrects.

Voici les étapes de base pour prendre en charge la reconnaissance continue :

  1. Ici, nous inscrivons le gestionnaire pour l’événement de reconnaissance continue ResultGenerated dans l’événement de page OnNavigatedTo.
speechRecognizer.ContinuousRecognitionSession.ResultGenerated +=
        ContinuousRecognitionSession_ResultGenerated;
  1. Nous vérifions ensuite la propriété Confidence. Si la valeur de confiance est moyenne ou meilleure, nous ajoutons le texte au StringBuilder. Nous mettons également à jour l’interface utilisateur à mesure que nous collectons des entrées.

    Notez que l’événement ResultGenerated est déclenché sur un thread d’arrière-plan qui ne peut pas mettre à jour l’interface utilisateur directement. Si un gestionnaire doit mettre à jour l’interface utilisateur (comme l’exemple [Speech et TTS] le fait), vous devez distribuer les mises à jour au thread d’interface utilisateur via la méthode RunAsync du répartiteur.

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. Nous gérons ensuite l’événement Completed , qui indique la fin de la dictée continue.

    La session se termine lorsque vous appelez les méthodes StopAsync ou CancelAsync (décrites dans la section suivante). La session peut également se terminer lorsqu’une erreur se produit ou lorsque l’utilisateur a cessé de parler. Vérifiez la propriété Status de l’argument d’événement pour déterminer pourquoi la session s’est terminée (SpeechRecognitionResultStatus).

    Ici, nous inscrivons le gestionnaire pour l’événement de reconnaissance continue Completed dans l’événement de page OnNavigatedTo.

speechRecognizer.ContinuousRecognitionSession.Completed +=
      ContinuousRecognitionSession_Completed;
  1. Le gestionnaire d’événements vérifie la propriété Status pour déterminer si la reconnaissance a réussi. Il gère également le cas où l’utilisateur a cessé de parler. Souvent, un TimeoutExceededed est considéré comme une reconnaissance réussie, car cela signifie que l’utilisateur a fini de parler. Vous devez gérer ce cas dans votre code pour une bonne expérience.

    Notez que l’événement ResultGenerated est déclenché sur un thread d’arrière-plan qui ne peut pas mettre à jour l’interface utilisateur directement. Si un gestionnaire doit mettre à jour l’interface utilisateur (comme l’exemple [Speech et TTS] le fait), vous devez distribuer les mises à jour au thread d’interface utilisateur via la méthode RunAsync du répartiteur.

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

Fournir des commentaires de reconnaissance continus

Lorsque les gens conversent, ils s’appuient souvent sur le contexte pour comprendre pleinement ce qui est dit. De même, le module de reconnaissance vocale a souvent besoin de contexte pour fournir des résultats de reconnaissance à haut niveau de confiance. Par exemple, par eux-mêmes, les mots « weight » et « wait » sont indistinguishables jusqu’à ce que plus de contexte puisse être glané à partir de mots environnants. Tant que le module de reconnaissance n’a pas confiance qu’un mot ou un mot a été reconnu correctement, il ne déclenche pas l’événement ResultGenerated .

Cela peut entraîner une expérience moins que idéale pour l’utilisateur lorsqu’il continue à parler et qu’aucun résultat n’est fourni tant que le module de reconnaissance n’a pas suffisamment de confiance pour déclencher l’événement ResultGenerated .

Gérez l’événement HypothesisGenerated pour améliorer ce manque apparent de réactivité. Cet événement est déclenché chaque fois que le module de reconnaissance génère un nouvel ensemble de correspondances potentielles pour le mot en cours de traitement. L’argument d’événement fournit une propriété Hypothèse qui contient les correspondances actuelles. Affichez-les à l’utilisateur lorsqu’il continue à parler et rassurez-les que le traitement est toujours actif. Une fois la confiance élevée et un résultat de reconnaissance a été déterminé, remplacez les résultats intermédiaires de l’hypothèse par le résultat final fourni dans l’événement ResultGenerated.

Ici, nous ajoutons le texte hypothétique et un point de suspension (« ... ») à la valeur actuelle de la zone de texte de sortie. Le contenu de la zone de texte est mis à jour à mesure que de nouvelles hypothèses sont générées et jusqu’à ce que les résultats finaux soient obtenus à partir de l’événement 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;
    });
  }

Démarrer et arrêter la reconnaissance

Avant de démarrer une session de reconnaissance, vérifiez la valeur de la propriété État du module de reconnaissance vocale. Le module de reconnaissance vocale doit être dans un état inactif .

Après avoir vérifié l’état du module de reconnaissance vocale, nous commençons la session en appelant la méthode StartAsync de la propriété ContinuousRecognitionSession du module de reconnaissance vocale.

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

La reconnaissance peut être arrêtée de deux façons :

  • StopAsync permet à tous les événements de reconnaissance en attente de se terminer (ResultGenerated continue d’être déclenché jusqu’à ce que toutes les opérations de reconnaissance en attente soient terminées).
  • CancelAsync termine immédiatement la session de reconnaissance et ignore les résultats en attente.

Après avoir vérifié l’état du module de reconnaissance vocale, nous arrêtons la session en appelant la méthode CancelAsync de la propriété ContinuousRecognitionSession du module de reconnaissance vocale.

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

Remarque

Un événement ResultGenerated peut se produire après un appel à CancelAsync.
En raison de la multithreading, un événement ResultGenerated peut toujours rester sur la pile lorsque CancelAsync est appelé. Si c’est le cas, l’événement ResultGenerated se déclenche toujours.
Si vous définissez des champs privés lors de l’annulation de la session de reconnaissance, confirmez toujours leurs valeurs dans le gestionnaire ResultGenerated. Par exemple, ne supposez pas qu’un champ est initialisé dans votre gestionnaire si vous les définissez sur Null lorsque vous annulez la session.

 

Exemples