WP8 - Voice Command,讓App懂你的話 - 1

Windows Phone 8–Voice Command,讓App懂你的話–1

過去在WP 7.1時代,如果您想在中文語系的手機裡,使用WP內鍵的語音指令功能,需要將手機調整為如下圖:

Screen Capture,長按「Start鍵」時,才會出現如右圖:Screen Capture (1)

這個時候的語音功能非常的微弱,只能「open calendar」、「Call Mother」等簡單的指令,更別說支援其他語言了。

好在WP 8開始支援多語言,讓自己的App或WP本身能使用熟悉的語言(例如:中文)進行指令或程式的操作。

 

 

Speech API

   WP 8提供三個Speech Components與App進行互動,概念如下圖:

   

這三個元件功能概略如下:

(1) voice commands:指定語音指令,開啟與串聯App功能;

(2) speech recognition;在App中增加語音輸入的識別;

(3) text-to-speech (TTS);讓App針對輸入的文字進行讀誦;

 

得知有這三個元件之後,往下針對Voice Commands的類型與使用方式深入的說明與探討。

 

Voice Commands

    當用戶安裝了App後,即可在長按「Start鍵」後使用「Voice Commands」去連結該App,例如:對手機說:「Open」

或「Start」後面接「App名稱」即可以開啟指定的App。藉由這樣的方式,開發者可自訂voice commands允許用戶透過說

的方式,開啟或指定到App中特定的頁面進行功能處理。然而,這自訂的方式為了方便用戶了解,開發者也可以設定要顯

示的help說明,可以說相當方便。

 

要完成上述的功能,主要有三個步驟需要完成:

(1) 建立Voice Command Definition (VCD) file。它是份XML檔案定義所有Spoken commands,用戶即透過這些command與app互動;

(2) 增加程式來初始化VCD file手機的語音功能

(3) 增加程式來處理導向(Navigation)與執行(Execute) Commands

 

往下便細部說明這三個步驟的執行方式:

(A) 在WMAppManifest.xml的<Capabilities />宣告需要的Capabilities

     要讓App支援Voice Commands需要先至WMAppManifest.xml增加需要的特性,如下:

   1: <Capabilities>
   2:   <!-- 
   3:   宣告Voice Commands需要的三個Capabilies:
   4:   網路支援搜尋、Speech功能與麥克風功能。
   5:   -->
   6:   <Capability Name="ID_CAP_NETWORKING"/>
   7:   <Capability Name="ID_CAP_SPEECH_RECOGNITION" />
   8:   <Capability Name="ID_CAP_MICROPHONE" />
   9: </Capabilities>

主要三個Capability:ID_CAP_SPEECH_RECOGNITION、ID_CAP_MICROPHONE 與 ID_CAP_NETWORKING。

 

 

(B) 建立Voice Command Definition File

      在App專案中建立一個新的VCD File,設定該檔案的[Build Action]為Content、[Copy to Output Dictionary]為Copy if newer,如下圖;

image image

建立好了Voice Command definition後,在使用前先了解一下每一組Command在XML裡需要定義那些東西。

 

(B-1) 每一組Voice command具有以下特性

     ‧一個example短語說明用戶如何講指令來完成command;

     ‧words或phrases指示應用程式將如何組識成一個可用的command;

     ‧設定應用程式顯示文字,以確認用戶所說的command;

     ‧指定當command執行時,應用程式要指定前往的screen;

 

來看一個簡單的sample說:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.0">
   3:   <CommandSet xml:lang="en-us">
   4:     <CommandPrefix> Contoso Widgets </CommandPrefix>
   5:     <Example> Show today's specials </Example>
   6:     <Command Name="showWidgets">
   7:       <Example> Show today's specials </Example>
   8:       <ListenFor> [Show] {widgetViews} </ListenFor>
   9:       <Feedback> Showing {widgetViews} </Feedback>
  10:       <Navigate Target="/favorites.xaml"/>
  11:     </Command>
  12:  
  13:     <PhraseList Label="widgetViews">
  14:       <Item> today's specials </Item>
  15:       <Item> best sellers </Item>
  16:     </PhraseList>
  17:   
  18:   </CommandSet>
  19:   
  20:   <!-- Other CommandSets for other languages -->
  21:  
  22: </VoiceCommands>

 

從上述VCD範例,有幾個注意的地方:

b-1.1. 選擇一個command prefix

         <CommondPrefix />用於聲明應用程式被開打的關鍵字,而其Command Name則聲明應用程式識別的動作。

         <CommandPrefix />該標籤是選用的,適用於二種主要的情境:

         a. 自己的應用程式名稱是不能併讀。例如:Contoso Widg3ts不能唸的,就需要用到這個標籤;

         b. 對Command做了在地化(localizing)。如果Command支援各種語系就需要設定標籤,以支援不同語系的Command;

        

        [注意]

        在使用<CommandPrefix />標籤時,需注意不支援「subset match text」,舉例來說:設定了「Contoso Weather」與

        「Contoso Weather [phrase]」,但如果用戶說「Contoso [phrase]」或「Weather [phrase]」將無法被識別。

         更多相關的可以參考<Voice command element and attribute reference for Windows Phone 8>。

 

 

b-1.2. 在VCD File中指定words與phrases

          每一組Command最少具有一個<ListenFor />標籤,<ListenFor />可包括單一word或集合words用來代表一個Command的Action來源

          並且透過<Command />將<ListerFor />包裝起來,另外,<ListenFor />無法透過程式化的方式修改

          <PhraseList />標籤關聯<ListenFor />的應用,但該標籤可透過程式化方式修改

          也代表說<ListenFor />定義用戶要說對的指令,其指令中可替換的內容利用「{}」符號包裝起來,再透過<PhraseList />增加「{}」

          中要替換的內容

          舉範例如:定義了<ListenFor>play {movie name}</ListenFor>,然而{movie}再藉由<PhraseList />定義可替換的名稱,因此,

          <PhraseList />即可以透過程式化來動態產生對應的值。

 

====

[補充] 詳細相關Voice Command Element與Attribute的說明;請參考<Windows Phone 8–Voice Command,讓App懂你的話–2>。

==

 

(C) 初始化VCD File

       在應用程式第一次啟動時,即需要將定義好的VCD File進行初始化並註冊其中的Command至電話中的Speech System裡。如下程式碼:

   1: await VoiceCommandService.InstallCommandSetsFromFileAsync(
   2:     new Uri("ms-appx:///ContosoWidgets.xml"));

       上述範例以取得放置於Install folder下的檔案:ContosoWidgets.xml;

 

 

(D) 在應用程式中擷取URI參數與執行Voice Commands

      上述提到VCD File定義Command與Navigate Page,Commands被註冊於Speech System後,隨著用戶口述的指令,Speech System

依該定義,將指令的內容透過URI(NavigationContext中的QueryString)的方式,傳入指定的Navigate Page裡,因此,此步驟將擷取

URI的參數以執行Command的任務。然而,要處理送進來的參數即是該Page負責處理Command的任務。

 

當Speech System識別出該應用程式專用的Command時,將組如成以下的格式,並傳給按照在VCD File中定義<Command />的<Navigate />:

   1: "/favorites.xaml?
   2: voiceCommandName=showWidgets&
   3: widgetViews=best%20sellers&
   4: reco=Contoso%20Widgets%Show%20best%20sellers" 
   5:  
   6: <!-- %20:代表空白 -->

上述QueryString格式,可以對應於VCD File定義的內容,說明如下:

‧vocieCommandName:對應的是<Command />中的Name屬性;

‧widgetViews:則是由開發人員定義<PhraseList />的Label屬性,根據定義的指令組合而成,空白的部分由%20組合;

‧reco:當match <ListenFor />指定時所組合的完整Command;

 

[注意]

‧VCD File允許指令不同指令對應不同畫面,所以不需要實作UriMapper來切換至對應的Page

    但如果本身已支援UriMapper時,需確保Voice command保持完整的QueryString通過UriMapper至Page,避免VCD資訊消失。

 

透過下列程式說明如何處理QueryString:

   1: protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
   2: {
   3:   base.OnNavigatedTo(e);
   4:  
   5:   // 識別是新的Activiation或是從Tombstone返回;
   6:   if (e.NavigationMode == System.Windows.Navigation.NavigationMode.New)
   7:   {
   8:     // 識別QueryString是否具有VoiceCommandName關鍵字;
   9:     if (NavigationContext.QueryString.ContainsKey("voiceCommandName"))
  10:     {
  11:  
  12:       // 取得VoiceCommandName中的值
  13:       string voiceCommandName 
  14:         = NavigationContext.QueryString["voiceCommandName"];
  15:  
  16:       // 定義VoiceCommandName要對應的處理方式
  17:       switch (voiceCommandName)
  18:       {
  19:         case "showWidgets":
  20:           string viewWidget = NavigationContext.QueryString["widgetViews"];
  21:                    
  22:           // Add code to display specified widgets.
  23:           break;
  24:  
  25:         // Add cases for other voice commands. 
  26:         default:
  27:  
  28:           // There is no match for the voice command name.
  29:           break;
  30:       }
  31:     }
  32:   }
  33: }

 

 

(E) Localizing voice commands

       VCD File支援指定多種語系的指令,透過建立多種<CommandSet />指定不同xml:lang的類型。如下範例:

   1: <VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.0">
   2:   <!-- 定義各種語系適用的指令 -->
   3:   <CommandSet xml:lang="en-US" />
   4:   <CommandSet xml:lang="zh-TW" />
   5: </VoiceCommands>

需注意的事,xml:lang是依據OS內鍵的Speech語系,需至「> System > Speech > Speech Language Screen」進行設定。

如果您只有設定的是一種語系,那在Speech Language Screen裡的設定一定要選擇該語系,不然應用程式將不支援voice command。

 

 

(F) Programmatically modifying phrase lists

      Voice commands API提供二種方法支援動態的更新phrase list:

(f-1) 透過CommandSet的Name屬性名稱擷取VoiceCommandSet;

(f-2) 透過PhraseList的Label屬性更新VoiceCommandSet指定Lable的<PhraseList />;

動態更新phrase list是非常好用的,可適合用指定定期更新的任務,例如:查詢電影播放時間或是用戶最愛的資料清單。

然而,要更新phrase list首先需取得預計更新的<CommandSet />;可透過VoiceCommandSet物件來進行操作,需注意每一個

VoiceCommandSet在VCD File裡有一個唯一的名稱,因此,要取得VoiceCommandSet即是透過Name來擷取,如下程式範例:

 

取得VoiceCommandSet:

   1: // 利用<CommandSet xml:lang="en-US" Name="en-US" />中的Name屬性;
   2: VoiceCommandSet widgetVcs =
   3:     VoiceCommandService.InstalledCommandSets["en-US"];

更新VoiceCommandSet中的指定Label的PhraseList:

   1: // 指令Label更新其中的Phrase List
   2: await widgetVcs.UpdatePhraseListAsync("saved", 
   3:     new string[] {"today’s special", "best sellers", "hammer", "plane", "scroll saw"});

要注意當更新了PhraseList後,它將取代原定義於VCD File中的內容,如果想要更新時也保留舊有的Phrase,則需要將舊有的Phrase也加入

才有辦法完整的保持。例如:原有"today's special",更新時一樣要加入至新的Phrase List。

 

 

(G) GUI screens for voice commands

       定義Voice commands時也包含了「GUI screens」協助用戶了解該應用程式提供那些Voice commands與那一種指令可以觸發程式。

‧用戶從應用程式清單選擇一個應用程式;

‧用戶在應用程式裡口述一個voice command,但被系統識別時不是正確的Request actiond時,螢幕會出現一個遮屏,裡面有個「?」可提示;

 

其GUI screens提供二種類型:

G-1. The What can I say screen

         主要列出系統一般支援的voice commands與範例來說明如何執行程式與觸發互動任務

要如何出現下列的圖示,可長按「Start」鍵然後說「what can I say?」或是在畫面中按下global listening畫面的「?」鈕。

         vm-00(點擊「?」鈕出現右邊的圖)vm-01

 

G-2. The Did you know? screen

         該畫面比較特別,它會列出指定應用程式可用的voice commands得以執行該程式。該畫面於上述的「global listening screen」

屬於同一個畫面只是不同的tab,它內容會包括應用程式名稱(或是VCD File中定義的<CommandPrefix />名稱)與voice command example。

       vm-00vm-02vm-03

       =>點擊「?」鈕後會出現有「apps頁籤」,選擇該頁籤點擊指定的應用程式,則可以看到如第三圖的說明。

 

 

[範例]

該範例簡單定義了一組<CommandSet />以支援中文語系,舉例搭公車的測試,其voice command為「VCDProject 搭72車」。

a. Voice command Definition File的格式

   1: <?xml version="1.0" encoding="utf-8"?>
   2:  
   3: <VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.0">
   4:   
   5:   <CommandSet xml:lang="zh-TW" Name="myTWCommands">
   6:     
   7:     <CommandPrefix>公車</CommandPrefix>
   8:     
   9:     <Example> 搭幾號車 </Example>
  10:  
  11:     <Command Name="TakeBus">
  12:       <Example> 搭幾號車 </Example>
  13:       <ListenFor> 搭 {busnumber} 車 </ListenFor>
  14:       <Feedback> 搭 {busnumber} 車 </Feedback>
  15:       <Navigate Target="MainPage.xaml" />
  16:     </Command>
  17:     
  18:     <PhraseList Label="busnumber">
  19:       <Item> 1 </Item>
  20:       <Item> 72 </Item>
  21:       <Item> 33 </Item>
  22:     </PhraseList>
  23:  
  24:   </CommandSet>
  25: </VoiceCommands>

 

b. 在MainPage.xaml中,實作註冊VCD File與在OnNavigated()時處理Speech System傳入的參數

b-1. 註冊VCD File

   1: private bool voiceCommandInitialized = false;
   2:  
   3: private async void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
   4: {
   5:     if (!this.voiceCommandInitialized)
   6:     {
   7:         try
   8:         {
   9:             // 向Speech System註冊該應用程式定義的VCD File
  10:             Uri uri = new Uri("ms-appx:///voicecommands.xml", UriKind.Absolute);
  11:             // 透過Windows.Phone.Speech.VoiceCommands.VoiceCommandService.InstallCommandSetsFromFileAsync註冊
  12:             await Windows.Phone.Speech.VoiceCommands.VoiceCommandService.InstallCommandSetsFromFileAsync(uri);
  13:  
  14:             this.voiceCommandInitialized = true;
  15:  
  16:             MessageBox.Show("install voice command file, successful!");
  17:         }
  18:         catch (Exception error)
  19:         {
  20:             MessageBox.Show(error.Message + "\r\nVoice Commands failed to initialize.");
  21:         }
  22:     }
  23: }

 

b-2. 在OnNavigated()時處理Speech System傳入的參數

   1: protected override void OnNavigatedTo(NavigationEventArgs e)
   2: {
   3:     base.OnNavigatedTo(e);
   4:  
   5:     // 判斷NavigationContext中的QueryString是否具有 voiceCommandName
   6:     if (NavigationContext.QueryString.ContainsKey("voiceCommandName") == true)
   7:     {
   8:         // 利用<Command />中定義的Name屬性取值
   9:         string tCmd = NavigationContext.QueryString["voiceCommandName"].ToString();
  10:         // 利用<Command />使用<PhraseList>的Label屬性取值
  11:         string tPhare = NavigationContext.QueryString["busnumber"].ToString();
  12:         // 取得完整的command
  13:         string tReco = NavigationContext.QueryString["reco"].ToString();
  14:         tblQueryStrgin.Text =
  15:             string.Format("voiceCommandName={0}&\nbusnumber={1}&\nreco={2}", tCmd, tPhare, tReco);
  16:     }
  17: }

 

[範例程式]

 

[注意]

‧在處理Voice Command時,如果遇到Exception時,可參考<Handling errors in speech apps for Windows Phone>。

‧WP8手機支援應用程式的Backup,但應用程式裡定義的VCD File並不會被Backup下來:

    =>建議在應用程式的"Lauch"事件裡,初始化或增加識別是否需要初始化VCD File的邏輯,避免無法使用Voice Command功能。

 

======

以上是介紹如何在自己的App裡加上WP 8新API:Speech API,讓應用程式可以支援包括:自訂專屬的Speech Command

Text-to-Speech APIs允許讀用戶的語言…等。這些功能也讓我聯想到可用於例如:指定開啟家裡的燈、電視等跟其他設備

的結合,讓App能控制的範圍更多更特別。該篇的介紹,希望有助於大家了解Speech API的使用。

 

References:

What's new in Windows Phone 8 SDK for developers (重要)

What's new in Windows Phone SDK 8.0 (重要)

Speech for Windows Phone 8 (重要)

Voice commands for Windows Phone 8

Speech recognition for Windows Phone 8

Text-to-speech (TTS) for Windows Phone

Voice command element and attribute reference for Windows Phone 8 (重要)

Text to Speech in Windows Phone 7 (重要)

Use Speech on my phone (教學,在手機中怎麼使用語音)

Alarm Clock with Voice Commands Sample

Updating a Voice Command Phrase List using a Background Agent (重要)

More Speech for Windows Phone Samples

WP8 Voice Commands: Phrase Lists & WP8 Voice Commands: Dynamic Phrase Lists … From Azure!

Windows Phone 8 语音 - Speech for Windows Phone 8

 

Dotblogs Tags: