Alexa skills de audio con la interfaz AudioPlayer: eventos de playback (III)
Tags: audioplayer, alexa
Published: 2021-08-31 17:21:46

---
title: Alexa skills de audio con la interfaz AudioPlayer: eventos de playback (III)
published: true
date: 2021-01-13 09:27:07 UTC
tags: audioplayer,alexa
canonical_url: https://www.kinisoftware.com/usando-audio-player-interface-iii/
---

 ![Alexa skills de audio con la interfaz AudioPlayer: eventos de playback (III)](https://images.unsplash.com/photo-1557077316-a5212159d3bf?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MXwxMTc3M3wwfDF8c2VhcmNofDF8fHBsYXliYWNrfGVufDB8fHw&ixlib=rb-1.2.1&q=80&w=1080)

En [esta](https://dev.to/kini/usando-la-interfaz-audioplayer-para-crear-alexa-skills-que-reproducen-audio-i-ip4-temp-slug-4555321) [serie](https://dev.to/kini/alexa-skills-de-audio-con-la-interfaz-audioplayer-directivas-ii-pjm-temp-slug-6616636) de artículos estoy contando todo lo que necesitas saber para usar la [interfaz AudioPlayer](https://developer.amazon.com/en-US/docs/alexa/custom-skills/audioplayer-interface-reference.html) en tus skills. Es una funcionalidad de Alexa que tiene bastante por detrás y le dedicaré varios posts.

En esta tercera entrega voy a hablar de los eventos que se producen relacionados con la reproducción de audio en un dispositivo Alexa, también denominados [eventos de playback](https://developer.amazon.com/en-US/docs/alexa/custom-skills/audioplayer-interface-reference.html#requests).

## Eventos de Playback

Estos eventos son simplemente peticiones que nos llegarán al back de la skill y nos informan de cambios de estado en la reproducción del audio. Son emitidos por el reproductor nativo de Alexa y llegarán a la skill sin necesidad de tener una sesión abierta.

El back de nuestra skill tiene la responsabilidad de manejar correctamente cada uno de los eventos de manera que no influya de forma negativa en la reproducción en curso. El uso de cada evento dependerá de la skill que tengamos entre manos y a veces bastará con generar una respuesta vacía. Además, no podemos responder a estos eventos con una respuesta estándar que contenga texto para Alexa. Solo podemos responder con las directivas de AudioPlayer que vimos en el artículo anterior.

Como decía antes, estos eventos no van a llevar información de sesión pero sí que tendrán información de contexto con lo que podremos sacar de ahí, por ejemplo, la info del `userId`. Esta información la usaremos para la capa de persistencia.

Los tipos de eventos son:

- `AudioPlayer.PlaybackStarted` > Se envía cuando el audio indicado por la directiva de `Play` ha comenzado a reproducirse de forma exitosa.
- `AudioPlayer.PlaybackFinished` > Vamos a recibir este evento cuando la reproducción finalice.
- `AudioPlayer.PlaybackStopped` > Alexa lo envía para responder a la directiva de `Stop` al parar el audio que se estaba reproduciendo.
- `AudioPlayer.PlaybackNearlyFinished` > Se envía para indicar que la reproducción en curso está próxima a terminar.
- `AudioPlayer.PlaybackFailed` > Indica que no se pudo reproducir el audio indicado debido a algún problema.

Los cuatro primeros eventos tienen la misma información en la petición:

```
{
  "type": "AudioPlayer.[type]",
  "requestId": "unique.id.for.the.request",
  "timestamp": "timestamp of request in format: 2018-04-11T15:15:25Z",
  "token": "token representing the currently playing stream",
  "offsetInMilliseconds": 0,
  "locale": "a locale code such as en-US"
}
```

En el caso de uso de nuestra skill, por el modelo de datos persistente, nos vendrá bien la información del campo `offsetInMilliseconds` que indica en qué punto de reproducción está el audio en cuestión. Para una explicación del resto de campos os enlazaré la documentación oficial según los detalle.

Para el evento de `AudioPlayer.PlaybackFailed`, además de lo anterior, vamos a tener información del error y del estado del playback en el momento que ocurre el problema. Lo veremos en su propio apartado.

### AudioPlayer.PlaybackStarted

Al recibir [este evento](https://developer.amazon.com/en-US/docs/alexa/custom-skills/audioplayer-interface-reference.html#playbackstarted) tendremos la confirmación de que el audio que se indicó en la directiva `Play` ha comenzado su reproducción sin problemas. Alexa lo envía tanto si se ha iniciado un audio desde su inicio, como si hemos continuado un audio que estaba pausado.

A la hora de responder a este tipo de eventos tenemos varias opciones:

- Usar las directivas de AudioPlayer `Stop` o `ClearQueue`.
- Cualquier otro tipo de respuesta que NO contenga un texto para Alexa u otras directivas ([como las de Dialog Management](https://dev.to/kini/dialog-management-en-alexa-introduccion-y-referencias-21a4)).

Una respuesta básica válida podría ser (en Kotlin):

{% gist https://gist.github.com/kinisoftware/7276f02879729b45931f27229b02c625 %}

Veremos el caso concreto de nuestra skill de ejemplo en otro post.

### AudioPlayer.PlaybackFinished

Alexa envía [esta petición](https://developer.amazon.com/en-US/docs/alexa/custom-skills/audioplayer-interface-reference.html#playbackfinished) cuando el audio finaliza por haber llegado al final de la reproducción del mismo.

A la hora de responder a este tipo de eventos tenemos varias opciones:

- Usar las directivas de AudioPlayer `Stop` o `ClearQueue`.
- Cualquier otro tipo de respuesta que NO contenga un texto para Alexa u otras directivas ([como las de Dialog Management](https://dev.to/kini/dialog-management-en-alexa-introduccion-y-referencias-21a4)).

Una respuesta básica válida podría ser (en Kotlin):

<script src="https://gist.github.com/kinisoftware/7276f02879729b45931f27229b02c625.js"></script>

En nuestro ejemplo no necesitaremos manejar este evento para dar una respuesta distinta a la anterior.

### AudioPlayer.PlaybackStopped

El back recibirá [esta petición](https://developer.amazon.com/en-US/docs/alexa/custom-skills/audioplayer-interface-reference.html#playbackstopped) como respuesta a:

- Diretiva de`Stop` .
- Directiva de `Play` indicando un comportamiento de `REPLACE_ALL` .
- Directiva de `ClearQueue` con un comportamiento de `CLEAR_ALL` .
- Durante una reproducción de audio en curso el usuario hace una petición a Alexa, con lo que el audio se pausa de forma momentánea.

A este tipo de eventos solo está permitido responder algo básico (en Kotlin):

{% gist https://gist.github.com/kinisoftware/7276f02879729b45931f27229b02c625 %}
### AudioPlayer.PlaybackNearlyFinished

Se envía cuando la reproducción está llegando a su fin, siendo [un evento](https://developer.amazon.com/en-US/docs/alexa/custom-skills/audioplayer-interface-reference.html#playbacknearlyfinished) especialmente útil cuando se trabaja con una lista de reproducción.

Posibles respuestas:

- Cualquier directiva de AudioPlayer.
- Cualquier otro tipo de respuesta que NO contenga un texto para Alexa u otras directivas ([como las de Dialog Management](https://dev.to/kini/dialog-management-en-alexa-introduccion-y-referencias-21a4)).

Al recibirlo podríamos responder con una directiva de `Play` y de esa forma preparar siguientes audios sin interferir en la reproducción actual. Alexa automáticamente se encarga de ir transicionando entre los elementos de la playlist.

### AudioPlayer.PlaybackFailed

Vamos a recibir [este evento](https://developer.amazon.com/en-US/docs/alexa/custom-skills/audioplayer-interface-reference.html#playbackfailed) en el back cuando se produzca algún tipo de problema con la reproducción del audio en el dispositivo.

El formato de la petición es distinto a los anteriores:

```
{
  "type": "AudioPlayer.PlaybackFailed",
  "requestId": "unique.id.for.the.request",
  "timestamp": "timestamp of request in format: 2018-04-11T15:15:25Z",
  "token": "token representing the currently playing stream",
  "offsetInMilliseconds": 0,
  "locale": "a locale code such as en-US",
  "error": {
    "type": "error code",
    "message": "description of the error that occurred"
  },
  "currentPlaybackState": {
    "token": "token representing stream playing when error occurred",
    "offsetInMilliseconds": 0,
    "playerActivity": "player state when error occurred, such as PLAYING"
  }
}
```

Podemos ver que en este caso vamos a tener información del `error` e información del estado del playback en el momento del error (`currentPlaybackState`). En el caso de las skills con AudioPlayer que yo he creado, y en el ejemplo que estamos desarrollando, no nos aporta nada conocer el estado del playback, pero sí los tipos de errores que nos vamos a poder encontrar:

- `MEDIA_ERROR_UNKNOWN` > Error desconocido al intentar reproducir el audio.
- `MEDIA_ERROR_INVALID_REQUEST` > Suele ser un error con el acceso al audio, como por ejemplo: no es público, no se encuentra, etc.
- `MEDIA_ERROR_SERVICE_UNAVAILABLE` > No es posible conectarse a la URL indicada.
- `MEDIA_ERROR_INTERNAL_SERVER_ERROR` > En este caso no hay problema con la URL pero Alexa encontró algún problema.
- `MEDIA_ERROR_INTERNAL_DEVICE_ERROR` > Error en el dispositivo al intentar reproducir el audio.

En mi opinión, estos errores son bastante pobres y no aportan mucho sobre lo que está ocurriendo realmente. Por poner unos ejemplos con la skill de "El informativo de Ángel Martín":

- Tuve un problema con los formatos del audio. Al principio usaba audios en formato `m4a`, las pruebas fueron bien y pasó el proceso de certificación. Al publicar la skill empecé a ver en los logs muchos `MEDIA_ERROR_INTERNAL_DEVICE_ERROR` pero no tenía más detalles. La solución para ese caso fue usar `mp3`. No fue nada intuitivo sino que tuve que buscar posibles problemas por otros sitios.
- Una vez realizado el cambio anterior y desaparecer esos errores vi que seguía recibiendo algunos de `MEDIA_ERROR_UNKNOWN` o `MEDIA_ERROR_INTERNAL_SERVER_ERROR`. Esto se debía a que, dependiendo del firmware del dispositivo Alexa, había incluso problemas al reproducir el `mp3`. En esos casos la solución consistía en que los usuarios actualizaran el firmware.
- Y, por último, a modo anécdota (y metedura buena de pata mía), cuando recibía un  `MEDIA_ERROR_INTERNAL_DEVICE_ERROR` estaba retornando un audio en `m4a` que, a su vez, provocaba otro `MEDIA_ERROR_INTERNAL_DEVICE_ERROR`... os podéis imaginar el bucle infinito de peticiones a la lambda y a s3.

A este tipo de eventos podemos responder con:

- Cualquier directiva de AudioPlayer.
- Cualquier otro tipo de respuesta que NO contenga un texto para Alexa u otras directivas ([como las de Dialog Management](https://dev.to/kini/dialog-management-en-alexa-introduccion-y-referencias-21a4)).

Un ejemplo en Kotlin:

{% gist https://gist.github.com/kinisoftware/cc19d75475b623cbfe676cb6517ce28b %}
- Si recibo el error `MEDIA_ERROR_INTERNAL_DEVICE_ERROR` > construyo una respuesta vacía (basado en lo que os comentaba antes de mi experiencia con un bucle infinito).
- Si recibo cualquier otro error > genero una respuesta con una directiva de `Play` y un audio de fallback.

* * *

Y hasta aquí el post sobre los eventos de playback. Me ha quedado un poco largo pero había ciertas cosas necesarias de explicar que me han dado más de un dolor de cabeza a mí.

En el siguiente artículo veremos los built-in intents, la tercera pata principal de una skill de audio, y nos permitirá ir dibujando la imagen global del back :)

<iframe src="https://rcm-eu.amazon-adsystem.com/e/cm?o=30&amp;p=48&amp;l=ur1&amp;category=prime_video&amp;banner=1WM3P83JBRAEDHZ74YR2&amp;f=ifr&amp;linkID=2a2fbae3d254865481664d76a10b3e2e&amp;t=kinisoftware-21&amp;tracking_id=kinisoftware-21" width="728" height="90" scrolling="no" border="0" marginwidth="0" style="border:none;" frameborder="0"></iframe>