我正在尝试为Cortana编写一个小型应用程序。
我的想法是,我说:(我启用了"嘿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();
}
}
}
有人能帮助我吗?
答案 0 :(得分:2)
您上面列出的VCD定义文件没有PhraseTopic或PhraseList来定义大括号中的部分:
<ListenFor> {farenheit} farenheit to degrees </ListenFor>
我猜你可能想要一个PhraseTopic,因为它允许一个适用于各种数字的无约束的听写,如下所示:
<PhraseTopic Label="farenheit" Scenario="Dictation">
<Subject>Temperature</Subject>
</PhraseTopic>
请参阅VCD的here on msdn规范,您可能想要调整Scenario值。这确实意味着你需要自己处理你所获得的文本作为farenheit术语,当然,通常用文本'1234'形式来指示数字的文本(但不是在100%的情况下)。
答案 1 :(得分:0)
检查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
答案 2 :(得分:0)
嗯......似乎你已经理解了所有步骤,但仍然缺少某些东西......
以下是我对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窗口回复用户,请在背景中查看关于Cortana的post
答案 3 :(得分:0)
我认为你错过了命令的一部分。
你要求Cortana将学位转换为华氏度,而且程序很混乱,因为你不够具体。
如果你想让Cortana从摄氏度转换到华氏度,你必须告诉它具体摄氏度到华氏度。