语音指令

本文介绍了如何在UWP应用中实现语音指令,通过VoiceCommandDefinition(VCD)文件定义语音指令,使得用户能通过Cortana进行操作。VCD文件包含CommandSet元素,每个CommandSet可包含多个Command,每个Command有Name、Example和ListenFor元素。当语音指令被执行时,OnActivated方法会被调用,用于处理相应操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 语音指令就是通过语音来完成一些常规操作,如启动某个应用,打开或关闭飞行模式等,随着智能助理Cortana的推出,语音操作的重要地位也逐渐显现。若能在应用程序中提供适当的语音操作支持,不仅能够提升应用的用户体验,也给用户的使用带来不少便捷。

语音指令是通过一种名为VoiceCommandDefinition(VCD)文件来定义,当应用程序运行后通过相关API进行安装注册。VCD文件安装成功后,开发者为应用所定义的语音指令就会被操作系统的语音识别引擎发现,并集成到Cortana中。用户只需要打开Cortana应用,并且说出应用程序预先定义好的指令,就可以完成相应的操作了。

VCD文件实质上是一个XML文档。

示例VCD文件内容:

<?xml version="1.0" encoding="utf-8" ?>
<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.2">
  <CommandSet xml:lang="zh-cn">
    <CommandPrefix>测试应用</CommandPrefix>
    <Example>"打开 主页"或"打开 我的音乐"或"我的音乐"或"打开 我的视频"或"我的视频"</Example>
    <Command Name="open">
      <Example>"打开 我的音乐"或"我的音乐"</Example>
      <ListenFor>[打开]{pages}</ListenFor>
      <Feedback>好的,正在打开中。。。</Feedback>
      <Navigate/>
    </Command>
    <PhraseList Label="pages">
      <Item>主页</Item>
      <Item>我的音乐</Item>
      <Item>我的视频</Item>
      <Item>我的照片</Item>
    </PhraseList>
  </CommandSet>
</VoiceCommands>

VCD文档的根元素为VoiceCommands,xmlns所指定的命名空间必须为 http://schemas.microsoft.com/voicdecommands/1.2。在VoiceCommands元素下,包含1~15个CommandSet元素,也就是说,CommandSet元素必须出现,至少要有一个。
CommandSet表示一个语音指令集,需要通过xml:lang属性设置所属的区域语言,例如面向简体中文的指令集可以使用语言标记zh-cn。Name属性是可选的,可以不设置,但是,如果开发者打算要在应用程序运行阶段通过代码来动态修改VCD文件,则应该为其命名。如果应用程序支持多种语言的指令,可以定义多个CommandSet。

每个CommandSet元素下都可以设置一个CommandPrefix元素,该元素是可选的,主要用于对应用程序进行标识。例如,应用的名字为Shaken_App,当用户使用语音指令调用该应用时,显然这个名字用口头语言不好说,此时可以通过CommandPrefix元素指定一个名字如"摇一摇",只要用户说出"摇一摇"。语音引擎就会识别出是Shaken_App应用。在版本1.2中,可以用APP Name元素来取代CommandPrefix元素。

CommandSet元素可以包含1~100个Command元素,一个Command元素就表示一条语音指令。必须通过Name属性为每条指令命名,而且在同一个CommandSet集合中不能出现名字重复的指令。Command匀速必须包含一个Example元素,该元素中的内容会显示在Cortana的操作界面上,用来提示用户如何使用该指令。随后还要包括不超过10个ListenFor元素,表示语音引擎应该收听的内容,即语音指令的内容。

PhraseList和PhraseTopic允许包含在CommandSet元素中,必须通过Label属性进行命名。PhraseList会提供一系列短语,语音引擎可以侦听其中任何一短语,这与前面介绍过的SpeechRecognitionListConstraint约束相似。而PhraseTopic则类似于SpeechRecognitionTopicConstraint约束,只是确定一个主题,来提高识别的精确度。

Feedback元素指定反馈信息,当语音识别引擎识别出指令后,在执行指令前向用户展示的反馈信息,如"好的,正在进入应用,请稍后..."。Navigate匀速指定当语音指令执行后要导航到应用程序中的哪个页面,虽然该元素是必须的,但是在Runtime App中可以不指定具体的页面。

当语音指令被成功识别并执行后,会激活当前应用程序,App类的OnActivated方法会被调用,开发者应当重写该方法以进行进一步处理,响应语音指令完成相关操作。这就是上面提到过Navigate元素在UWP App中不需要指定具体的页面的原因,因为开发者可以在OnActivated方法中处理。

该示例包含四个页面,分别为"主页"、"我的音乐"、"我的视频"和"我的照片"。通过语音指令操作应用程序进入特定的页面。例如,用户说出"测试应用我的视频",就会打开当前应用程序,并导航进入"我的视频"页面。

ComamndPrefix元素定义了该应用的别称为"测试应用",只要用户说出"测试应用"系统就能够知道用户要操作的就是当前应用。

在CommandSet元素下面的Example元素向用户展示的是针对真个指令集的使用说明,而在Command元素下的Example元素表示的只是针对单条指令的使用说明。

在ListenFor元素中,"打开"二字被一对中括号([ ])包起来,表示该内容为可选,也就是说,不管用户是否说出"打开"二字,该指令都能够匹配。随后的pages放在一对大括号中,它表示引用了后面的Label为pages的PhraseList元素。只要用户说出PhraseList中任意一个Item元素的内容都可以进行识别。

接下来,在App类中重写OnActivated方法,当用户通过语音操作激活当前应用程序后应该进行的相关处理。

        protected override void OnActivated(IActivatedEventArgs args)
        {
            base.OnActivated(args);
            var varg = args as VoiceCommandActivatedEventArgs;
            //处理识别结果
            SpeechRecognitionResult result = varg.Result;
            //获取已识别的指令名字
            string cmdName = result.RulePath[0];
            if (cmdName is "open")
            {
                //获取 PhraseList中被识别出来的项
                var interpretation = result.SemanticInterpretation;
                if (interpretation != null)
                {
                    //通过 PhraseList的Label属性可以查询出被识别Item
                    string item = interpretation.Properties["pages"].FirstOrDefault();
                    if (!string.IsNullOrEmpty(item))
                    {
                        //导航到对应页面
                        Frame root = Window.Current.Content as Frame;
                        if (root is null)
                        {
                            root = new Frame();
                            Window.Current.Content = root;
                        }
                        switch (item)
                        {
                            case "我的音乐":
                                root.Navigate(typeof(MyMusicPage));
                                break;
                            case "我的视频":
                                root.Navigate(typeof(MyVideoPage));
                                break;
                            case "我的照片":
                                root.Navigate(typeof(MyPhotoPage));
                                break;
                            case "主页":
                                root.Navigate(typeof(MainPage));
                                break;
                            default:
                                root.Navigate(typeof(MainPage));
                                break;
                        }
                    }
                }
            }
            Window.Current.Activate();
        }

由于许多行为都可以激活应用程序(如协议激活),所以必须通过Kind属性来判断一下,是否因语音指令操作而激活应用程序。

判断成立后,可以将方法参数转换为VoiceCommandActivatedEventArgs类型进行操作,并从Result属性中获取到SpeechRecognitionReuslt实例。SpeechRecognitionResult对象的RulePath中会包含别识别的语音指令的名字,该名字就是VCD文件中Command元素的Name属性值。由于本示例之定义了一个Command元素,因此RulePath中包含的元素应当为open。

随后,应用代码还应该知道用户说出了名为pages的PhraseList元素中哪个Item值。可以从SemanticInterpretation属性的Properties集合中找到被识别的PhraseList值。该集合是以字典形式存储的,要在其中检索PhraseList元素的内容,可以用其名字(本例中为pages)作为Key来查找。得到的结果是一个字符串列表,其中就包含被识别的Item元素的内容了。

最后,代码通过分析被识别的Item元素的内容来确定要导航到哪个页面。

为了让自定义的VCD文件能够与Cortana集成,在App类的OnLaunched方法中加入以下代码,以便应用程序在启动时安装VCD文件。

            StorageFile vcdFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///vcd.xml"));
            //使用VoiceCommandManager API, 需要引用 Windows Mobile Extension SDK (introduced in 10.0.10240.0)
            //await VoiceCommandManager.InstallCommandSetsFromStorageFileAsync(vcdFile);

            await VoiceCommandDefinitionManager.InstallCommandDefinitionsFromStorageFileAsync(vcdFile);

从项目目录中获取到VCD文件的引用后,直接调用静态的VoiceCommandManager.InstalCommandSetsFromStorageFileAsync方法就可以完成VCD文件的安装与注册了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值