Condividi tramite


Dettatura continua

Scopri come acquisire e riconoscere l'input vocale di dettatura continua e di lunga durata.

API importanti: SpeechContinuousRecognitionSession, ContinuousRecognitionSession

In Riconoscimento vocale si è appreso come acquisire e riconoscere un input vocale relativamente breve usando i metodi RecognizeAsync o RecognizeWithUIAsync di un oggetto SpeechRecognizer , ad esempio quando si compone un messaggio SMS (Short Message Service) o quando si pone una domanda.

Per sessioni di riconoscimento vocale continue, ad esempio dettatura o posta elettronica, utilizzare la proprietà ContinuousRecognitionSession di un SpeechRecognizer per ottenere un oggetto SpeechContinuousRecognitionSession .

Annotazioni

Il supporto della lingua di dettatura dipende dal dispositivo in cui è in esecuzione l'app. Per PC e portatili, viene riconosciuto solo en-US, mentre Xbox e telefoni possono riconoscere tutte le lingue supportate dal riconoscimento vocale. Per altre info, vedi Specificare la lingua del riconoscimento vocale.

Configurazione

L'app necessita di alcuni oggetti per gestire una sessione di dettatura continua:

  • Istanza di un oggetto SpeechRecognizer .
  • Riferimento a un dispatcher dell'interfaccia utente per aggiornare l'interfaccia utente durante la dettatura.
  • Un modo per tenere traccia delle parole accumulate pronunciate dall'utente.

In questo caso si dichiara un'istanza speechRecognizer come campo privato della classe code-behind. L'app deve archiviare un riferimento altrove se vuoi rendere persistente la dettatura continua oltre una singola pagina XAML (Extensible Application Markup Language).

private SpeechRecognizer speechRecognizer;

Durante la dettatura, il riconoscitore genera eventi da un thread in background. Poiché un thread in background non può aggiornare direttamente l'interfaccia utente in XAML, l'app deve usare un dispatcher per aggiornare l'interfaccia utente in risposta agli eventi di riconoscimento.

In questo caso dichiariamo un campo privato che verrà inizializzato in un secondo momento con il dispatcher dell'interfaccia utente.

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

Per tenere traccia di ciò che l'utente sta dicendo, è necessario gestire gli eventi di riconoscimento vocale generati dal riconoscimento vocale. Questi eventi forniscono i risultati di riconoscimento per blocchi di espressioni utente.

In questo caso viene usato un oggetto StringBuilder per contenere tutti i risultati di riconoscimento ottenuti durante la sessione. I nuovi risultati vengono aggiunti a StringBuilder durante l'elaborazione.

private StringBuilder dictatedTextBuilder;

Inizializzazione

Durante l'inizializzazione del riconoscimento vocale continuo, è necessario:

  • Ottieni il dispatcher per il thread UI se aggiorni l'interfaccia utente della tua applicazione nei gestori degli eventi di riconoscimento continuo.
  • Inizializzare il riconoscimento vocale.
  • Compilare la grammatica di dettatura predefinita. Nota Il riconoscimento vocale richiede almeno un vincolo per definire un vocabolario riconoscibile. Se non viene specificato alcun vincolo, viene utilizzata una grammatica di dettatura predefinita. Vedere Riconoscimento vocale.
  • Configurare i listener di eventi per gli eventi di riconoscimento.

In questo esempio il riconoscimento vocale viene inizializzato nell'evento della pagina OnNavigatedTo .

  1. Poiché gli eventi generati dal riconoscimento vocale si verificano in un thread in background, creare un riferimento al dispatcher per gli aggiornamenti al thread dell'interfaccia utente. OnNavigatedTo viene sempre richiamato sul thread dell'interfaccia utente.
this.dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
  1. Si inizializza quindi l'istanza di SpeechRecognizer .
this.speechRecognizer = new SpeechRecognizer();
  1. Aggiungere e compilare quindi la grammatica che definisce tutte le parole e le frasi che possono essere riconosciute da SpeechRecognizer.

    Se non si specifica una grammatica in modo esplicito, per impostazione predefinita viene usata una grammatica di dettatura predefinita. In genere, la grammatica predefinita è ideale per la dettatura generale.

    In questo caso si chiama CompileConstraintsAsync immediatamente senza aggiungere una grammatica.

SpeechRecognitionCompilationResult result =
      await speechRecognizer.CompileConstraintsAsync();

Gestire gli eventi di riconoscimento

È possibile acquisire una singola espressione o frase chiamando RecognizeAsync o RecognizeWithUIAsync.

Tuttavia, per acquisire una sessione di riconoscimento continua più lunga, vengono specificati i listener per gli eventi da eseguire in background mentre l'utente parla e si definiscono i gestori per compilare la stringa di dettatura.

Usiamo quindi la proprietà ContinuousRecognitionSession del riconoscimento per ottenere un oggetto SpeechContinuousRecognitionSession che fornisce metodi ed eventi per la gestione di una sessione di riconoscimento continuo.

Due eventi in particolare sono critici:

  • ResultGenerated, che si verifica quando il riconoscitore ha generato alcuni risultati.
  • Completata, che si verifica al termine della sessione di riconoscimento continuo.

L'evento ResultGenerated viene generato quando l'utente parla. Il riconoscitore ascolta continuamente l'utente e genera periodicamente un evento che passa un blocco di input vocale. È necessario esaminare l'input vocale, usando la proprietà Result dell'argomento evento e intraprendere un'azione appropriata nel gestore eventi, ad esempio accodando il testo a un oggetto StringBuilder.

Come istanza di SpeechRecognitionResult, la proprietà Result è utile per determinare se si vuole accettare l'input vocale. Un SpeechRecognitionResult fornisce due proprietà per questa operazione:

Ecco i passaggi di base per supportare il riconoscimento continuo:

  1. In questo caso, registriamo il gestore per l'evento di riconoscimento continuo ResultGenerated nell'evento di pagina OnNavigatedTo .
speechRecognizer.ContinuousRecognitionSession.ResultGenerated +=
        ContinuousRecognitionSession_ResultGenerated;
  1. Si controlla quindi la proprietà Confidence . Se il valore di Confidence è Medio o superiore, aggiungeremo il testo a StringBuilder. Aggiorniamo anche l'interfaccia utente durante la raccolta dell'input.

    Si noti che l'evento ResultGenerated viene generato in un thread in background che non può aggiornare direttamente l'interfaccia utente. Se un gestore deve aggiornare l'interfaccia utente (come illustrato nell'esempio di Riconoscimento vocale e TTS), è necessario inviare gli aggiornamenti al thread dell'interfaccia utente tramite il metodo RunAsync del 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. Viene quindi gestito l'evento Completed, che indica la fine della dettatura continua.

    La sessione termina quando si chiamano i metodi StopAsync o CancelAsync (descritta la sezione successiva). La sessione può anche terminare quando si verifica un errore o quando l'utente ha smesso di parlare. Controllare la proprietà Status dell'argomento evento per determinare il motivo per cui la sessione è terminata (SpeechRecognitionResultStatus).

    Qui registriamo il gestore per l'evento di riconoscimento continuo Completed nell'evento di navigazione della pagina OnNavigatedTo.

speechRecognizer.ContinuousRecognitionSession.Completed +=
      ContinuousRecognitionSession_Completed;
  1. Il gestore eventi controlla la proprietà Status per determinare se il riconoscimento è riuscito. Gestisce anche il caso in cui l'utente ha smesso di parlare. Spesso, un timeoutExceeded viene considerato un riconoscimento riuscito perché significa che l'utente ha finito di parlare. È consigliabile gestire questo caso nel codice per un'esperienza ottimale.

    Si noti che l'evento ResultGenerated viene generato in un thread in background che non può aggiornare direttamente l'interfaccia utente. Se un gestore deve aggiornare l'interfaccia utente (come illustrato nell'esempio di Riconoscimento vocale e TTS), è necessario inviare gli aggiornamenti al thread dell'interfaccia utente tramite il metodo RunAsync del 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";
            });
          }
        }
      }

Fornire feedback continuo sul riconoscimento

Quando le persone conversano, spesso si basano sul contesto per comprendere appieno ciò che viene detto. Analogamente, il riconoscimento vocale spesso necessita di contesto per fornire risultati di riconoscimento con attendibilità elevata. Ad esempio, da soli, le parole "peso" e "attesa" sono indistinguibili fino a quando non è possibile ottenere più contesto dalle parole circostanti. Finché il riconoscitore non ha la certezza che una parola, o parole, sia stata riconosciuta correttamente, non genererà l'evento ResultGenerated .

Ciò può comportare un'esperienza meno che ideale per l'utente man mano che continua a parlare e non vengono forniti risultati fino a quando il riconoscitore non ha una confidenza sufficiente per generare l'evento ResultGenerated .

Gestire l'evento HypothesisGenerated per migliorare questa apparente mancanza di velocità di risposta. Questo evento viene generato ogni volta che il riconoscitore genera un nuovo set di potenziali corrispondenze per la parola in fase di elaborazione. L'argomento evento fornisce una proprietà Hypothesis che contiene le corrispondenze correnti. Mostrarli all'utente mentre continuano a parlare e rassicurarli che l'elaborazione è ancora attiva. Una volta che la confidenza è elevata e viene determinato un risultato di riconoscimento, sostituire i risultati provvisori dell'ipotesi con il risultato finale fornito nell'evento ResultGenerated .

In questo caso, aggiungiamo il testo ipotetico e i puntini di sospensione ("...") al valore corrente dell'output TextBox. Il contenuto della casella di testo viene aggiornato man mano che vengono generate nuove ipotesi e fino a quando non vengono ottenuti i risultati finali dall'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;
    });
  }

Avvia e ferma il riconoscimento

Prima di avviare una sessione di riconoscimento, controllare il valore della proprietà State del riconoscimento vocale. Il riconoscimento vocale deve trovarsi in uno stato di inattività .

Dopo aver controllato lo stato del riconoscimento vocale, si avvia la sessione chiamando il metodo StartAsync della proprietà ContinuousRecognitionSession del riconoscimento vocale.

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

Il riconoscimento può essere arrestato in due modi:

  • StopAsync consente il completamento di tutti gli eventi di riconoscimento in sospeso (ResultGenerated continua a essere generato fino al completamento di tutte le operazioni di riconoscimento in sospeso).
  • CancelAsync termina immediatamente la sessione di riconoscimento e rimuove tutti i risultati in sospeso.

Dopo aver controllato lo stato del riconoscimento vocale, la sessione viene interrotta chiamando il metodo CancelAsync della proprietà ContinuousRecognitionSession del riconoscimento vocale.

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

Annotazioni

Un evento ResultGenerated può verificarsi dopo una chiamata a CancelAsync.
A causa del multithreading, un evento ResultGenerated potrebbe rimanere nello stack quando viene chiamato CancelAsync . In tal caso, l'evento ResultGenerated viene comunque generato.
Se si impostano campi privati durante l'annullamento della sessione di riconoscimento, confermare sempre i relativi valori nel gestore ResultGenerated . Ad esempio, non presupporre che un campo venga inizializzato nel gestore se vengono impostati su Null quando si annulla la sessione.

 

esempi di