【问题标题】:Windows 10 - programming CortanaWindows 10 - 对 Cortana 进行编程
【发布时间】:2015-08-15 11:03:47
【问题描述】:

我正在尝试为 Cortana 编写一个小应用程序。

我的想法是,我说:(我启用了“Hey Cortana”功能)

Hey Cortana, Convert 45 degrees to farenheit

我(此刻)在我的输出窗口 (Visual Studio) 中获得了一个日志。我试图准确地说出这句话,Cortana 完全听懂了,但 Cortana 打开浏览器并将其输入到 Bing 中。

为什么?我做错什么了?我没有收到任何语法错误。

这是我的代码:

// commands.xml

<?xml version="1.0" encoding="utf-8"?>
<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.1">
  <CommandSet xml:lang="en-us" Name="MyCommands_en-us">
    <CommandPrefix> Convert, </CommandPrefix>
    <Example> Convert 45 degrees to farenheit </Example>

    <Command Name ="farenheitToDegrees">
      <Example> 73 farenheit to degrees</Example>
      <ListenFor> {farenheit} farenheit to degrees </ListenFor>
      <Feedback> {farenheit} are ... in degrees </Feedback>
      <Navigate/>
    </Command>

    <Command Name="degreesToFarenheit">
      <Example> 45 degrees to farenheit </Example>
      <ListenFor> {degrees} degrees to farenheit </ListenFor>
      <Feedback> {degrees} degrees are ... in fareneheit </Feedback>
      <Navigate/>
    </Command>

    <PhraseTopic Label="degrees" Scenario="Dictation">
      <Subject>Temperature</Subject>
    </PhraseTopic>

    <PhraseTopic Label="farenheit" Scenario="Dictation">
      <Subject>Temperature</Subject>
    </PhraseTopic>
  </CommandSet>
</VoiceCommands>

// App.xaml.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

using Windows.ApplicationModel.VoiceCommands;
using Windows.Storage;
using Windows.Media.SpeechRecognition;

namespace HelloWorld
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default  Application class.
    /// </summary>
    sealed partial class App : Application
    {
        /// <summary>
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            Microsoft.ApplicationInsights.WindowsAppInitializer.InitializeAsync(
            Microsoft.ApplicationInsights.WindowsCollectors.Metadata |
            Microsoft.ApplicationInsights.WindowsCollectors.Session);
            this.InitializeComponent();
            this.Suspending += OnSuspending;
        }

        /// <summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used such as when the application is launched to open a specific file.
        /// </summary>
        /// <param name="e">Details about the launch request and process.</param>
        protected async override void OnLaunched(LaunchActivatedEventArgs e)
        {

#if DEBUG
            if (System.Diagnostics.Debugger.IsAttached)
            {
                this.DebugSettings.EnableFrameRateCounter = true;
            }
#endif

            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                rootFrame.NavigationFailed += OnNavigationFailed;

                if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    //TODO: Load state from previously suspended application
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (rootFrame.Content == null)
            {
                // When the navigation stack isn't restored navigate to the first page,
                // configuring the new page by passing required information as a navigation
                // parameter
                rootFrame.Navigate(typeof(MainPage), e.Arguments);
            }
            // Ensure the current window is active
            Window.Current.Activate();


            var storageFile =
              await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///commands.xml"));
            await
                Windows.ApplicationModel.VoiceCommands.VoiceCommandDefinitionManager.InstallCommandDefinitionsFromStorageFileAsync(storageFile);
        }

        protected override void OnActivated(IActivatedEventArgs e)
        {
            // Was the app activated by a voice command?
            if (e.Kind != Windows.ApplicationModel.Activation.ActivationKind.VoiceCommand)
            {
                return;
            }

            var commandArgs = e as Windows.ApplicationModel.Activation.VoiceCommandActivatedEventArgs;

        SpeechRecognitionResult speechRecognitionResult = commandArgs.Result;

        // Get the name of the voice command and the text spoken
        string voiceCommandName = speechRecognitionResult.RulePath[0];
        string textSpoken = speechRecognitionResult.Text;

        switch (voiceCommandName)
        {
            case "farenheitToDegrees":
                string farenheit = speechRecognitionResult.SemanticInterpretation.Properties["farenheit"][0];
                System.Diagnostics.Debug.WriteLine((Convert.ToInt32(farenheit) - 32) / 1.8);
                break;

            case "degreesToFarenheit":
                string degrees = speechRecognitionResult.SemanticInterpretation.Properties["degrees"][0];
                System.Diagnostics.Debug.WriteLine(Convert.ToInt32(degrees) * 1.8 + 32);
                break;

            default:
                System.Diagnostics.Debug.WriteLine("None of my bussiness");
                break;
        }
    }


    /// <summary>
    /// Invoked when Navigation to a certain page fails
    /// </summary>
    /// <param name="sender">The Frame which failed navigation</param>
    /// <param name="e">Details about the navigation failure</param>
    void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
    {
        throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
    }

    /// <summary>
    /// Invoked when application execution is being suspended.  Application state is saved
    /// without knowing whether the application will be terminated or resumed with the contents
    /// of memory still intact.
    /// </summary>
    /// <param name="sender">The source of the suspend request.</param>
    /// <param name="e">Details about the suspend request.</param>
    private void OnSuspending(object sender, SuspendingEventArgs e)
    {
        var deferral = e.SuspendingOperation.GetDeferral();
        //TODO: Save application state and stop any background activity
        deferral.Complete();
    }
}

}

有人可以帮帮我吗?

【问题讨论】:

  • 对于命令前缀有一个,转换后这是故意的吗?我不确定 Cortana 是否会识别 , 当它被说出时……
  • 另外我认为您使用了错误版本的语音命令定义文件。试试下面的schemas.microsoft.com/voicecommands/1.2
  • @Mark3308 链接已过时

标签: windows voice-recognition cortana


【解决方案1】:

您上面列出的 VCD 定义文件既没有 PhraseTopic 也没有 PhraseList 来定义花括号中的部分:

 <ListenFor> {farenheit} farenheit to degrees </ListenFor>

我猜你可能想要一个 PhraseTopic,因为它允许不受约束的听写适用于广泛的数字,如下所示:

<PhraseTopic Label="farenheit" Scenario="Dictation">
   <Subject>Temperature</Subject>
</PhraseTopic>

请参阅 VCD 的 here on msdn 规范,您可能想尝试调整 Scenario 值。当然,这确实意味着您需要自己处理获得的文本作为华氏术语,但通常口述数字的文本以文本“1234”形式出现(但不是在 100% 的情况下)。

【讨论】:

  • 似乎只是问题的一部分。 Cortana 仍然什么都不做。也许我做错了什么?要将功能安装到 Cortana,我只需按“本地机器”按钮对吗?
  • Paul,你能用更新的 VCD 文件更新你的问题吗?我可以把它放到这里的一个项目中然后戳它。
  • 嗯,所以我可以在我的测试环境中使用它而无需任何修改。如果你打开 Cortana,在搜索框中输入“帮助”,然后使用应该出现在顶部的“获取帮助”选项,你的应用程序是否会显示在 Cortana 可以做的事情列表的底部(你可能会需要向下滚动)
  • 不,我的应用程序未显示在“帮助”下。但我可以在已安装的应用程序下找到它。我做错了什么?
  • @PaulScharnofske 好的,如果它没有在帮助下显示,那么由于某种原因没有安装 VCD,很奇怪。您的系统设置为美国英语吗?还是您在其他地区?
【解决方案2】:

检查 VCD 文件的属性,值应为:构建操作 = 内容,复制到输出目录 = 始终复制。无论如何,我希望你注册了 vcd 文件:

VoiceCommandService.InstallCommandSetsFromFileAsync(new Uri("ms-appx:///VCD.xml"));

查看有关 Cortana 的 MVA 视频:https://www.microsoftvirtualacademy.com/en-US/training-courses/universal-windows-app-development-with-cortana-and-the-speech-sdk-8487

【讨论】:

【解决方案3】:

嗯...似乎您已经了解了所有步骤,但仍然缺少一些东西...

这是我就 Cortana 的前台功能制作的一个示例:

这是VCD...

    <?xml version="1.0" encoding="utf-8" ?>
    <VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.2">
      <CommandSet xml:lang="en-us" Name="HomeControlCommandSet_en-us">
        <CommandPrefix>HomeControl</CommandPrefix>
        <Example>Control alarm, temperature, light and others</Example>

        <Command Name="Activate_Alarm">
          <Example>Activate alarm</Example>
          <ListenFor>[Would] [you] [please] activate [the] alarm [please]</ListenFor>
          <ListenFor RequireAppName="BeforeOrAfterPhrase">Activate alarm</ListenFor>
          <ListenFor RequireAppName="ExplicitlySpecified">Activate {builtin:AppName} alarm</ListenFor>
          <Feedback>Activating alarm</Feedback>
          <Navigate />
        </Command>

创建此定义后,您需要在 App Startup 处注册它:

    protected async override void OnLaunched(LaunchActivatedEventArgs e)
    {
        ...
        // Install the VCD
        try
        {
            StorageFile vcdStorageFile = await Package.Current.InstalledLocation.GetFileAsync(@"HomeControlCommands.xml");
            await VoiceCommandDefinitionManager.InstallCommandDefinitionsFromStorageFileAsync(vcdStorageFile);
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine("There was an error registering the Voice Command Definitions", ex);
        }
    }

然后重写 App.OnActivated 方法来处理事件触发时:

    protected override void OnActivated(IActivatedEventArgs e)
    {
        // Handle when app is launched by Cortana
        if (e.Kind == ActivationKind.VoiceCommand)
        {
            VoiceCommandActivatedEventArgs commandArgs = e as VoiceCommandActivatedEventArgs;
            SpeechRecognitionResult speechRecognitionResult = commandArgs.Result;

            string voiceCommandName = speechRecognitionResult.RulePath[0];
            string textSpoken = speechRecognitionResult.Text;
            IReadOnlyList<string> recognizedVoiceCommandPhrases;

            System.Diagnostics.Debug.WriteLine("voiceCommandName: " + voiceCommandName);
            System.Diagnostics.Debug.WriteLine("textSpoken: " + textSpoken);

            switch (voiceCommandName)
            {
                case "Activate_Alarm":
                    System.Diagnostics.Debug.WriteLine("Activate_Alarm command");
                    break;

要查看完整的教程,请访问此link,工作项目是here。此外,如果您有兴趣通过 Cortana 窗口回复用户,请查看此 post 关于后台 Cortana 的信息

【讨论】:

    【解决方案4】:

    我认为您缺少命令的一部分。

    您要求 Cortana 将度数转换为华氏度,但程序很混乱,因为您不够具体。

    如果你想让 Cortana 从摄氏度转换为华氏度,你必须明确告诉它摄氏到华氏度。

    【讨论】:

      猜你喜欢
      • 2016-02-22
      • 2016-01-31
      • 2017-10-15
      • 2016-07-22
      • 2018-11-09
      • 2016-05-24
      • 1970-01-01
      • 1970-01-01
      • 2020-11-15
      相关资源
      最近更新 更多