Freigeben über


Kontinuierliches Diktieren

Erfahren Sie, wie Sie langformige, kontinuierliche Diktier-Spracheingaben erfassen und erkennen.

Wichtige APIs: SpeechContinuousRecognitionSession, ContinuousRecognitionSession

In der Spracherkennung haben Sie gelernt, wie Sie relativ kurze Spracheingaben mithilfe der Methoden "RecognizeAsync" oder "RecognizeWithUIAsync" eines SpeechRecognizer-Objekts erfassen und erkennen, z. B. beim Verfassen einer SMS-Nachricht (Short Message Service) oder beim Stellen einer Frage.

Verwenden Sie für längere, kontinuierliche Spracherkennungssitzungen wie Diktat oder E-Mail die ContinuousRecognitionSession-Eigenschaft eines SpeechRecognizers, um ein SpeechContinuousRecognitionSession -Objekt abzurufen.

Hinweis

Die Sprachunterstützung für Diktat hängt vom Gerät ab, auf dem Ihre App ausgeführt wird. Bei PCs und Laptops wird nur en-US erkannt, während Xbox und Smartphones alle Sprachen erkennen können, die von der Spracherkennung unterstützt werden. Weitere Informationen finden Sie unter Angeben der Sprache für die Spracherkennung.

Einrichten

Ihre App benötigt einige Objekte, um eine fortlaufende Diktiersitzung zu verwalten:

  • Eine Instanz eines SpeechRecognizer-Objekts.
  • Ein Verweis auf einen UI-Verteiler, um die Benutzeroberfläche während des Diktierens zu aktualisieren.
  • Eine Möglichkeit zum Nachverfolgen der gesammelten Wörter, die vom Benutzer gesprochen werden.

Hier deklarieren wir eine SpeechRecognizer-Instanz als privates Feld der CodeBehind-Klasse. Ihre App muss einen Verweis an anderer Stelle speichern, wenn sie eine fortlaufende Diktierfunktion über eine einzelne XAML-Seite (Extensible Application Markup Language) hinaus beibehalten möchten.

private SpeechRecognizer speechRecognizer;

Während des Diktierens löst die Erkennung Ereignisse aus einem Hintergrundthread aus. Da ein Hintergrundthread die UI in XAML nicht direkt aktualisieren kann, muss Ihre App einen Verteiler verwenden, um die Benutzeroberfläche als Reaktion auf Erkennungsereignisse zu aktualisieren.

Hier deklarieren wir ein privates Feld, das später mit dem UI-Verteiler initialisiert wird.

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

Um zu verfolgen, was der Benutzer sagt, müssen Sie Erkennungsereignisse behandeln, die von der Spracherkennung ausgelöst werden. Diese Ereignisse stellen die Erkennungsergebnisse für Blöcke von Benutzerutterungen bereit.

Hier verwenden wir ein StringBuilder-Objekt , um alle Erkennungsergebnisse zu halten, die während der Sitzung abgerufen wurden. Neue Ergebnisse werden beim Verarbeiten an den StringBuilder angefügt.

private StringBuilder dictatedTextBuilder;

Initialisierung

Während der Initialisierung der kontinuierlichen Spracherkennung müssen Sie:

  • Rufen Sie den Dispatcher für den UI-Thread ab, wenn Sie die Benutzeroberfläche Ihrer App in den Ereignishandlern für die kontinuierliche Erkennung aktualisieren.
  • Initialisieren Sie die Spracherkennung.
  • Kompilieren Sie die integrierte Diktiergrammatik. Die Spracherkennung erfordert mindestens eine Einschränkung, um ein erkennbares Vokabular zu definieren. Wenn keine Einschränkung angegeben ist, wird eine vordefinierte Diktiergrammatik verwendet. Siehe Spracherkennung.
  • Richten Sie die Ereignislistener für Erkennungsereignisse ein.

In diesem Beispiel initialisieren wir die Spracherkennung im OnNavigatedTo-Seitenereignis.

  1. Da Ereignisse, die von der Spracherkennung ausgelöst werden, in einem Hintergrundthread auftreten, erstellen Sie einen Verweis auf den Verteiler für Aktualisierungen des UI-Threads. OnNavigatedTo wird immer im UI-Thread aufgerufen.
this.dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
  1. Anschließend initialisieren wir die SpeechRecognizer-Instanz.
this.speechRecognizer = new SpeechRecognizer();
  1. Anschließend fügen wir die Grammatik hinzu und kompilieren die Grammatik, die alle Wörter und Ausdrücke definiert, die vom SpeechRecognizer erkannt werden können.

    Wenn Sie keine Grammatik explizit angeben, wird standardmäßig eine vordefinierte Diktiergrammatik verwendet. In der Regel eignet sich die Standardgrammatik am besten für das allgemeine Diktieren.

    Hier rufen wir CompileConstraintsAsync sofort auf, ohne eine Grammatik hinzuzufügen.

SpeechRecognitionCompilationResult result =
      await speechRecognizer.CompileConstraintsAsync();

Behandeln von Erkennungsereignissen

Sie können eine einzelne, kurze Äußerung oder Phrase erfassen, indem Sie "RecognizeAsync" oder "RecognizeWithUIAsync" aufrufen.

Um jedoch eine längere fortlaufende Erkennungssitzung zu erfassen, geben wir Ereignislistener an, die im Hintergrund ausgeführt werden sollen, während der Benutzer spricht und Handler definiert, um die Diktierzeichenfolge zu erstellen.

Anschließend verwenden wir die ContinuousRecognitionSession-Eigenschaft unserer Erkennung, um ein SpeechContinuousRecognitionSession -Objekt abzurufen, das Methoden und Ereignisse zum Verwalten einer kontinuierlichen Erkennungssitzung bereitstellt.

Zwei Ereignisse sind insbesondere kritisch:

  • ResultGenerated, das auftritt, wenn die Erkennung einige Ergebnisse generiert hat.
  • Abgeschlossen, was auftritt, wenn die fortlaufende Erkennungssitzung beendet wurde.

Das ResultGenerated-Ereignis wird ausgelöst, wenn der Benutzer spricht. Die Erkennung lauscht kontinuierlich dem Benutzer und löst in regelmäßigen Abständen ein Ereignis aus, das einen Teil der Spracheingabe übergibt. Sie müssen die Spracheingabe mithilfe der Result-Eigenschaft des Ereignisarguments untersuchen und entsprechende Aktionen im Ereignishandler ausführen, z. B. das Anfügen des Texts an ein StringBuilder-Objekt.

Als Instanz von SpeechRecognitionResult ist die Result-Eigenschaft hilfreich, um zu bestimmen, ob Sie die Spracheingabe akzeptieren möchten. Ein SpeechRecognitionResult stellt hierfür zwei Eigenschaften bereit:

  • Status gibt an, ob die Erkennung erfolgreich war. Die Erkennung kann aus verschiedenen Gründen fehlschlagen.
  • Konfidenz gibt die relative Konfidenz an, dass die Erkennung die richtigen Wörter verstanden hat.

Im Folgenden sind die grundlegenden Schritte zur Unterstützung der kontinuierlichen Erkennung aufgeführt:

  1. Hier registrieren wir den Handler für das Ereignis "ResultGenerated continuous recognition" im OnNavigatedTo-Seitenereignis.
speechRecognizer.ContinuousRecognitionSession.ResultGenerated +=
        ContinuousRecognitionSession_ResultGenerated;
  1. Anschließend überprüfen wir die Konfidenzeigenschaft. Wenn der Wert "Konfidenz" mittel oder besser ist, fügen wir den Text an den StringBuilder an. Außerdem wird die Benutzeroberfläche aktualisiert, während wir Eingaben sammeln.

    Beachten Sie, dass das ResultGenerated-Ereignis in einem Hintergrundthread ausgelöst wird, der die Benutzeroberfläche nicht direkt aktualisieren kann. Wenn ein Handler die Benutzeroberfläche aktualisieren muss (wie das [Speech- und TTS-Beispiel]), müssen Sie die Aktualisierungen über die RunAsync-Methode des Dispatchers an den UI-Thread verteilen.

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. Anschließend behandeln wir das Completed-Ereignis , das das Ende des kontinuierlichen Diktierens angibt.

    Die Sitzung endet, wenn Sie die StopAsync- oder CancelAsync-Methoden aufrufen (im nächsten Abschnitt beschrieben). Die Sitzung kann auch enden, wenn ein Fehler auftritt oder wenn der Benutzer nicht mehr spricht. Überprüfen Sie die Status-Eigenschaft des Ereignisarguments, um zu bestimmen, warum die Sitzung beendet wurde (SpeechRecognitionResultStatus).

    Hier registrieren wir den Handler für das "Completed continuous recognition"-Ereignis im OnNavigatedTo-Seitenereignis.

speechRecognizer.ContinuousRecognitionSession.Completed +=
      ContinuousRecognitionSession_Completed;
  1. Der Ereignishandler überprüft die Status-Eigenschaft, um zu bestimmen, ob die Erkennung erfolgreich war. Es behandelt auch den Fall, in dem der Benutzer nicht mehr spricht. Häufig wird eine TimeoutExceeded-Methode als erfolgreiche Erkennung betrachtet, da dies bedeutet, dass der Benutzer das Sprechen beendet hat. Sie sollten diesen Fall in Ihrem Code behandeln, um eine gute Erfahrung zu erzielen.

    Beachten Sie, dass das ResultGenerated-Ereignis in einem Hintergrundthread ausgelöst wird, der die Benutzeroberfläche nicht direkt aktualisieren kann. Wenn ein Handler die Benutzeroberfläche aktualisieren muss (wie das [Speech- und TTS-Beispiel]), müssen Sie die Aktualisierungen über die RunAsync-Methode des Dispatchers an den UI-Thread verteilen.

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

Bereitstellen von fortlaufenden Erkennungsfeedback

Wenn sich die Menschen dagegen unterhalten, verlassen sie sich häufig auf kontextbezogene Informationen, um zu verstehen, was gesagt wird. Ebenso benötigt die Spracherkennung häufig Kontext, um Ergebnisse der Erkennung mit hoher Vertrauenswürdigkeit bereitzustellen. Die Wörter "gewichten" und "warten" sind beispielsweise unveränderlich, bis mehr Kontext von umgebenden Wörtern geglängt werden kann. Bis die Erkennung ein gewisses Vertrauen hat, dass ein Wort oder Wörter richtig erkannt wurden, löst es das ResultGenerated-Ereignis nicht aus.

Dies kann zu einer weniger als idealen Erfahrung für den Benutzer führen, während er weiter spricht, und es werden keine Ergebnisse bereitgestellt, bis die Erkennung hoch genug Konfidenz hat, um das ResultGenerated-Ereignis auszulösen.

Behandeln Sie das HypotheseGenerated-Ereignis , um diesen scheinbaren Mangel an Reaktionsfähigkeit zu verbessern. Dieses Ereignis wird ausgelöst, wenn die Erkennung einen neuen Satz potenzieller Übereinstimmungen für das verarbeitete Wort generiert. Das Ereignisargument stellt eine Hypotheseneigenschaft bereit, die die aktuellen Übereinstimmungen enthält. Zeigen Sie diese dem Benutzer an, während er weiter spricht, und stellen Sie sicher, dass die Verarbeitung noch aktiv ist. Sobald die Konfidenz hoch ist und ein Erkennungsergebnis ermittelt wurde, ersetzen Sie die Zwischenhypotheseergebnisse durch das endgültige Ergebnis, das im ResultGenerated-Ereignis bereitgestellt wird.

Hier fügen wir den hypothetischen Text und ein Auslassungszeichen ("...") an den aktuellen Wert des TextBox-Ausgabefelds an. Der Inhalt des Textfelds wird aktualisiert, wenn neue Hypothesen generiert werden und bis die endgültigen Ergebnisse aus dem ResultGenerated-Ereignis abgerufen werden.

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

Starten und Beenden der Erkennung

Überprüfen Sie vor dem Starten einer Erkennungssitzung den Wert der Eigenschaft "Status der Spracherkennung " . Die Spracherkennung muss sich im Leerlaufzustand befinden.

Nach dem Überprüfen des Zustands der Spracherkennung starten wir die Sitzung, indem wir die StartAsync-Methode der ContinuousRecognitionSession-Eigenschaft der Spracherkennung aufrufen.

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

Die Erkennung kann auf zwei Arten beendet werden:

  • StopAsync ermöglicht den Abschluss aller ausstehenden Erkennungsereignisse (ResultGenerated wird weiterhin ausgelöst, bis alle ausstehenden Erkennungsvorgänge abgeschlossen sind).
  • CancelAsync beendet die Erkennungssitzung sofort und verwirft alle ausstehenden Ergebnisse.

Nach dem Überprüfen des Zustands der Spracherkennung beenden wir die Sitzung, indem wir die CancelAsync-Methode der ContinuousRecognitionSession-Eigenschaft der Spracherkennung aufrufen.

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

Hinweis

Ein ResultGenerated-Ereignis kann nach einem Aufruf von CancelAsync auftreten.
Aufgrund von Multithreading bleibt ein ResultGenerated-Ereignis möglicherweise weiterhin im Stapel, wenn CancelAsync aufgerufen wird. Ist dies der Fall, wird das ResultGenerated-Ereignis weiterhin ausgelöst.
Wenn Sie beim Abbrechen der Erkennungssitzung private Felder festlegen, bestätigen Sie ihre Werte immer im ResultGenerated-Handler. Gehen Sie beispielsweise nicht davon aus, dass ein Feld im Handler initialisiert wird, wenn Sie sie beim Abbrechen der Sitzung auf NULL festlegen.

 

Beispiele