En un post anterior contaba cómo crear una Alexa skill de audio siguiendo una serie de pasos y usando para el back un código ya creado por mi. Ese tipo de skills que hacen streaming de audio usan la interfaz AudioPlayer de Alexa. El uso de AudioPlayer no es complicado pero todo lo que quiero contar da para varios artículos.

En este primer post voy a hacer una introducción al AudioPlayer y explicar en qué consiste su funcionamiento. Es un caso bastante particular con respecto al uso habitual de skills. Iré soltando muchos conceptos que enlazaré con la documentación oficial. Para terminar indicaré cómo habilitar la interfaz en una skill y qué efectos tiene eso en el modelo de interacción.

La carga de trabajo de este tipo de skills recae en el back y es lo que iremos viendo en futuros artículos donde podré detallar y explicar bien todo lo contado en esta introducción.

Interfaz AudioPlayer

¿Qué es?

La interface de AudioPlayer nos permite crear skills que reproduzcan audio y nos ofrece información sobre el estado de la reproducción, playback, para que nosotros en el back podamos reaccionar a eso en caso necesario.

El AudioPlayer se puede controlar tanto por voz como por botones o vía táctil. Dependiendo del origen de la acción que hagamos sobre el audio nos llegarán distintos tipos de requests al back.

En el código que tengo publicado se recogen la mayoría de eventos relacionados con el playback, así como intents específicos para el control del audio. Lo que no tengo cubierto en mi ejemplo de código son eventos de botones/táctiles pero los comentaré igualmente aquí porque añadirlo es trivial.

¿Cómo funciona?

La interfaz de AudioPlayer habilita una forma bastante particular de usar Alexa e interactuar con una skill. El punto de entrada inicial siempre va a ser arrancar la skill de forma normal con su nombre de invocación. Una vez que un audio se reproduzca a partir de nuestra skill, Alexa de forma nativa tomará el control del resto de interacciones sin que el usuario tenga que volver a invocar la skill. Además de esto vamos a tener eventos que van a llegar al back cuando pasen ciertas cosas, así como comandos si se está usando una interfaz táctil.

Por tanto, si tuviéramos una skill que reproduce un audio pasaría lo siguiente:

  • El usuario invoca la skill y se empieza a reproducir un audio. Para ello se usa una directiva, AudioPlayerPlayDirective, desde el back. Se finaliza la sesión y toma el control Alexa. De esta forma ya no estamos en el contexto de nuestra skill.
  • A partir de este momento podemos hacer uso de ciertos built-in intents, predefinidos por Amazon, para manejar el audio en curso (pausar, parar, repetir desde el principio, etc). Por ejemplo el usuario va a poder decir: "Alexa, para" o "Alexa, siguiente", sin invocar a la skill.
  • Igualmente, si tenemos un dispositivo con pantalla, podremos hacer uso de los controles del reproductor de audio. Este controlador enviará distintos comandos por cada operación elegida. Ejemplos aquí serían los típicos botones de cualquier reproductor multimedia.
  • También, de forma transparente para el usuario, Alexa va enviando eventos al back de la skill que inició la reproducción del audio. Estos eventos están asociados a distintas cosas como, por ejemplo, la reproducción del audio comenzó o falló, la reproducción se ha parado, está a punto de finalizar, ha finalizado, etc

Un apunte importante aquí: Amazon deja en manos del desarrollador toda la gestión de saber identificar qué audio se ha pausado/ se quiere retomar, en qué offset, cuál sería el siguiente audio o el anterior a reproducir, etc. Cada evento de playback o intent predefinido (como Resume/Previous/Next/Pause) ocurren fuera del contexto de una skill abierta y, por tanto, no tienen información de sesión con lo que no podemos hacer uso de los atributos de ese tipo en estas skills. Esto hace inevitable tirar de algún tipo de solución de persistencia. En mi caso uso DynamoDB.

La "magia" en este tipo de skills radica en cómo Alexa gestiona la reproducción del audio. Una vez que una skill lanza la directiva de play y comienza el playback del audio, Alexa va a recordar esa skill. Gracias a eso, si el usuario dice: "Alexa, siguiente", se generará una petición de Amazon.NextIntent al back de la skill correcta. Y esto puede ocurrir al poco tiempo de haber usado la skill o mucho después.

Alexa va a recordar la última skill que reprodujo audio y, de esta forma, va a poder enviarle built-in intents sin necesidad de usar el nombre de invocación. Si, por ejemplo, usamos la skill de "el informativo de Ángel Martín" por la mañana y por la tarde, sin usar el nombre de invocación, decimos: "Alexa, anterior", la skill del informativo recibirá la petición e intentará enviar el nuevo audio correspondiente.

Para "olvidar" esta última skill que reprodujo audio tiene que pasar uno de los siguientes casos:

  • Que el usuario use otra skill con AudioPlayer que reproduzca audio.
  • Que el usuario use algún servicio nativo de audio,  como el de música o los resúmenes de noticias.
  • Que el usuario reinicie el dispositivo.

Requisitos para reproducir una audio

Lo que se le proporciona a Alexa para reproducir el audio es una URL que tiene que cumplir ciertos requisitos:

  • El fichero tiene que estar alojado en un endpoint accesible por https en el puerto 443.
  • El servidor web debe presentar un certificado SSL válido y de confianza. La mayoría de servicios de almacenamiento son validos como S3 o Dropbox. Yo he usado ambos sin problema.
  • Si lo que se envía es la URL de una playlist, lo anterior aplica a cada elemento de la misma.
  • Formatos soportados: AAC/MP4, MP3, PLS, M3U/M3U8, and HLS. Bitrates: 16kbps to 384 kbps.

Habilitar la interfaz de AudioPlayer en tu skill

Para que un skill pueda usar la interfaz de AudioPlayer primero tenemos que activarla en el listado de interfaces posibles a implementar. Desde la Alexa Developer Console, dentro de la skill, vamos a Custom > Interfaces.

Al activarla veremos que se añaden dos nuevos built-in intents, predefinidos por Amazon, para las acciones de pausar (Amazon.PauseIntent) y de reanudar (Amazon.ResumeIntent). Estos los tendremos que tener en cuenta de forma obligatoria en nuestro back y manejarlos correctamente. Cualquier cosa que se nos pase la detectarán en el proceso de certificación y nos informarán.

Aparte de estos dos built-in intents obligatorios se recomienda que una skill de audio controle sin fallar otros tantos intents listados en la documentación oficial de Alexa. Estos otros intents no hay que definirlos en el modelo de interacción, simplemente manejarlos en el back.

En mi caso no los he controlado nunca todos y eso no ha supuesto un problema en el proceso de certificación. Serían:

  • AMAZON.CancelIntent > Lo he usado para cancelar el audio que en ese momento esté sonando.
  • AMAZON.LoopOffIntent > No lo he usado. Sería para desactivar la reproducción en bucle.
  • AMAZON.LoopOnIntent > No lo he usado. Sería para activar la reproducción en bucle.
  • AMAZON.NextIntent > Lo he usado, en la skill del informativo de Ángel Martín, para reproducir el resumen del día siguiente, a modo playlist.
  • AMAZON.PreviousIntent > Lo he usado, en la skill del informativo de Ángel Martín, para reproducir el resumen del día anterior, a modo playlist.
  • AMAZON.RepeatIntent > Lo he usado para repetir desde el principio el audio que estuviera sonando en el momento.
  • AMAZON.ShuffleOffIntent > No lo he usado. Sería para desactivar el modo aleatorio.
  • AMAZON.ShuffleOnIntent > No lo he usado. Sería para activar el modo aleatorio.
  • AMAZON.StartOverIntent > Lo he usado para repetir desde el principio el audio que estuviera sonando en el momento.

En el siguiente post comenzaré a explicar cómo manejar en back cada uno de los tipos de interacciones que hemos visto aquí: built-in intents, eventos del playback y comandos del reproductor.

Hay bastante chicha con todo el AudioPlayer y nos dará para unos cuantos artículos. Cero aburrimiento :)