Georg fährt extra nach Berlin um Steve Ballmer zu treffen

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

Die­ser Arti­kel ist Tag #6 der Serie 8 Tage Win­dows Pho­ne 8 von Geert van der Cru­ij­sen.

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

8 Tage Windows Phone 8

Herz­lich will­kom­men zu einer wei­te­ren Aus­ga­be mei­ner Serie 8 Tage Win­dows Pho­ne 8. Heu­te, im sechs­ten Arti­kel, wid­men wir uns den APIs zur Sprach­steue­rung. Spra­che auf Win­dows Pho­ne 8 besteht aus drei wesent­li­chen Bau­stei­nen: Text To Speech (Syn­the­se), 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 aus­ein­an­der­set­zen.

day6

Text To Speech

Als ers­te der drei APIs zur Sprach­steue­rung dis­ku­tie­ren wir die Text to Speech API zur Sprach­syn­the­se. In Win­dows Pho­ne 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 Pho­ne 8 ist die­se API Teil der Win­dows Pho­ne API. Unter der Hau­be ver­wen­det die­se höchst­wahr­schein­lich auch wei­ter­hin die Bing Ser­ver.

Erstel­len wir ein neu­es Pro­jekt. Als ers­tes müs­sen wir die Capa­bi­li­ty zur Sprach­er­ken­nung im WMAppManifest.xml hin­zu­fü­gen. Mit Visu­al 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 But­ton.

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 die­se 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 Metho­de SpeakTextA­sync der Klas­se Speech­Syn­the­si­zer eine async Metho­de ist. Sie kön­nen auch die Spra­che und die Stim­me des gespro­che­nen Schnip­sels ver­än­dern. Fügen wir etwas mehr Code hin­zu, um eine deut­sche Aus­ga­be, gespro­chen von einer männ­li­chen Stim­me zu bekom­men:

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ür­de 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 bei­de Fäl­le tes­ten zu kön­nen), hören wir eine männ­li­che deut­sche Stim­me. Kom­men wir zum nächs­ten The­ma, 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­tier­te Sprach­syn­the­se 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 hin­zu, mit dem wir den Benut­zer fra­gen, wie er sich gera­de 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 hin­zu 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 Anga­be, wie sicher der Text der gespro­che­nen Spra­che ent­spricht) der Sprach­er­ken­nung aus­zu­ge­ben.

Im Click Event begin­nen wir, indem wir ein Speech­Re­co­gni­ze­rUI Objekt erstel­len. Auf die­sem Speech­Re­co­gni­ze­rUI Objekt set­zen wir eini­ge Eigen­schaf­ten: die Eigen­schaft Lis­ten­Text ist der Text, wel­cher als Titel im Sprach­dia­log ange­zeigt wird (sie­he das Bild unten). Die nächs­te Eigen­schaft ist der Example­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 Readou­tEnab­led auf true, damit das Tele­fon den Text an den Benut­zer zurück spricht. Als letz­te Eigen­schaft set­zen wir Show­Con­fir­ma­ti­on, damit der gespro­che­ne 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 die­se Eigen­schaf­ten gesetzt haben, kön­nen wir die Metho­de Reco­gni­ze­Wi­t­hUIA­sync auf­ru­fen, um die Sprach­er­ken­nung zu star­ten. Beach­ten Sie, dass beim ers­ten Auf­ruf die­ser Metho­de der Benut­zer gefragt wird, ob er zustimmt, dass die Sprach­auf­nah­me 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 gestar­tet.

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­gni­ze­Wi­t­hUIA­sync 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 bei­de Wer­te 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­gni­ze­rUI Klas­se umzu­set­zen. Wir fügen einen wei­te­ren But­ton und zwei wei­te­re Text­Bo­xes zur Main­Page hin­zu um den Benut­zer zu fra­gen, wel­cher Wochen­tag heu­te 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 hin­zu. Die­ser ist, bis auf eini­ge Erwei­te­run­gen, fast der sel­be wie vor­her.

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 neu­en Zei­le geben wir die Lis­te der mög­li­chen Ant­wor­ten an. Die Sprach­er­ken­nung wird die gespro­che­ne Spra­che nun nur noch gegen die­se Wör­ter prü­fen. In unse­rem Bei­spiel habe ich die Wochen­ta­ge als mög­li­che Ant­wor­ten ange­ge­ben.

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 Lis­te als Ant­wort akzep­tiert wer­den.

Voice Commands

Das letz­te The­ma für heu­te sind die Sprach­kom­man­dos. Mit Sprach­kom­man­dos kann der Benut­zer Ihre App mit einer bestimm­ten Auf­ga­be star­ten oder eine Auf­ga­be inner­halb der App aus­füh­ren, wenn die­se bereits läuft. Sprach­kom­man­dos bestehen immer aus 3 Tei­len: Dem Namen der App, damit das Betriebs­sys­tem weiß, an wel­che App das Kom­man­do zu rich­ten ist, dem Namen des Kom­man­dos und einem Satz, wel­cher eine Art Para­me­ter für Ihr Kom­man­do dar­stellt.

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­ti­on der Sprach­kom­man­dos beinhal­tet. Um die­se VCD Datei hin­zu­zu­fü­gen, kli­cken Sie mit Rechts auf Ihr Pro­jekt im Visu­al Stu­dio und wäh­len sie Add New Item. Dann wäh­len Sie Voice Com­mand Defi­ni­ti­on aus der Lis­te.

vcdfile

Stan­dard­mä­ßig erhal­ten Sie eine VCD Datei, wel­che bereits eini­ge Bei­spiel­kom­man­dos und ‑Sät­ze beinhal­tet. Wir wer­den die­se ändern, um ein Kom­man­do zu defi­nie­ren, wel­ches die App star­tet, indem es den Benut­zer fragt, wel­cher Tag heu­te, 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­man­do hin­zu. 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­man­do 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­ti­on der Kom­man­dos in unse­rer VCD Datei abge­schlos­sen ist, kön­nen wir die­se 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 hin­zu.

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 unse­re 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 Sei­te mit der Erklä­rung, wel­che Kom­man­dos ver­füg­bar sind. Die ers­te Sei­te 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. Unse­re App ist hier auf­ge­führt. Wenn Sie auf die App kli­cken, sehen Sie die Lis­te der Kom­man­dos, die von die­ser App unter­stützt wer­den.

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 unse­re Anwen­dung star­ten und die Main­Page anzei­gen.

speech12

Das Sprach­kom­man­do wird der Main­Page in Form des Que­rystring über­ge­ben. In dem wir den Hand­ler OnNavi­ga­ted­To über­schrei­ben, kön­nen wir prü­fen, wel­ches Sprach­kom­man­do ver­wen­det wur­de und wel­cher Satz vom Benut­zer gespro­chen wur­de.

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­man­do und der Satz wer­den als sepa­ra­te Para­me­ter über­ge­ben. Wenn wir die App also star­ten und sie über das Sprach­kom­man­do akti­vie­ren, sehen wir im Debug­ger das fol­gen­de:

onnavigatedto

Wie Sie sehen, gibt es einen Para­me­ter „day“, wel­chen Sie bei­spiels­wei­se in einem Switch State­ment nut­zen kön­nen, um eine geeig­ne­te Metho­de auf­zu­ru­fen.

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

Das ist alles für heu­te 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 erfah­ren.

Schreibe einen Kommentar

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