8 Tage Windows Phone 8 | Tag #6: Die API zur Sprachsteuerung

Geschrieben am von leitning

Die­ser Arti­kel ist Tag #6 der Serie 8 Tage Win­dows Phone 8 von Geert van der Cruijsen.

Der Ori­gi­nal­ar­ti­kel befin­det sich hier: 8 days of Win­dows Phone 8 — Day 6: Speech API.

8 Tage Windows Phone 8

Herz­lich will­kom­men zu einer wei­te­ren Aus­gabe mei­ner Serie 8 Tage Win­dows Phone 8. Heute, im sechs­ten Arti­kel, wid­men wir uns den APIs zur Sprach­steue­rung. Spra­che auf Win­dows Phone 8 besteht aus drei wesent­li­chen Bau­stei­nen: Text To Speech (Syn­these), Speech To Text (Sprach­ver­ständ­nis) und Voice Com­mands (Sprach­kom­man­dos). In die­sem Arti­kel wol­len wir uns mit allen drei Aspek­ten auseinandersetzen.

day6

Text To Speech

Als erste der drei APIs zur Sprach­steue­rung dis­ku­tie­ren wir die Text to Speech API zur Sprach­syn­these. In Win­dows Phone 7 muss­ten Sie die Bing Speech API ver­wen­den, wenn Sie einen geschrie­be­nen Satz in Ton über­set­zen woll­ten. In Win­dows Phone 8 ist diese API Teil der Win­dows Phone API. Unter der Haube ver­wen­det diese höchst­wahr­schein­lich auch wei­ter­hin die Bing Server.

Erstel­len wir ein neues Pro­jekt. Als ers­tes müs­sen wir die Capa­bi­lity zur Sprach­er­ken­nung im WMAppManifest.xml hin­zu­fü­gen. Mit Visual Stu­dio 2012 kön­nen wir das direkt im Capa­bi­li­ties Tab machen.

ID_CAP_SPEECH_RECOGNITION

Als nächs­tes plat­zie­ren wir einen But­ton auf der Main­Page und schrei­ben die fol­gen­den zwei Zei­len in den Click Event Hand­ler zu die­sem 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 aus­füh­ren, wer­den Sie mer­ken, dass Sie wirk­lich nur diese zwei Zei­len brau­chen, um geschrie­be­nen Text in Spra­che zu ver­wan­deln. Groß­ar­tig! Beach­ten Sie, dass die Methode SpeakTex­tAsync der Klasse Speech­Syn­the­si­zer eine async Methode ist. Sie kön­nen auch die Spra­che und die Stimme des gespro­che­nen Schnip­sels ver­än­dern. Fügen wir etwas mehr Code hinzu, um eine deut­sche Aus­gabe, gespro­chen von einer männ­li­chen 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 Zei­len erfor­der­lich, um die Spra­che und das Geschlecht zu set­zen (ja, es würde sogar auch mit einer gehen). Der Rest bleibt unver­än­dert. Wenn wir den But­ton jetzt noch mal drü­cken (im Bei­spiel­pro­jekt habe ich einen zwei­ten But­ton hin­zu­ge­fügt, um beide Fälle tes­ten zu kön­nen), hören wir eine männ­li­che deut­sche Stimme. Kom­men wir zum nächs­ten Thema, der Über­set­zung von gespro­che­ner Spra­che in Text — Speech To Text.

Speech To Text

Die im vor­he­ri­gen Abschnitt dis­ku­tierte Sprach­syn­these ist schon sehr prak­tisch. Die Kon­ver­tie­rung von gespro­che­ner Spra­che in Text ist noch ein­drucks­vol­ler und nicht viel schwe­rer zu imple­men­tie­ren. Bevor wir anfan­gen, müs­sen wir der App die Fähig­keit zur Nut­zung des Mikro­fons ver­lei­hen. Machen Sie einen Haken bei der ent­spre­chen­den Box im Capa­bi­li­ties Rei­ter der Datei WMAppManifest.xml.

capabilitiesmicrophone

Nun, da wir die Fähig­keit zur Nut­zung des Mikro­fons haben, begin­nen wir mit etwas Code zur Sprach­er­ken­nung. Wir fügen einen But­ton hinzu, mit dem wir den Benut­zer fra­gen, 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 die­sem But­ton etwas Code zur Sprach­er­ken­nung hinzu und geben das Ergeb­nis der Erken­nung im Sta­tus­Text Text­Block aus. Wir ver­wen­den zudem einen wei­te­ren Text­Block, um das Con­fi­dence Level (also die Angabe, wie sicher der Text der gespro­che­nen Spra­che ent­spricht) der Sprach­er­ken­nung auszugeben.

Im Click Event begin­nen wir, indem wir ein Speech­Re­co­gnize­rUI Objekt erstel­len. Auf die­sem Speech­Re­co­gnize­rUI Objekt set­zen wir einige Eigen­schaf­ten: die Eigen­schaft Lis­ten­Text ist der Text, wel­cher als Titel im Sprach­dia­log ange­zeigt wird (siehe das Bild unten). Die nächste Eigen­schaft ist der Exam­ple­Text. Mit die­ser Eigen­schaft kön­nen Sie ein ein­fa­ches Bei­spiel für die Ant­wort des Benut­zers ange­ben. Danach set­zen wir die Eigen­schaft Rea­dou­tEn­ab­led auf true, damit das Tele­fon den Text an den Benut­zer zurück spricht. Als letzte Eigen­schaft set­zen wir Show­Con­fir­ma­tion, damit der gespro­chene Text dem Benut­zer schrift­lich auf dem Bild­schirm ange­zeigt 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();
   }
}

Nach­dem wir alle diese Eigen­schaf­ten gesetzt haben, kön­nen wir die Methode Reco­gnize­Wi­t­hUI­Async auf­ru­fen, um die Sprach­er­ken­nung zu star­ten. Beach­ten Sie, dass beim ers­ten Auf­ruf die­ser Methode der Benut­zer gefragt wird, ob er zustimmt, dass die Sprach­auf­nahme zur Ver­ar­bei­tung an die Ser­ver von Micro­soft gesen­det wird. Wenn der Benut­zer zustimmt, wird die Sprach­er­ken­nung gestartet.

speech1

speech2

speech3

speech4

Nach­dem die Sprach­er­ken­nung abschlos­sen ist, kön­nen Sie das Ergeb­nis im Code abfra­gen. Das Ergeb­nis, wel­ches von Reco­gnize­Wi­t­hUI­Async zurück kommt, ent­hält eine Text Eigen­schaft und ein Con­fi­dence Level. Mit dem Con­fi­dence Level bekom­men wir einen Hin­weis, ob das Ergeb­nis brauch­bar ist. Im Bei­spiel­pro­jekt zei­gen wir beide Werte in den bei­den Text­Bo­xes auf der Main­Page an.

In man­chen Fäl­len wol­len Sie den Benut­zer nur zwi­schen eini­gen vor­ge­ge­be­nen Optio­nen aus­wäh­len las­sen. Das ist eben­falls sehr ein­fach mit der Speech­Re­co­gnize­rUI Klasse umzu­set­zen. Wir fügen einen wei­te­ren But­ton und zwei wei­tere Text­Bo­xes zur Main­Page hinzu um den Benut­zer zu fra­gen, wel­cher Wochen­tag 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 But­tons hinzu. Die­ser ist, bis auf einige Erwei­te­run­gen, 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 ein­zi­gen neuen Zeile geben wir die Liste der mög­li­chen Ant­wor­ten an. Die Sprach­er­ken­nung wird die gespro­chene Spra­che nun nur noch gegen diese Wör­ter prü­fen. In unse­rem Bei­spiel habe ich die Wochen­tage als mög­li­che Ant­wor­ten angegeben.

speech5

speech6

speech7

Wenn Sie die Anwen­dung aus­füh­ren, wer­den Sie mer­ken, dass nur noch die Wör­ter in der Liste als Ant­wort akzep­tiert werden.

Voice Com­mands

Das letzte Thema für heute sind die Sprach­kom­man­dos. Mit Sprach­kom­man­dos kann der Benut­zer Ihre App mit einer bestimm­ten Auf­gabe star­ten oder eine Auf­gabe inner­halb der App aus­füh­ren, wenn diese bereits läuft. Sprach­kom­man­dos beste­hen immer aus 3 Tei­len: Dem Namen der App, damit das Betriebs­sys­tem weiß, an wel­che App das Kom­mando zu rich­ten ist, dem Namen des Kom­man­dos und einem Satz, wel­cher eine Art Para­me­ter für Ihr Kom­mando darstellt.

Um Sprach­kom­man­dos zu rea­li­sie­ren, müs­sen Sie eine XML Datei hin­zu­fü­gen, wel­che die Defi­ni­tion der Sprach­kom­man­dos beinhal­tet. Um diese VCD Datei hin­zu­zu­fü­gen, kli­cken Sie mit Rechts auf Ihr Pro­jekt im Visual Stu­dio und wäh­len sie Add New Item. Dann wäh­len Sie Voice Com­mand Defi­ni­tion aus der Liste.

vcdfile

Stan­dard­mä­ßig erhal­ten Sie eine VCD Datei, wel­che bereits einige Bei­spiel­kom­man­dos und –Sätze beinhal­tet. Wir wer­den diese ändern, um ein Kom­mando zu defi­nie­ren, wel­ches die App star­tet, indem es den Benut­zer fragt, wel­cher Tag heute, ges­tern oder mor­gen ist.

Als ers­tes müs­sen Sie in der VCD Datei das Com­mandPre­fix defi­nie­ren. Das ist das Wort, wel­ches das Betriebs­sys­tem ver­wen­det, um Ihre App zu fin­den. Danach fügen wir das Kom­mando hinzu. Die­ses braucht ein Ele­ment Lis­ten­For, womit dem Betriebs­sys­tem ange­ge­ben wird, auf wel­chen Text es hören soll. Zu dem Kom­mando kön­nen Sie wei­ter­hin einen Satz ange­ben, wie ich es im Bei­spiel mit dem {day} gemacht habe. Die­ser Satz, zusam­men mit sei­nen Vari­an­ten, muss eben­falls 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 Defi­ni­tion der Kom­man­dos in unse­rer VCD Datei abge­schlos­sen ist, kön­nen wir diese beim Betriebs­sys­tem regis­trie­ren. Sie müs­sen dies nur ein­mal machen, wenn Ihre Anwen­dung zum ers­ten Mal aus­ge­führt wird. Der Ein­fach­heit hal­ber fügen wir die Regis­trie­rung in unse­rem Bei­spiel ein­fach dem Kon­struk­tor der Main­Page 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üs­sen, um unsere Anwen­dung per Spra­che zu star­ten. Sie kön­nen die Sprach­er­ken­nung aus­lö­sen, indem Sie den Win­dows But­ton etwas län­ger gedrückt hal­ten. Sie sehen dann ein klei­nes „Ich höre zu …“ Fens­ter. Wenn Sie fra­gen „Was kann ich sagen?“ oder das Fra­ge­zei­chen drü­cken, kom­men Sie auf eine neue Seite mit der Erklä­rung, wel­che Kom­man­dos ver­füg­bar sind. Die erste Seite beinhal­tet die Kom­man­dos, die in das Sys­tem ein­ge­baut sind. Wenn Sie nach rechts wischen, sehen Sie eine Über­sicht über die Apps, die Sprach­kom­man­dos anbie­ten. Unsere App ist hier auf­ge­führt. Wenn Sie auf die App kli­cken, sehen Sie die Liste der Kom­man­dos, die von die­ser App unter­stützt werden.

speech8

speech9

speech10

speech11

Wenn wir jetzt den Win­dows But­ton gedrückt hal­ten und sagen „8 days, What day is it tomor­row?“, wird unsere Anwen­dung star­ten und die Main­Page anzeigen.

speech12

Das Sprach­kom­mando wird der Main­Page in Form des Que­rys­tring über­ge­ben. In dem wir den Hand­ler OnNa­vi­ga­tedTo über­schrei­ben, kön­nen wir prü­fen, wel­ches Sprach­kom­mando ver­wen­det wurde und wel­cher Satz vom Benut­zer gespro­chen 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 Kom­mando und der Satz wer­den als sepa­rate Para­me­ter über­ge­ben. Wenn wir die App also star­ten und sie über das Sprach­kom­mando akti­vie­ren, sehen wir im Debug­ger das folgende:

onnavigatedto

Wie Sie sehen, gibt es einen Para­me­ter „day“, wel­chen Sie bei­spiels­weise in einem Switch State­ment nut­zen kön­nen, um eine geeig­nete Methode aufzurufen.

Sie kön­nen das Bei­spiel­pro­jekt hier her­un­ter­la­den: http://sdrv.ms/QSJ2yx.

Das ist alles für heute zu den APIs zur Sprach­steue­rung. Hof­fent­lich kom­men Sie mor­gen wie­der, um mehr über die APIs zu NFC und Blue­thooth zu erfahren.

Hinterlasse eine Antwort

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind markiert *

*

*

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>