天天看點

自定義語音識别規則

添加自定義規則的方法是将實作了ISpeechRecognitionConstraint接口的文法限制執行個體添加到SpeechRecogtnizer對象的Constraints集合中,這些類型包括:

  • SpeechRecognitionGrammarFileConstraint: 通過自定義的SGRS(Speech Recognition Grammer Specification)檔案來定義文法規則。SGRS檔案實質上是一個XML檔案,而且需要遵循W3C組織制定的與語音識别相關的文法标準。
  • SpeechRecognitionListConstraint: 設定一系列短語,在接收語音時,使用者必須說出短語清單中所指定的任意一個關鍵詞才能正确識别。
  • SpeechRecognitionTopicConstraint: 設定識别模式和主題。識别模式分為"聽寫模式"和"搜尋模式",主題是由開發者所指定的一個字元串,如"人名"、“天氣”等。該限制隻是為了提高語音識别的精确率而設的,它不直接控制識别過程中的文法規則。
  • SpeechRecognitionVoiceCommandDefinitionConstraint: 該類沒有構造函數,不直接使用。該限制隻在通過由VCD(Voice Command Definition)檔案所定義的語音指令激活應用程式時才會使用,可以通路SpeechRecognitionResult對象的Constraint屬性來擷取SpeechRecognitionVoiceCommandDefinitionConstraint執行個體。

另外,還需要注意的是,如果Constraints集合中已添加了一個SpeechRecognitionTopicConstraint限制後,同一集合中隻能添加SpeechRecognitionGrammarFileConstraint類型的限制。簡而言之,就是SpeechRecognitionTopicConstraint和SpeechRecognitionGrammarFileConstraint可以配合使用。

1. 自定義SGRS檔案

本小節将通過一個例子來幫助讀者初步掌握如何使用SRGS檔案來限制語音識别的結果。當識别系統應用了自定義的SRGS檔案後,語音識别過程隻遵循SRGS檔案中定義的規則,如果使用者說出的内容不符合SRGS檔案中的規則,那麼語音識别系統将無法正确識别,至少識别的準确性會很低。

首先,需要編寫一個SRGS檔案,該檔案實質上是一個XML檔案,是以隻需要向應用項目中添加一個新的XML檔案即可。

預設情況下,新的XML檔案添加後會自動用XML文檔編輯視窗打開,此時,打開"屬性"視窗,單擊"架構"右邊的省略号按鈕,。随後會打開一個視窗,用來選擇該XML文檔将用到哪些XML架構檔案。找到命名空間 http://www.w3.org/2001./06/grammar,然後單擊其所在行最左邊的單元格,從下拉菜單中選擇"使用該架構"。

進行以上操作是為了在編寫SRGS文檔的時候讓Visual Studio給出智能提示,可以提升SRGS文檔的準确性和編寫效率。

在剛才建立的XML文檔中輸入以下内容:

<?xml version="1.0" encoding="utf-8" ?>
<grammar xmlns="http://www.w3.org/2001/06/grammar" tag-format="semantics/1.0" version="1.0" xml: root="color">
  <rule id="color">
    <item repeat="0-1">把</item>
    <item>顔色</item>
    <one-of>
      <item>改為</item>
      <item>設定為</item>
    </one-of>
    <one-of>
      <item>紅色</item>
      <item>白色</item>
      <item>藍色</item>
    </one-of>
  </rule>
</grammar>
           

從上面的XML文檔中可以看出,SRGS文檔的根元素為grammar,并為該元素指定以下屬性:

  • xmlns: XML文檔的命名空間,必須設定為 http:///www.w3.org/201/06/grammar。
  • tag-forfmat: tag元素的文法格式,本文檔中并未使用tag元素,是以該值可以不考慮。
  • version: 必須指定為1.0。
  • xml: lang: 文檔所使用的區域和語言,zh-cn表示簡體中文。
  • root: 必須指定SRGS文檔中某一條文法規則的名字,此規則在SRGS被加載時将作為預設規則使用。如果不設定該值,SRGS文檔可以正常編譯,DNA語音識别引擎不會進行識别。該文檔中隻有一條名為color的規則,是以root的值也應該為color。

在grammar元素下可以使用rule元素來定義規則,每個rule元素表示一條規則,必須通過id屬性設定規則的名字,而且該名字在整個SRGS文檔中也應該時唯一的,不能出現重複的規則名字。

随後,在rule元素之下,可以使用item元素來定義一個短語,短語可以是任意的合法的字元串。該字元串指定語音識别引擎應該聽到的内容。如果使用了one-of元素,則表明one-of元素下的item元素中所指定的短語隻能識别一條。例如上面SRGS文檔中最後一個one-of元素如下:

<one-of>
      <item>紅色</item>
      <item>白色</item>
      <item>藍色</item>
    </one-of>
           

這表明,識别引擎隻能偵聽以上列出的顔色短語,其他内容則不會被正确識别。

上面的SRGS文檔中第一個item元素(即“把”字短語所在的元素)設定了repeat=="0-1",表示使用者在說話時,可以說出"把"字,也可以不說出,因為"把"字短語的出現次數被指定為0到1個,要麼出現0次,要麼出現1次,表示該短語是可選的。

SRGS檔案編寫完成後,需要設計示例程式的使用者界面,核心的XAML代碼如下:

<StackPanel>
        <Button x:Name="btn" Content="開始說話" Tapped="tbn_Tapped"/>
        <TextBlock TextWrapping="Wrap" FontSize="20"/>
        <TextBlock x:Name="tbRes" FontSize="24" TextWrapping="Wrap"/>
    </StackPanel>do
           

處理按鈕的Click事件,并将識别的結果顯示在TextBlock控件中。

private async void tbn_Tapped(object sender, TappedRoutedEventArgs e)
        {
            btn.IsEnabled = false;
            using (SpeechRecognizer recognizer = new SpeechRecognizer())
            {
                try
                {
                    //加載文法檔案
                    var sgrsFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///srgs.xml"));
                    //建立識别限制
                    SpeechRecognitionGrammarFileConstraint grammarFileConstraint = new SpeechRecognitionGrammarFileConstraint(sgrsFile);
                    //加入到限制集合中
                    recognizer.Constraints.Add(grammarFileConstraint);
                    //編譯限制
                    SpeechRecognitionCompilationResult compilationResult = await recognizer.CompileConstraintsAsync();
                    if (compilationResult.Status == SpeechRecognitionResultStatus.Success)
                    {
                        //開始識别
                        SpeechRecognitionResult result = await recognizer.RecognizeAsync();
                        if (result.Status == SpeechRecognitionResultStatus.Success)
                        {
                            tbRes.Text = $"識别結果:{result.Text}";
                        }
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
            }
            btn.IsEnabled = true;
        }
           

先通過StorageFile.GetFileFormApplicationUriAsync靜态方法從項目目錄中加載SRGS檔案,接着建立SpeechRecognitionGrammarFileConstraint執行個體,并把SRGS檔案傳遞到它的構造函數中,完成初始化。

然後将SpeechRecognitionGrammarFileConstraint執行個體添加到Constraints集合中,再調用COmpileConstraingtsAsync方法編譯所有語音識别的限制對象。最後就可以調用RecognizeAsync方法開始識别了。

2. 短語清單限制

SpeechRecognitionListConstraint類允許開發者使用一個字元串清單(如一個字元串數組)來限制語音識别的過程。當該限制被添加到識别元件的限制集合中後,語音識别引擎隻會偵聽字元串清單中出現的短語。

下面通過一個示例來示範一下如何使用短語清單來限制語音識别的過程。

使用者界面布局請參考以下XAML代碼來完成:

<StackPanel>
        <TextBlock Text="請說出你最喜歡的體育運動:"/>
        <Button Content="開始識别" Width="200" Tapped="Button_Tapped"/>
        <ListBox x:Name="listBox">
            <x:String>足球</x:String>
            <x:String>排球</x:String>
            <x:String>跑步</x:String>
            <x:String>羽毛球</x:String>
            <x:String>橄榄球</x:String>
            <x:String>結束</x:String>
        </ListBox>
    </StackPanel>
           

稍後使用的限制清單與ListBox中的子項相同,當使用者說出清單中的第一個項時,ListBox控件會選中該項。

以下代碼初始化語音識别引擎,并添加作為限制的短語清單。

private async void Page_Loaded(object sender,object e)
        {
            _recognizer = new SpeechRecognizer();
            //建立自定義短語限制
            string[] arrgy = { "足球", "排球", "跑步", "羽毛球", "橄榄球","結束" };
            SpeechRecognitionListConstraint listConstraint = new SpeechRecognitionListConstraint(arrgy);
            //添加限制執行個體到集合中
            _recognizer.Constraints.Add(listConstraint);
            //編譯限制
            await _recognizer.CompileConstraintsAsync();
        }
           
private void Page_UnLoaded(object sender, RoutedEventArgs e)
        {
            //釋放資源
            _recognizer.Dispose();
        }
           

處理按鈕的Click事件,開始語音識别:

private async void Button_Tapped(object sender, TappedRoutedEventArgs e)
        {
            try
            {
                while (true)
                {
                    SpeechRecognitionResult result = await _recognizer.RecognizeAsync();
                    if (result.Status == SpeechRecognitionResultStatus.Success)
                    {
                        //處理識别結果
                        listBox.SelectedItem = result.Text;
                        if (result.Text == "結束")
                        {
                            return;
                        }
                    }
                }

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }
           

要讓ListBox選中某個項,隻需要設定其SelectedItem屬性引用要選中的字元串即可,在以上代碼中,直接将語音識别的結果指派給SelectedItem屬性就可以了。

運作應用程式,單擊"開始識别"按鈕,然後說出ListBox控件中的其中一個子項,當識别成功後,被說出的項會處于選中狀态。

示例Demo

繼續閱讀