Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Habilitación de voz de una aplicación de Windows Phone 8 con comandos de voz
Descargar el ejemplo de código
Una tarde, hace poco, iba tarde a reunirme, después de trabajar, con un viejo amigo. Sabía que él ya estaba conduciendo al lugar de nuestro encuentro, de manera que no podía llamarlo. Sin embargo, mientras salía de mi oficina y me dirigía a mi automóvil, tomé mi Windows Phone y presioné el botón Inicio. Cuando escuché la solicitud de escucha "earcon", dije "Texto Robert Brown" y, cuando se inició la aplicación de mensajes de texto, dije "Salí tarde, estoy saliendo de la oficina ahora", seguido por "enviar", para enviar el mensaje de texto.
Sin las características de habla en la aplicación de mensajes de texto integrada, habría debido detenerme y manipular de forma frustrante y torpe el móvil para enviar el texto, puesto que me parece difícil usar el teclado con mis dedos gordos, además que la pantalla me parece difícil de leer mientras se está apurado. El uso de habla a texto me ahorró tiempo, frustración y no poca ansiedad.
Windows Phone 8 ofrece estas mismas características de habla para que los desarrolladores interactúen con sus usuarios mediante reconocimiento de texto y texto a habla. Estas características son compatibles con los dos escenarios ilustrados en mi ejemplo: Desde cualquier parte en el teléfono, el usuario puede decir un comando para iniciar una aplicación y llevar a cabo una acción con solo un enunciado y, una vez en la aplicación, el teléfono lleva a cabo un diálogo con el usuario para capturar comandos o texto de los enunciados del hablante y al representar de forma audible el texto de las notificaciones y comentarios para el usuario.
El primer escenario es compatible con una característica llamada comandos de voz. Para habilitar esta característica, la aplicación proporciona un archivo de definición de comando de voz (Voice Command Definition, VCD) para especificar una serie de comandos que la aplicación está equipada para controlar. Cuando se inicia la aplicación con comandos de voz, recibe parámetros en un subproceso de consulta, como lo son el nombre de comando, nombres de parámetros y el texto reconocido que se puede usar para ejecutar el comando especificado por el usuario. La primera parte del artículo de dos partes explica cómo habilitar comandos de voz en su aplicación de Windows Phone 8.
En la segunda parte, se analizará el diálogo de habla integrado a la aplicación. Para dar compatibilidad a esto, Windows Phone 8 proporciona una API para reconocimiento y síntesis de habla. Esta API incluye una UI predeterminada para confirmación y desambiguación, además de valores predeterminados para gramáticas de habla, tiempos de expiración y otras propiedades, lo que hace posible agregar reconocimiento de habla a una aplicación con pocas líneas de código. De forma similar, la API de síntesis de habla (también conocida como texto a habla, o TTS) es fácil de construir en código para escenarios simples, también proporciona características avanzadas, tales como la manipulación detallada mediante el lenguaje de marcado de síntesis de habla (Speech Synthesis Markup Language, SSML) de World Wide Web Consortium y cambiar entre voces de usuarios finales que ya están en el teléfono o descargados desde el catálogo de soluciones. Manténgase atento, que se hará una exploración detallada de esta característica en el siguiente artículo.
Para demostrar estas características, desarrollé una aplicación simple denominada Magic Memo. Puede lanzar Magic Memo y ejecutar un comando al presionar el botón Inicio y después enunciar un comando cuando se lo solicite. Dentro de la aplicación, puede introducir su nota usando simplemente mediante dictado o puede navegar dentro de la aplicación y ejecutar comandos usando habla. A través de este artículo, explicaré el código fuente que implementa estas características.
Requisitos para usar características de habla en aplicaciones
La aplicación Magic Memo debiera funcionar tal como está, dando por sentado que su entorno de desarrollo satisface los requisitos de hardware y software para desarrollar aplicaciones de Windows Phone 8 y probarlas en el emulador de teléfono. Cuando se publicó este artículo, los requisitos eran los siguientes:
- Versión de 64 bits de Windows 8 Pro o superior
- 4 GB o más de RAM
- Traducción de direcciones de segundo nivel con compatibilidad con la BIOS
- Hyper-V instalado y funcionando
- Visual Studio 2012 Express para Windows Phone o superior
Como siempre, es recomendable revisar su documentación de MSDN para los últimos requisitos antes de intentar desarrollar y ejecutar su aplicación.
Tres otras cosas que debe tener en mente al desarrollar su propia aplicación de cero:
Asegúrese de que el micrófono y el parlante del dispositivo estén funcionando correctamente.
Agregue capacidades de reconocimiento de habla y micrófono al archivo WpAppManifest.xml, ya sea al comprobar las casillas adecuadas en el editor de propiedades o manualmente, al incluir lo siguiente en el archivo XML:
<Capability Name="ID_CAP_SPEECH_RECOGNITION" />
<Capability Name="ID_CAP_MICROPHONE"/>Al intentar el reconocimiento de habla, debe captar la excepción que aparece cuando el usuario no ha aceptado la directiva de privacidad de habla. El asistente de la función GetNewMemoByVoice en MainPage.xaml.cs en la siguiente descarga de código de muestra entrega un ejemplo de como hacer esto.
El escenario
En cualquier smartphone, un escenario común es lanzar una aplicación y ejecutar un solo comando, opcionalmente seguido por más comandos. Hacer esta operación de forma manual requiere varios pasos: encontrar la aplicación, navegar al lugar correcto, encontrar el botón o elemento de menú, darle un toque, etc. Muchos usuarios sienten que esto es frustrante, incluso después de que se han acostumbrado a estos pasos.
Por ejemplo, para mostrar una nota guardada, por ejemplo, nota número 12, en la aplicación de muestra de Magic Memo, el usuario debe encontrar y lanzar la aplicación, tocar "Ver notas guardadas" y desplazarse hacia abajo hasta que se muestre la nota deseada. Compare esto con la experiencia de usar la característica de comandos de voz de Windows Phone 8: El usuario mantiene presionado el botón Inicio y dice "Magic Memo, muestra nota 12", después de lo cual, la aplicación Magic Memo se inicia y la nota deseada se muestra en un cuadro de mensaje. Incluso para este sencillo comando, existe una forma clara de disminuir la interacción del usuario.
Hay tres pasos para implementar comandos de voz en una aplicación y un cuarto paso adicional para controlar contenido dinámico. Las siguientes secciones detallan esos pasos.
Especificar los comandos de usuario por reconocer
El primer paso para implementar los comandos de voz es especificar los comandos para que escuchen en un archivo VCD. Un archivo VCD se escribe en un formato XML simple, que consiste de una colección de elementos CommandSet, cada uno con elementos Command secundarios que contienen las frases por escuchar. Un ejemplo de la aplicación Magic Memo se muestra en la Figura 1.
Figura 1 Archivo de definición de comandos de voz de la aplicación Magic Memo
<?xml version="1.0" encoding="utf-8"?>
<VoiceCommands xmlns="https://schemas.microsoft.com/voicecommands/1.0">
<CommandSet xml:lang="en-us" Name="MagicMemoEnu">
<!-- Command set for all US English commands-->
<CommandPrefix>Magic Memo</CommandPrefix>
<Example>enter a new memo</Example>
<Command Name="newMemo">
<Example>enter a new memo</Example>
<ListenFor>Enter [a] [new] memo</ListenFor>
<ListenFor>Make [a] [new] memo</ListenFor>
<ListenFor>Start [a] [new] memo</ListenFor>
<Feedback>Entering a new memo</Feedback>
<Navigate /> <!-- Navigation defaults to Main page -->
</Command>
<Command Name="showOne">
<Example>show memo number two</Example>
<ListenFor>show [me] memo [number] {num} </ListenFor>
<ListenFor>display memo [number] {num}</ListenFor>
<Feedback>Showing memo number {num}</Feedback>
<Navigate Target="/ViewMemos.xaml"/>
</Command>
<PhraseList Label="num">
<Item> 1 </Item>
<Item> 2 </Item>
<Item> 3 </Item>
</PhraseList>
</CommandSet>
<CommandSet xml:lang="ja-JP" Name="MagicMemoJa">
<!-- Command set for all Japanese commands -->
<CommandPrefix>マジック・メモ</CommandPrefix>
<Example>新規メモ</Example>
<Command Name="newMemo">
<Example>新規メモ</Example>
<ListenFor>新規メモ[を]</ListenFor>
<ListenFor>新しいメモ</ListenFor>
<Feedback>メモを言ってください</Feedback>
<Navigate/>
</Command>
<Command Name="showOne">
<Example>メモ1を表示</Example>
<ListenFor>メモ{num}を表示[してください] </ListenFor>
<Feedback>メモ{num}を表示します。 </Feedback>
<Navigate Target="/ViewMemos.xaml"/>
</Command>
<PhraseList Label="num">
<Item> 1 </Item>
<Item> 2 </Item>
<Item> 3 </Item>
</PhraseList>
</CommandSet>
</VoiceCommands>
A continuación se muestran las directrices para diseñar un archivo VCD:
- Mantenga el prefijo del comando fonéticamente distinto de las palabras clave de Windows Phone. Esto le ayudará a evitar confusiones entre su aplicación y su característica de teléfono. Para inglés estadounidense, las palabras clave son call (llamar), dial (discar), start (iniciar), open (abrir), find (buscar), text (enviar mensaje de texto), note (tomar nota) y help (ayuda).
- Haga que su prefijo de comando sea un subconjunto o una pronunciación natural del nombre de la aplicación, en lugar de hacerlo algo diferente. Esto evitará la confusión del usuario y reducirá la posibilidad de problemas de reconocimiento de su aplicación por otra aplicación o característica.
- Tenga en cuenta que el reconocimiento exige una coincidencia exacta del sufijo de comando. Por lo tanto, es una buena idea mantener el prefijo de comando simple y fácil de recordar.
- De a cada comando establecido un atributo Name, de manera que pueda obtener acceso a ello desde su código.
- Mantenga los elementos ListenFor en elementos de comando fonéticamente distintos de los otros para evitar las posibilidades de error de reconocimiento.
- Asegúrese de que los elementos ListenFor en el mismo comando sean distintas maneras de especificar el mismo comando. Si los elementos ListenFor de un comando corresponden a más de una acción, sepárelas en comandos distintos. Esto facilitará el controlar los comandos en su aplicación.
- Tenga en cuenta los límites: 100 elementos Command en un conjunto de comando; 10 entradas ListenFor en un comando; 50 elementos PhraseList en total y 2.000 elementos PhraseList en total en todas las PhraseList.
- Tenga en cuenta que el reconocimiento de elementos de PhraseList exige una coincidencia exacta y no un subconjunto. Por lo tanto, para reconocer tanto "Star Wars" y "Star Wars, Episodio Uno", debe incluirlos a ambos como elementos PhraseList.
En mi ejemplo hay dos elementos CommandSet, cada uno con distintos atributos xml:lang y Name. Solo puede haber un CommandSet por valor xml:lang. Los atributos Name deben ser únicos, pero están restringidos solo por la especificación de valor del atributo Name. Aunque sea opcional, es altamente recomendable incluir un atributo Nombre, porque lo necesitará para obtener acceso a CommandSet desde su código de aplicación para implementar el paso 4. También observe que solo un CommandSet está activado para su aplicación en un momento dado, específicamente aquel cuyo atribuye xml:lang coincide exactamente con el del reconocedor de habla global actual, como lo configura el usuario en SETTINGS/speech. Debe incluir CommandSets en cualquier idioma en que espere que sus usuarios necesiten en su mercado.
Lo siguiente que debe notar es el elemento CommandPrefix. Considérelo como un alias que el usuario puede decir para invocar su aplicación. Esto es útil si su nombre de aplicación tiene caracteres estándares o no pronunciables, tales como Mag1a o 0nd4. Recuerde que esta palabra o frase debe ser algo que el motor de reconocimiento de habla pueda reconocer y que debe ser fonéticamente diferente a las palabras clave integradas de Windows Phone.
Notará que hay elementos Example secundarios en tanto el elemento CommandSet y el elemento Command. El Example en CommandSet es un ejemplo general de su aplicación que mostrará la pantalla de ayuda del sistema ¿Qué puedo decir? como se muestra en la Figura 2. En contraste, el elemento Example en Command es específico de ese Command. Este Example aparece en una página de ayuda de sistema (ver Figura 3) que se muestra cuando el usuario toca el nombre de la aplicación en la página de ayuda, la cual se muestra en la Figura2.
Figura 2 La página de ayuda muestra ejemplos de comandos de voz para aplicaciones instaladas
Figura 3 Página de ejemplo para comandos de voz de Magic Memo
Hablando de esto, cada elemento secundario Command con un CommandSet se corresponde con una acción que se debe tomar en la aplicación una vez que se lanzó. Pueden haber varios elementos ListenFor en un Command, pero todos debieran ser distintas maneras de decirle a la aplicación cómo llevar a cabo la acción (command) de lo cual estos elementos son secundarios.
Observe también que el texto en un elemento ListenFor tiene dos construcciones especiales. Los corchetes alrededor del texto implica que el texto es opcional, es decir, que el enunciado del usuario se puede reconocer con o sin el texto entre corchetes. Las llaves de cierre contienen una etiqueta que hace referencia a un elemento PhraseList. En el ejemplo de inglés estadounidense de la Figura 1, el primer ListenFor en el comando "showOne" tiene una etiqueta {num} que hace referencia a la lista de frases debajo de ella. Puede imaginarse esto como si se pudiera llenar con cualquier frase de la lista referida; en este caso serían números.
¿Qué ocurre cuando un comando se reconoce en el enunciado del usuario? El reconocedor de habla global del teléfono lanzará la aplicación en la página especificada en el atributo Target del elemento Navigate bajo el Command correspondiente, como se explica más tarde en el paso 3, pero antes de eso, analizaremos el paso 2.
Habilitar comandos de voz
Al incluir el archivo VCD en su paquete de instalación, el paso 2 es registrar el archivo, de manera que Windows Phone 8 pueda incluir los comandos de la aplicación en la gramática del sistema. Puede hacer esto al llamar un método estático InstallCommandSetsFromFileAsync en la clase VoiceCommandService, como se muestra en la Figura 4. Muchas aplicaciones harán este llamado en el primer intento, pero, por supuesto, se puede hacer en cualquier momento. La implementación de VoiceCommandService es suficientemente inteligente para hacer nada en llamadas posteriores si no hubiese cambios en el archivo, de manera que no debe preocuparse del hecho de que se llama en cada inicio de la aplicación.
Figura 4 Inicialización del archivo VCD desde el interior de la aplicación
using Windows.Phone.Speech.VoiceCommands;
// ...
// Standard boilerplate method in the App class in App.xaml.cs
private async void Application_Launching(object sender,
LaunchingEventArgs e)
{
try // try block recommended to detect compilation errors in VCD file
{
await VoiceCommandService.InstallCommandSetsFromFileAsync(
new Uri("ms-appx:///MagicMemoVCD.xml"));
}
catch (Exception ex)
{
// Handle exception
}
}
Como el nombre del método InstallCommandSetsFromFileAsync podría sugerir, la unidad operativa en el archivo VCD es un elemento CommandSet en lugar del archivo mismo. La llamada de este método inspecciona y valida todos los conjuntos de comando contenidos en el archivo, pero instala solo aquel método cuyo atributo xml:lang coincida exactamente con el motor de habla global. Si el usuario cambia el lenguaje de reconocimiento global a uno que coincida con el xml:lang de un CommandSet distinto en su VCD, ese CommandSet se cargará y activará.
Controlar un comando de voz
Ahora analizaré el paso 3. Cuando el reconocedor de habla global reconoce el prefijo de comando y un comando de su aplicación, lanzará la aplicación en la página especificada en el atributo Target del element Navigate, usando su destino de tareas predeterminado (generalmente eso es MainPage.xaml para aplicaciones de Silverlight) si no hay un blanco especificado. También adjunta a la consulta pares de clave/valor de subproceso del nombre Command y los valores PhraseList. Por ejemplo, si la frase reconocida es "Magic Memo mostrar nota número tres", entonces la consulta se vería algo así (el subproceso real puede variar de acuerdo con la implementación o versión):
"/ViewMemos.xaml?voiceCommandName=show&num=3&reco=show%20memo%20number%20three"
Afortunadamente, no necesita analizar el subproceso de consulta y retirar los parámetros usted mismo, puesto que están disponibles en la colección QueryString del objeto NavigationContext. La aplicación puede usar estos datos para determinar si se lanzó por comando de voz y, si es así, controlar el comando de forma apropiada (por ejemplo, en el controlador Loaded de la página). La Figura 5 muestra un ejemplo de la aplicación Magic Memo de la página ViewMemos.xaml.
Figura 5 Control de comandos de voz en una aplicación
// Takes appropriate action if the application was launched by voice command.
private void ViewMemosPage_Loaded(object sender, RoutedEventArgs e)
{
// Other code omitted
// Handle the case where the page was launched by Voice Command
if (this.NavigationContext.QueryString != null
&& this.NavigationContext.QueryString.ContainsKey("voiceCommandName"))
{
// Page was launched by Voice Command
string commandName =
NavigationContext.QueryString["voiceCommandName"];
string spokenNumber = "";
if (commandName == "showOne" &&
this.NavigationContext.QueryString.TryGetValue("num",
out spokenNumber))
{
// Command was "Show memo number 'num'"
int index = -1;
if (int.TryParse(spokenNumber, out index) &&
index <= memoList.Count && index > 0)
{ // Display the specified memo
this.Dispatcher.BeginInvoke(delegate
{ MessageBox.Show(String.Format(
"Memo {0}: \"{1}\"", index, memoList[index - 1])); });
}
}
// Note: no need for an "else" block because if launched by another VoiceCommand
// then commandName="showAll" and page is shown
}
}
Dado que hay más de una manera de navegar en cualquier página, el código de la Figura 5 comprueba primero la presencia de la clave voiceCommandName en el subproceso de consulta para determinar si el usuario lanzó la aplicación en un comando de voz. Si es así, comprobará el nombre de comando y obtendrá el valor del parámetro num de PhraseList, que es el número de la nota que el usuario desea ver. Esta página solo tiene dos comandos de voz y el procesamiento es simple, pero una página que se puede lanzar a partir de muchos comandos de voz debiera usar algo así como un bloque switch en commandName para decidir la acción a tomar.
PhraseList, en este ejemplo, también es algo sencillo, es solo una serie de números, uno para cada nota almacenada. Vale decir que puede planificar escenarios más sofisticados, que requieren listas de frases que se rellenan de forma dinámica, por ejemplo, de datos en un sitio web. El paso opcional 4 que se mencionó anteriormente detalla cómo implementar PhraseList para esos escenarios. Analizaré esto a continuación.
Actualizar listas de frases de su aplicación
Puede que haya observado un problema con el archivo VCD en la Figura 1: La PhraseList "num" definida estadísticamente en VCD es compatible con reconocimiento de hasta tres elementos, pero es posible que en algún momento hayan considerablemente más de tres notas almacenadas en el almacenamiento aislado de la aplicación. Para casos de uso donde la lista de frases cambia con el tiempo, hay una manera de actualizar la lista de frases de forma dinámica en la aplicación, como se muestra en la Figura 6. Esto es especialmente útil para aplicaciones que necesitan hacer reconocimiento para contrastaciones de listas dinámicas, como películas descargadas, restaurantes o puntos de interés favoritos en la proximidad de la ubicación actual del teléfono.
Figura 6 Actualización de las listas de frases instaladas dinámicamente
// Updates the "num" PhraseList to have the same number of
// entries as the number of saved memos; this supports
// "Magic Memo show memo 5" if there are five or more memos saved
private async void UpdateNumberPhraseList(string phraseList,
int newLimit, string commandSetName)
{
// Helper function that sets string array to {"1", "2", etc.}
List<string> positiveIntegers =
Utilities.GetStringListOfPositiveIntegers(Math.Max(1, newLimit));
try
{
VoiceCommandSet vcs = null;
if (VoiceCommandService.InstalledCommandSets.TryGetValue(
commandSetName, out vcs))
{
// Update "num" phrase list to the new numbers
await vcs.UpdatePhraseListAsync(phraseList, positiveIntegers);
}
}
catch (Exception ex)
{
this.Dispatcher.BeginInvoke(delegate
{ MessageBox.Show("Exception in UpdateNumberPhraseList "
+ ex.Message); }
);
}
}
Aunque la aplicación Magic Memo no lo demuestre, las listas de frases actualizadas automáticamente son candidatas perfectas para actualizaciones en un agente de usuario, debido a que la actualización puede ocurrir detrás de bambalinas, incluso si no se está ejecutando la aplicación.
Y ya lo tiene: cuatro pasos para habilitar comandos de voz en su aplicación. Realice la comprobación con la aplicación de ejemplo Magic Memo. Recuerde que debe ejecutarlo una vez de forma normal para cargar el archivo VCD, pero después de eso, puede decir cosas tales como las siguientes para lanzar la aplicación e ir directamente a una página y realizar el comando:
- Magic Memo, introducir una nota nueva
- Magic Memo, mostrar todas las notas
- Magic Memo, mostrar nota número cuatro
Siguiente paso: Diálogo interno de la aplicación
La implementación de comandos de voz, como se discutió en este artículo, es el primer paso para dejar que sus usuarios interactúen con su aplicación en Windows 8, tal como pueden hacerlo con aplicaciones integradas, tales como mensajes de texto, buscar y llamar.
El segundo paso es proporcionar diálogos integrados a la aplicación, donde el usuario habla a la aplicación después que se inició para registrar textos o ejecutar comandos y recibir respuestas de audio en forma de texto hablado. Profundizaré en ese tema durante la parte 2, así que manténgase conectado.
F Avery Bishop ha trabajado en desarrollo de software por más de 20 años, de los cuales ha dedicado 12 a Microsoft, donde es administrador de programa para la plataforma de habla. Ha publicado muchos artículos acerca de compatibilidad de lenguaje natural en aplicaciones, lo que incluye temas tales como compatibilidad con scripts complejos, aplicaciones multilingües y reconocimiento de habla.
Gracias a los siguientes expertos técnicos por su ayuda en la revisión de este artículo: Robert Brown, Victor Chang, Jay Waltmunson y Travis Wilson