本文章是由機器翻譯。

Windows Phone

啟用 Windows Phone 8 應用程式的語音功能,第 2 篇:應用程式內對話方塊

F Avery Avery

下載代碼示例

上個月,在第 1 部分 (msdn.microsoft.com/magazine/jj721592) 的這兩部分的系列,我討論了 Windows Phone 8 app 中有利的聲音命令。在這裡,我將與使用者在運行的程式,使用語音輸入和輸出中討論對話方塊的。

一旦發起了一個應用程式,很多情況下可以受益于使用者和手機使用語音輸入和輸出之間的相互作用。一種自然是在應用程式對話方塊。例如,使用者可以啟動魔法備註 app (見前面第條) 轉到主頁面,然後使用語音辨識輸入新的備註、 接收音訊回饋並確認所做的更改。假設沒有逐個,使用者可以完全輸入並保存幾個備忘錄並沒有觸及 (除了第一次的長推開始按鈕) 的電話。

你可以想像使用語音對話開始在應用程式中的許多其他方案。例如,一旦使用者導航到頁面顯示我的最愛清單中保存備忘錄、 電影或紀念品等,她可以使用識別要選擇一個,然後採取行動:編輯、 播放、 順序、 刪除等。語音輸出會然後讀回所選內容,並要求進行確認。

在下面的部分我打賭出例子使用語音輸入和輸出,以簡單的例子開始和工作到更複雜的例子。我會展示執行簡單的情況下,可顯示一些更豐富的功能可用於高級方案是多麼容易。

對使用者進行通信:語音合成 API

電腦生成的語音輸出分別調用文本到語音 (TTS) 或語音合成 (儘管嚴格地講,TTS 包含更多語音合成的)。常見用途包括通知和確認,如前所述,但它也是其他使用方式下書閱讀器或螢幕閱讀器的關鍵。

語音合成的簡單示例在其最簡單的表單中,您的應用程式可以翻譯到口語音訊中只是兩行代碼的文本字串。這裡是使用從魔術備註樣本中提取的代碼示例:

// Instantiate a speech synthesizer
private SpeechSynthesizer speechOutput = 
  new SpeechSynthesizer();
// ...
// Private method to get a new memo
private async void GetNewMemoByVoice()
{
  await speechOutput.SpeakTextAsync("Say your memo");
  // Other code for capturing a new memo
}

當使用者點擊麥克風按鈕時,她就會聽到"說您的備忘錄"口語從當前音訊裝置。 在下面的部分我會擴展此示例通過添加代碼,以接受使用者的輸入使用語音辨識。

TTS 功能先進的方案嚴重依賴語音輸出的應用程式可能使用的情況下,需要更改音量、 音調或在致辭中的講率輸出。 以涵蓋這些先進的情況下,有兩種其他方法:SpeakSsmlAsync 和 SpeakSsmlFromUriAsync。 這些方法假定輸入是語音合成標記語言 (SSML) 格式,全球資訊網協會 (W3C) XML 標準的文本中嵌入音訊和合成器引擎的屬性說出來。 我還沒在這篇文章或魔法備註代碼下載,包括 SSML 示例代碼,但您可以在 MSDN 庫參考文章中找出更多有關 SSML bit.ly/QwWLsu (或在 W3C 規範 bit.ly/V4DlgG)。

合成器類還具有事件為 SpeakStarted 和 BookmarkReached,並有每講一講方法的重載,採取一般狀態物件作為第二個參數,以説明您跟蹤的講一講方法的哪個實例生成一個特定的事件。 使用 SSML 和處理的事件,您的代碼可以提供突出口語的文本或重新開機段落的中間講一講呼叫等功能。

語音輸入:語音辨識 API

語音辨識應用程式中的使用案例兩大類是文本輸入和命令和控制。 在第一個使用案例,文本輸入的 app 只是捕獲使用者的話語作為文本 ; 這是有用的當使用者可以說幾乎所有東西,如"新"備註示例代碼的功能。

在第二個使用案例、 指揮和控制,使用者操作 app 口語話語而不是通過點擊按鈕或跨手機的臉上滑動手指。 此使用案例是無手駕駛或烹飪等的方案中尤其有用。

語音辨識的簡單示例關於語音辨識應用程式中的功能的詳細資訊之前,讓我們看看最簡單的例子:文本輸入幾行代碼。

圖 1 顯示 GetNewMemo­ByVoice 方法顯示較早前,但添加初始化一個識別器物件,該物件的行數與啟動識別會話和處理結果。

圖 1 初始化一個識別器物件、 啟動識別會話及處理結果

private SpeechRecognizerUI speechInput = 
  new SpeechRecognizerUI();
// Set text to display to the user when recognizing
speechInput.Settings.ExampleText = 
  "Example: \"Buy roses\"";
speechInput.Settings.ListenText = "Say your memo";
// ...
// Private method to get a new memo
private async void GetNewMemoByVoice()
{
  await speechOutput.SpeakTextAsync("Say your memo"); // TTS prompt
  var recoResult =
    await speechInput.RecognizeWithUIAsync();
      // Uses default Dictation grammar
  Memo_TB.Text =
    recoResult.RecognitionResult.Text; // Do something with the result
}

當然,在實際代碼中就永遠不會這樣,一樣簡單,如果你看魔術備註示例中,您將看到一個 try/catch 塊,並檢查成功識別。

如果您嘗試此應用程式範例中通過點擊麥克風圖示,您會發現你說的話,您的備忘錄後,出現"思維"螢幕,其次是 UI,確認後的結果在備註文字方塊中插入。 幕後的很多事情上,最重要的是要識別語音的遠端伺服器上的"語法"的使用。 語法是基本上是一套規則,指定哪些詞彙條目 ("字"),引擎需要認識到並以何種順序。 下一節將探討語音辨識 API 和與識別語法如何使用它。

語音辨識 API 的概述我進入語音辨識編碼的細節之前,讓我們看高級別看 API 和他們的角色中的類別。 圖 2 顯示 API 的基本佈局。 您會注意到的第一件是兩個框有語音­在名稱中的識別器。

Speech Recognition API Design Overview
圖 2 語音辨識 API 設計概述

如果您的應用程式不需要顯示 UI 與語音辨識,或者如果您想要顯示您自己的自訂 UI,您應具現化示的左側中部的 SpeechRecognizer 類的副本圖 2。 此物件看作是此 API 中的語音辨識的基本業務單位。 這是該應用程式中添加了任何語法它需要。 初始化後,調用 RecognizeAsync 來做實際的承認。 由於 SpeechRecognizer 實現 IAsyncOperation <SpeechRecognitionResult>,狀態和結果物件是已完成回呼函數中可用。 因此,沒有任何單獨的事件,識別完成或拒絕與其他託管語音的 Api。

顧名思義,頂級的 SpeechRecognizerUI 類提供了語音辨識的預設 GUI,與手機的全球語音使用者介面回饋、 消歧和確認是一致的。 與全球語音使用者介面保持相容性,並簡化編碼,大多數應用程式應使用此類,而不是前面提到的非 UI 類。 當你具現化一個 SpeechRecognizerUI 物件時,它附帶的兩個重要的物件:設置物件,設置要顯示給使用者 ; 的 UI 文本的位置 和一個 SpeechRecognizer 物件,使您可以指定語法,如以下各節中所述。 初始化後,您應該調用父 SpeechRecognizerUI 物件要啟動識別會話的 RecognizeWithUIAsync。 如果您在子 SpeechRecognizer 物件上使用 RecognizeAsync,它將識別好像 SpeechRecognizer 物件正在使用的獨立,就沒有 UI。 此後,術語 SpeechRecognizer 和承認­非同步應理解為泛型物件和方法有和無的 UI,酌情參考檔。

使用語音辨識步驟有了 Windows Phone 8 應用程式中使用語音辨識的四個基本步驟:

  1. 創建要在 (不需要如果使用預定義的語法) 的識別過程中使用的語法。
  2. 通過設置屬性,並根據需要添加語法初始化的 SpeechRecognizer 物件。
  3. 通過調用語音啟動識別會話­Recognizer.RecognizeAsync 或 SpeechRecognizer­-UI。RecognizeWithUIAsync。
  4. 進程識別結果和採取適當的行動。

圖 1 顯示了所有這些步驟除號 1、 創建語法。 預定義的聽寫語法,是預設語法,因此,不需要創建或將其添加到集合中的語法。

很大程度上實現這些步驟的代碼取決於在語音辨識中使用的語法的類型。 下一節仲介紹的概念和使用的 Windows Phone 8 的語音辨識語法。

語音辨識語法簡介

現代語音辨識引擎所有使用語法來抑制的短語的識別引擎必須通過該搜索 (以下簡稱"搜索空間") 的一組以查找到使用者的話語,匹配,從而提高識別的準確性。 語法規則可能允許短語的識別號碼的清單作為簡單或複雜作為一般會話文本。

在 Windows Phone 8 語音 API,您可以指定語法以三種方式,如以下各節中所述。 每種情況,您將添加到語法上的 SpeechRecognizer 物件的集合語法。

簡單列表語法最簡單的方法來指定自訂的語法,為應用程式提供的識別器應該聽簡單的字串陣列中的所有短語的清單。 這些清單語法是由設備上語音辨識引擎處理的。 創建和添加清單語法的代碼可以簡單的按鈕名稱,承認對靜態清單如下所示:

commandReco.Recognizer.Grammars.AddGrammarFromList(
  "mainPageCommands", new string[] { "cancel", "save", "quit" });

魔術備註示例沒有一點更複雜的工具:它建立的片語清單通過查找頁面上的所有按鈕控制項的內容屬性並向字串清單中添加的內容的文本。 請參閱 MainPage.xaml.cs 中的 InitCommandGrammar 方法,獲得詳細資訊。

要處理使用清單語法識別會話的結果,你如果使用的版本沒有 UI,讀取 SpeechRecognitionUIResult (或 SpeechRecognitionResult) 上的文字屬性。 你可以這樣做,例如,在 switch 語句,如中所示圖 3

圖 3 加工識別會話的結果

switch (result.RecognitionResult.Text.ToLower())
{
  case "cancel":
  // Cancel code
    break;
  case "save":
  // Save memo code
    break;
  case "quit":
    break;
  default:
    break;
}

更詳細的示例是在 MainPage.xaml.cs 中的 CommandCompleted 回檔中找到的。

預定義的語法上 Windows Phone 8 語音 API 提供了兩個預定義的語法:聽寫和粘性。 聽寫也被稱為短消息聽寫和雇用作為在內置短信應用程式中使用相同的語法。 相比之下,粘性被優化,可用於線上搜索的短語。 內置的查找/搜索命令將使用相同的粘性語法。

這兩個預定義的語法的搜索空間是巨大的需要通過使用 Microsoft 語音的 Web 服務的遠端語音辨識可用的處理能力。 一般這些語法不適合于指揮和控制由於識的可能性和範圍廣泛的可能的結果。

預定義語法的一個主要優點是它們很容易在應用程式中實現。 例如,若要使用的粘性語法,而不是預設聽寫語法中的圖 1,您只需添加此線前對 RecognizeWithUIAsync 的調用:

speechInput.Recognizer.Grammars.AddGrammarFromPredefinedType(
  "webSearch", SpeechPredefinedGrammar.WebSearch);

處理從預定義的語法識別結果通過訪問結果文字屬性,如中所示圖 1

語音辨識語法標準格式的語法語音辨識語法規范 (SRGS) 是一種 W3C 標準的 XML 格式。 有關格式和用法的詳細資訊,參閱 MSDN 庫文章,"自力更生團體語法 XML 參考",在 bit.ly/SYnAu5; 在 W3C 規範 bit.ly/V4DNeS; 或任何數目的教程的 Web 頁面,你會發現通過線上搜索"自力更生團體語法"。自力更生團體語法提供豐富的功能,如引用指定可選項目和重複專案,規則,規則的能力,特別規則和語義 — — 而額外努力創作、 測試和調試語法。 在 Windows Phone 8,自力更生團體語法用於僅在手機上的本地識別引擎,即不在遠端服務。

若要添加自力更生團體語法,您引用的 URI 的語法檔在應用程式的安裝路徑,如下:

commandReco.Recognizer.Grammars.AddGrammarFromUri(
  "srgsCommands", new Uri("ms-appx:///ViewMemos.grxml"));

自力更生團體語法的一個主要優點是它們允許您指定要簡化處理廣泛的使用者回應,而無需訪問的公認的話語 (這是與往常一樣上的 RecognitionResult.Text 屬性,可用) 的語義值。

自力更生團體語義是物件 (這在實踐中往往是字串) 您賦給變數中使用 <tag> 你自力更生團體語法 元素和 ECMAScript 的一個子集。 他們有兩個直接使用識別的文本優點:

  1. 簡化的處理:不解析已識別的文本,可能需要在多個表單的含義相同的情況下,您可以確定使用者的意圖。 例如,使用語義,您可以映射意味著肯定的所有話語 — —"是,""啊,""肯定,""OK"或"雅"— — 為單個的語義值"yes"。
  2. 當地語系化的易用性:您可以使用相同的代碼隱藏進程中的任何受支援語言的話語,如果您跨所有語言使用一套統一的語義值。

為了說明這些概念,魔術備註示例使用一個簡單的文法 ViewMemos.grxml 控制的 ViewMemos.xaml 頁 ; 這與語義標記的語法檔的摘錄所示圖 4。 在 ViewMemos.xaml.cs 中的函數 micImage_Tap (摘錄在圖 5) 演示了如何使用映射到的操作的使用者的話語中的語義值。

圖 4 從 ViewMemos.grxml SRGS 語法的摘錄

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE grammar PUBLIC "-//W3C//DTD GRAMMAR 1.0//EN"
  "http://www.w3.org/TR/speech-grammar/grammar.dtd">
<!-- the default grammar language is US English -->
<grammar xmlns="http://www.w3.org/2001/06/grammar"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.w3.org/2001/06/grammar
           http://www.w3.org/TR/speech-grammar/grammar.xsd"
         xml:lang="en-US" version="1.0" tag-format="semantics/1.0"
           root="buttons">
  <rule id="buttons" scope="public">
    <one-of>
      <!--The 'process' semantic can be one of 'clear',
        'save', 'new', or 'select'-->
      <item>
        <!--Reference to the internal rule "scope" below-->
        Clear <ruleref uri="#scope" type="application/srgs+xml"/>
        <tag>out.process="clear";out.
num = rules.latest();</tag>
      </item>
      <item>
        Save
        <item repeat="0-1">changes</item>
        <tag>out.process="save";</tag>
      </item>
      <item>
        Enter new
        <tag>out.process="new";</tag>
      </item>
      <item>       
        Select
        <item repeat="0-1">memo</item> <!-- Optional words -->
        <item repeat="0-1">number</item>
        <!--Reference to the internal rule "number" below -->
        <ruleref uri="#number" type="application/srgs+xml"/>
        <tag>out.process="select";out.
num =
          rules.latest();</tag>
      </item>
    </one-of>
  </rule>
  <rule id="scope" scope="private">
    <one-of> <!-- Can be "all", "selected" or a number from the
      'number' rule -->
      <item>
        all <tag>out.scope="all";</tag>
      </item>
      <item>
        selected <tag>out.scope="selected";</tag>
      </item>      <item>
        <item repeat="0-1">memo</item> <!-- Optional words -->
        <item repeat="0-1">number</item>
        <ruleref uri="#number" type="application/srgs+xml"/>
      </item>
    </one-of>
  </rule>
 <rule id="number" scope="public">
      <item>
        1
      </item>
    <!-- See ViewMemos.grxml for the remainder
      of the items in this block -->
  </rule>
</grammar>

圖 5 處理使用語義屬性識別結果

// micImage Tap handler, excerpted from ViewMemos.xaml.cs
private async void micImage_Tap(object sender, GestureEventArgs e)
{
  var commandResult = await commandReco.RecognizeWithUIAsync();
  if (commandResult.ResultStatus ==
    SpeechRecognitionUIStatus.Succeeded)
  {
    var commandSemantics = commandResult.RecognitionResult.Semantics;
    SemanticProperty process = null;
    if (commandSemantics.TryGetValue("process", out process))
    {
      // In general a semantic property can be any object,
      // but in this case it's a string
      switch (process.Value as string)
      {
        // For this grammar the "process" semantic more or less
        // corresponds to a button on the page
        case "select":
        // Command was "Select memo number 'num'"
          break;
        case "clear":
        // Command was "Clear memo number 'num,'" "Clear all"
        // or "Clear Selected"
          break;
        case "save":
        // Command was "Save" or "Save Changes"
          break;
        case "new":
        // Command was "Enter new"
          break;
        default:
          break;
      }
    }
  }
}

此示例只是表面的什麼是可能的語義。 探索更多,開頭的 MSDN Library 的文章,"標記元素,使用"在 bit.ly/PA80Wp。 語義的 W3C 標準是在 bit.ly/RyqJxc

通過導航到 ViewMemos 頁面,並點擊麥克風圖示,您可以嘗試此魔術備註示例中的語法。 ViewMemos.xaml.cs 檔具有代碼隱藏,包括根據代碼 # 定義您可以啟動的部分 (使用 # 定義 SemanticsDebug) 來顯示和調試上識別結果返回的語義值。

識別器在同一物件上使用多個語法一個自然的問題要問此時是 SpeechRecognizer 物件上是否可以使用多個語法。 答案是肯定的有一些限制條件。 這裡是一些準則和編碼技術為使用多個語法:

  1. 如果您添加預定義的語法,您不能添加任何其他語法。 此外,您不能禁用某個預定義的語法 ; 它是一個和只有其存留期內關聯到識別器物件的語法。
  2. 您可以為單個識別器物件添加多個自訂語法 (清單語法和自力更生團體語法) 和啟用或禁用語法根據需要為您的應用程式中的不同情形:
    1. 若要訪問某個特定的語法,請使用語法名稱 (字串參數傳遞給 AddGrammar 方法調用中) 作為語法集合上的某個鍵。
    2. 若要啟用或禁用某個特定的語法,設置其啟用布林值為 true 或 false。 例如,以下語句將禁用命名為"buttonNames"的語法:
myRecognizer.Grammars["buttonNames"]。啟用 = false ;
  1. 當您調用 AddGrammar 方法中的任何時,語法放在佇列中等待處理,但並不是分析或載入。 語法是編譯和載入或可選調用預緊上第一次調用 RecognizeAsync­GrammarsAsync。 實際使用可以減少從 RecognizeAsync 返回結果的延隔時間,並因此為大多數使用方式下,建議之前調用這後一種方法。

下一步 ' 殺手 '

語音功能的 Windows Phone 8 代表,當中所有的智慧手機產品,語音特色這兩個設備上和遠端識別服務的第一功能齊全的開發者平臺上的應用程式。 使用聲音命令和應用程式的對話方塊,你可以打開許多令人信服的方案,都會很高興您的使用者對您的應用程式。 與這些語音功能,您的應用程式可以捕獲 buzz 並將下一次的"殺手級應用",在市場上。

F Avery Bishop 一直在 20 年以上,軟體發展中與在 Microsoft,他在哪裡的語音平臺專案經理花了 12 年。他在應用程式中包括複雜字集支援、 多語言應用程式和語音辨識等主題發表了許多文章對自然語言的支援。

感謝以下技術專家對本文的審閱:愛德華多 · Billo、 Rob 分庭、 Gabriel Ghizila、 邁克爾 Kim 和 Brian Mouncer