Dieser Artikel ist Tag #6 der Serie 8 Tage Windows Phone 8 von Geert van der Cruijsen.
Der Originalartikel befindet sich hier: 8 days of Windows Phone 8 — Day 6: Speech API.
Herzlich willkommen zu einer weiteren Ausgabe meiner Serie 8 Tage Windows Phone 8. Heute, im sechsten Artikel, widmen wir uns den APIs zur Sprachsteuerung. Sprache auf Windows Phone 8 besteht aus drei wesentlichen Bausteinen: Text To Speech (Synthese), Speech To Text (Sprachverständnis) und Voice Commands (Sprachkommandos). In diesem Artikel wollen wir uns mit allen drei Aspekten auseinandersetzen.
- Tag 0: Einleitung zu den 8 Tagen Windows Phone 8
- Tag 1: Überblick über das SDK
- Tag 2: Live Tiles und Sperrbildschirm
- Tag 3: Der Emulator & das Simulation Dashboard
- Tag 4: Die neuen Bildschirmauflösungen
- Tag 5: .NET 4.5 & C# 5.0
- Tag 6: Die API zur Sprachsteuerung
- Tag 7: NFC und Bluetooth
- Tag 8: Brieftasche und In-App Käufe
Text To Speech
Als erste der drei APIs zur Sprachsteuerung diskutieren wir die Text to Speech API zur Sprachsynthese. In Windows Phone 7 mussten Sie die Bing Speech API verwenden, wenn Sie einen geschriebenen Satz in Ton übersetzen wollten. In Windows Phone 8 ist diese API Teil der Windows Phone API. Unter der Haube verwendet diese höchstwahrscheinlich auch weiterhin die Bing Server.
Erstellen wir ein neues Projekt. Als erstes müssen wir die Capability zur Spracherkennung im WMAppManifest.xml hinzufügen. Mit Visual Studio 2012 können wir das direkt im Capabilities Tab machen.
Als nächstes platzieren wir einen Button auf der MainPage und schreiben die folgenden zwei Zeilen in den Click Event Handler zu diesem Button.
private void SayHelloButton_Click(object sender, RoutedEventArgs e) { SpeechSynthesizer ss = new SpeechSynthesizer(); ss.SpeakTextAsync("8 days of windows phone 8, day 6"); }
Wenn Sie die App ausführen, werden Sie merken, dass Sie wirklich nur diese zwei Zeilen brauchen, um geschriebenen Text in Sprache zu verwandeln. Großartig! Beachten Sie, dass die Methode SpeakTextAsync der Klasse SpeechSynthesizer eine async Methode ist. Sie können auch die Sprache und die Stimme des gesprochenen Schnipsels verändern. Fügen wir etwas mehr Code hinzu, um eine deutsche Ausgabe, gesprochen von einer männlichen Stimme zu bekommen:
private void SayGermanButton_Click_(object sender, RoutedEventArgs e) { SpeechSynthesizer ss = new SpeechSynthesizer(); VoiceInformation vi = InstalledVoices.All.Where(v => v.Language == "de-DE" && v.Gender == VoiceGender.Male).FirstOrDefault(); ss.SetVoice(vi); ss.SpeakTextAsync("8 Tage von Windows Phone 8, Tag 6"); }
Es sind nur zwei Zeilen erforderlich, um die Sprache und das Geschlecht zu setzen (ja, es würde sogar auch mit einer gehen). Der Rest bleibt unverändert. Wenn wir den Button jetzt noch mal drücken (im Beispielprojekt habe ich einen zweiten Button hinzugefügt, um beide Fälle testen zu können), hören wir eine männliche deutsche Stimme. Kommen wir zum nächsten Thema, der Übersetzung von gesprochener Sprache in Text — Speech To Text.
Speech To Text
Die im vorherigen Abschnitt diskutierte Sprachsynthese ist schon sehr praktisch. Die Konvertierung von gesprochener Sprache in Text ist noch eindrucksvoller und nicht viel schwerer zu implementieren. Bevor wir anfangen, müssen wir der App die Fähigkeit zur Nutzung des Mikrofons verleihen. Machen Sie einen Haken bei der entsprechenden Box im Capabilities Reiter der Datei WMAppManifest.xml.
Nun, da wir die Fähigkeit zur Nutzung des Mikrofons haben, beginnen wir mit etwas Code zur Spracherkennung. Wir fügen einen Button hinzu, mit dem wir den Benutzer fragen, wie er sich gerade fühlt.
<Button x:Name="AskStatusButton" Content="how are you doing?" Click="AskStatusButton_Click"></Button> <TextBlock x:Name="StatusText"></TextBlock> <TextBlock x:Name="ConfidenceText"></TextBlock>
Im Code Behind fügen wir im Click Event zu diesem Button etwas Code zur Spracherkennung hinzu und geben das Ergebnis der Erkennung im StatusText TextBlock aus. Wir verwenden zudem einen weiteren TextBlock, um das Confidence Level (also die Angabe, wie sicher der Text der gesprochenen Sprache entspricht) der Spracherkennung auszugeben.
Im Click Event beginnen wir, indem wir ein SpeechRecognizerUI Objekt erstellen. Auf diesem SpeechRecognizerUI Objekt setzen wir einige Eigenschaften: die Eigenschaft ListenText ist der Text, welcher als Titel im Sprachdialog angezeigt wird (siehe das Bild unten). Die nächste Eigenschaft ist der ExampleText. Mit dieser Eigenschaft können Sie ein einfaches Beispiel für die Antwort des Benutzers angeben. Danach setzen wir die Eigenschaft ReadoutEnabled auf true, damit das Telefon den Text an den Benutzer zurück spricht. Als letzte Eigenschaft setzen wir ShowConfirmation, damit der gesprochene Text dem Benutzer schriftlich auf dem Bildschirm angezeigt wird.
private async void AskStatusButton_Click(object sender, RoutedEventArgs e) { SpeechRecognizerUI sr = new SpeechRecognizerUI(); sr.Settings.ListenText = "How are you doing?"; sr.Settings.ExampleText = "I'm doing fine"; sr.Settings.ReadoutEnabled = true; sr.Settings.ShowConfirmation = true; SpeechRecognitionUIResult result = await sr.RecognizeWithUIAsync(); if (result.ResultStatus == SpeechRecognitionUIStatus.Succeeded) { StatusText.Text = result.RecognitionResult.Text; ConfidenceText.Text = result.RecognitionResult.TextConfidence.ToString(); } }
Nachdem wir alle diese Eigenschaften gesetzt haben, können wir die Methode RecognizeWithUIAsync aufrufen, um die Spracherkennung zu starten. Beachten Sie, dass beim ersten Aufruf dieser Methode der Benutzer gefragt wird, ob er zustimmt, dass die Sprachaufnahme zur Verarbeitung an die Server von Microsoft gesendet wird. Wenn der Benutzer zustimmt, wird die Spracherkennung gestartet.
Nachdem die Spracherkennung abschlossen ist, können Sie das Ergebnis im Code abfragen. Das Ergebnis, welches von RecognizeWithUIAsync zurück kommt, enthält eine Text Eigenschaft und ein Confidence Level. Mit dem Confidence Level bekommen wir einen Hinweis, ob das Ergebnis brauchbar ist. Im Beispielprojekt zeigen wir beide Werte in den beiden TextBoxes auf der MainPage an.
In manchen Fällen wollen Sie den Benutzer nur zwischen einigen vorgegebenen Optionen auswählen lassen. Das ist ebenfalls sehr einfach mit der SpeechRecognizerUI Klasse umzusetzen. Wir fügen einen weiteren Button und zwei weitere TextBoxes zur MainPage hinzu um den Benutzer zu fragen, welcher Wochentag heute ist.
<Button x:Name="AskDayButton" Content="which day is it?" Click="AskDayButton_Click"></Button> <TextBlock x:Name="DayText"></TextBlock> <TextBlock x:Name="DayConfidenceText"></TextBlock>
Danach fügen wir den Code zum Click Event des Buttons hinzu. Dieser ist, bis auf einige Erweiterungen, fast der selbe wie vorher.
private async void AskDayButton_Click(object sender, RoutedEventArgs e) { SpeechRecognizerUI sr = new SpeechRecognizerUI(); sr.Settings.ListenText = "Which day is it today?"; sr.Settings.ExampleText = "Friday"; sr.Settings.ReadoutEnabled = true; sr.Settings.ShowConfirmation = true; sr.Recognizer.Grammars.AddGrammarFromList("answer", new string[] { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }); SpeechRecognitionUIResult result = await sr.RecognizeWithUIAsync(); if (result.ResultStatus == SpeechRecognitionUIStatus.Succeeded) { DayText.Text = result.RecognitionResult.Text; DayConfidenceText.Text = result.RecognitionResult.TextConfidence.ToString(); } }
In der einzigen neuen Zeile geben wir die Liste der möglichen Antworten an. Die Spracherkennung wird die gesprochene Sprache nun nur noch gegen diese Wörter prüfen. In unserem Beispiel habe ich die Wochentage als mögliche Antworten angegeben.
Wenn Sie die Anwendung ausführen, werden Sie merken, dass nur noch die Wörter in der Liste als Antwort akzeptiert werden.
Voice Commands
Das letzte Thema für heute sind die Sprachkommandos. Mit Sprachkommandos kann der Benutzer Ihre App mit einer bestimmten Aufgabe starten oder eine Aufgabe innerhalb der App ausführen, wenn diese bereits läuft. Sprachkommandos bestehen immer aus 3 Teilen: Dem Namen der App, damit das Betriebssystem weiß, an welche App das Kommando zu richten ist, dem Namen des Kommandos und einem Satz, welcher eine Art Parameter für Ihr Kommando darstellt.
Um Sprachkommandos zu realisieren, müssen Sie eine XML Datei hinzufügen, welche die Definition der Sprachkommandos beinhaltet. Um diese VCD Datei hinzuzufügen, klicken Sie mit Rechts auf Ihr Projekt im Visual Studio und wählen sie Add New Item. Dann wählen Sie Voice Command Definition aus der Liste.
Standardmäßig erhalten Sie eine VCD Datei, welche bereits einige Beispielkommandos und ‑Sätze beinhaltet. Wir werden diese ändern, um ein Kommando zu definieren, welches die App startet, indem es den Benutzer fragt, welcher Tag heute, gestern oder morgen ist.
Als erstes müssen Sie in der VCD Datei das CommandPrefix definieren. Das ist das Wort, welches das Betriebssystem verwendet, um Ihre App zu finden. Danach fügen wir das Kommando hinzu. Dieses braucht ein Element ListenFor, womit dem Betriebssystem angegeben wird, auf welchen Text es hören soll. Zu dem Kommando können Sie weiterhin einen Satz angeben, wie ich es im Beispiel mit dem {day} gemacht habe. Dieser Satz, zusammen mit seinen Varianten, muss ebenfalls Teil der VCD Datei sein.
<?xml version="1.0" encoding="utf-8"?> <VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.0"> <CommandSet xml:lang="en-US"> <CommandPrefix>8 days</CommandPrefix> <Example>what day is it today?</Example> <Command Name="DayToday"> <Example>What day is it?</Example> <ListenFor>What day is it {day}</ListenFor> <Feedback>Checking the day</Feedback> <Navigate Target="/MainPage.xaml"/> </Command> <PhraseList Label="day"> <Item> today </Item> <Item> tomorrow </Item> <Item> yesterday </Item> </PhraseList> </CommandSet> </VoiceCommands>
Wenn die Definition der Kommandos in unserer VCD Datei abgeschlossen ist, können wir diese beim Betriebssystem registrieren. Sie müssen dies nur einmal machen, wenn Ihre Anwendung zum ersten Mal ausgeführt wird. Der Einfachheit halber fügen wir die Registrierung in unserem Beispiel einfach dem Konstruktor der MainPage hinzu.
public MainPage() { InitializeComponent(); InitializeVoiceCommands(); } private async System.Threading.Tasks.Task InitializeVoiceCommands() { await VoiceCommandService.InstallCommandSetsFromFileAsync(new Uri("ms-appx:///VoiceCommandDefinition1.xml")); }
Das ist alles, was wir tun müssen, um unsere Anwendung per Sprache zu starten. Sie können die Spracherkennung auslösen, indem Sie den Windows Button etwas länger gedrückt halten. Sie sehen dann ein kleines „Ich höre zu …“ Fenster. Wenn Sie fragen „Was kann ich sagen?“ oder das Fragezeichen drücken, kommen Sie auf eine neue Seite mit der Erklärung, welche Kommandos verfügbar sind. Die erste Seite beinhaltet die Kommandos, die in das System eingebaut sind. Wenn Sie nach rechts wischen, sehen Sie eine Übersicht über die Apps, die Sprachkommandos anbieten. Unsere App ist hier aufgeführt. Wenn Sie auf die App klicken, sehen Sie die Liste der Kommandos, die von dieser App unterstützt werden.
Wenn wir jetzt den Windows Button gedrückt halten und sagen „8 days, What day is it tomorrow?“, wird unsere Anwendung starten und die MainPage anzeigen.
Das Sprachkommando wird der MainPage in Form des Querystring übergeben. In dem wir den Handler OnNavigatedTo überschreiben, können wir prüfen, welches Sprachkommando verwendet wurde und welcher Satz vom Benutzer gesprochen wurde.
protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); if (e.NavigationMode == System.Windows.Navigation.NavigationMode.New) { if (NavigationContext.QueryString.ContainsKey("voiceCommandName")) { string command = NavigationContext.QueryString["voiceCommandName"]; } } }
Das Kommando und der Satz werden als separate Parameter übergeben. Wenn wir die App also starten und sie über das Sprachkommando aktivieren, sehen wir im Debugger das folgende:
Wie Sie sehen, gibt es einen Parameter „day“, welchen Sie beispielsweise in einem Switch Statement nutzen können, um eine geeignete Methode aufzurufen.
Sie können das Beispielprojekt hier herunterladen: http://sdrv.ms/QSJ2yx.
Das ist alles für heute zu den APIs zur Sprachsteuerung. Hoffentlich kommen Sie morgen wieder, um mehr über die APIs zu NFC und Bluethooth zu erfahren.