Espejito, espejito… Construimos un smart mirror y esto fue lo que aprendimos

Marian C. Moldovan
6 min readNov 13, 2018

--

Recientemente se nos ha planteado el reto de construir desde cero un espejo inteligente con habilidades conversacionales. Un dispositivo físico, capaz de hablar, reconocer voz, mantener una conversación y, además, autenticarse mediante identificación facial. ni más ni menos, una especie de altavoz inteligente tipo Amazon Echo o Google Home, pero vitaminado, con visión artificial y con una interfaz visual, en definitiva, un espejo.

Software

Aunque construir un hardware en una empresa de software es un desafío bastante curioso, esta tarea la asumimos, principalmente, como un reto de software (casi como construir un sistema operativo, un software embebido). Lo planteamos como una aplicación web, en HTML5, escrito en el framework Vue.js, funcionando en modo kiosko con una serie de servicios, asíncronos, comunicados por websockets, el ‘backend’.

Visión

Una de las necesidades del espejo es la de detectar y reconocer caras. La primera funcionalidad se utiliza para despertar el espejo y la segunda para identificar usuarios. La detección es algo que se realiza en local mediante una técnica tradicional: el algoritmo Viola & Jones utilizando la librería DLib. El reconocimiento de personas, así como el registro, se realiza mediante un servicio externo, una API REST de Microsoft, Azure Face API. Utilizando para todo una webcam tradicional.

Habla y reconocimiento de voz

Como cualquier otro sistema de interacción por voz, también hay una palabra para despertarlo, lo que se conoce como una wake up word. Así evitamos falsos positivos de interacción, como evitar que hable al usuario cuando vea una cara (incluso cuando a lo mejor simplemente estás de paso delante del espejo).

Por tanto, tanto la detección de la wake up word como el reconocimiento automático de voz, se realiza mediante otro servicio externo, Google Speech API. Este está configurado para que se reconozca en streaming, pero con el flag de single utterance activado a true. Esto significa que detecta toda la voz recibida, hasta que el usuario deja de hablar. De esta manera, la interacción es por turnos.

Como dispositivo de entrada para la voz, hemos elegido un micrófono especializado, el UMA-8. Se trata de un hardware diseñado para este tipo de aplicaciones y es similar al incluido en los altavoces inteligentes existentes en el mercado. Incluye una serie de micrófonos, para detectar a más distancia la voz e incorpora una serie de funcionalidades como la eliminación de ruido o la cancelación de eco que permiten realizar una mejor detección de la voz.

En el caso del habla, generamos una serie de samples con distintas voces en castellano, sintetizadas por proveedores como Amazon, Google o Azure/Bing, y finalmente elegimos la que, a priori, suena más natural y se adapta mejor a los textos. Todos comparten la misma filosofía, un servicio accesible mediante REST que genera el fichero de audio a partir de texto o descripción SSML.

Gestión de diálogo, NLU e integración con funcionalidades de terceros

Decidimos delegar toda la gestión del diálogo y el procesamiento de lenguaje natural en la herramienta de DialogFlow, de manera que desde la aplicación web frontal, se envía todo el texto dicho por el usuario mediante su API REST y se obtienen las respuestas generadas por DialogFlow y que se van a decir al usuario. La app solamente tiene que adaptar la representación visual, no persiste el estado ni monitoriza el momento del diálogo. Para detectar el wake up word, también utilizamos el servicio de NLU de DialogFlow, entrenamos un intent con la palabra despertador: “Espejito espejito”.

Para desplegar el software y “poner en producción” el dispositivo, elegimos un sistema operativo basado en Linux, Ubuntu y ejecutar sobre Chromium la app web. Para automatizar el arranque de todos los servicios y monitorizar los procesos, utilizamos la herramienta PM2. De esta manera, centralizamos logs, se controlan los errores de tipo crash y se reinician si es necesario. Y finalmente, habilitamos el acceso remoto vía SSH mediante un túnel, Ngrok.

Dificultades encontradas

A lo largo del proceso de desarrollo, nos encontramos con múltiples dificultades. El hecho de tener distintas fuentes de salida de sonido hacía que la voz y los sonidos no se reprodujeran a través del HDMI, es decir, mediante los altavoces de la tele. Para ello creamos un dispositivo de salida de audio virtual mediante ALSA. La utilidad de Ubuntu.

Los navegadores web modernos imponen bastante restricciones en cuanto a aplicaciones que no tienen interacción explícita del usuario, mediante un teclado o un puntero. Como es la aplicación diseñada,de tipo kiosko, sin interacción por teclado y/o ratón. Una de esas limitaciones es la reproducción de sonidos desde la app web, el front. Como, por ejemplo, el pitido que anuncia el turno de habla del usuario. Es por ello que la reproducción de dichos sonidos se realiza desde un proceso del backend, que escucha de manera activa los mensajes enviados vía websockets y, cuando es necesario, reproduce un sonido u otro.

El hecho de recurrir a servicios en la nube, tanto para el procesamiento/detección de la voz y la detección de caras, ocasiona que a veces el sistema tenga un funcionamiento más lento, debido a una mala conectividad a internet. Y cuando no existe una conexión a internet, es difícil, o imposible conocer el causante del mal funcionamiento de la aplicación.

La arquitectura se ha diseñado desde el principio con un enfoque distribuido, para desacoplar todos los servicios. Como por ejemplo los servicios de síntesis de voz y el de reconocimiento de voz. De manera que, si el cliente lo solicita, puede darse el caso cuando el espejo habla y detecta a la vez. Para controlar dicha funcionalidad e impedir que el dispositivo se hable a sí mismo y entre en un bucle. Se han introducido unos flags de control en los servicios, de manera que se prioriza el habla del espejo y cuando se da dicha situación, el reconocimiento de voz se para.

Parte de la conversación del espejo se realiza directamente con un servicio de terceros, fuera del control del gestor de diálogo principal, DialogFlow. Esa separación obliga a introducir una serie de controles, como un detector de intents paralelo, donde detectamos cuando el usuario quiere parar la interacción o existe un momento de frustración ante un error o un bucle no deseado. Por lo tanto, si un usuario dice ‘Cancelar’, ‘Basta ya’ o frases similares, cerramos la interacción. Lo que provoca que, a la vez, se utilizan dos servicios de NLU.

Mejoras

Una de las mejores que detectamos es en la detección de la palabra de activación, la wake up word. En lugar de realizar el reconocimiento mediante un sistema de ASR y clasificarlo mediante un motor de NLU, aprendimos que es una tarea que debería hacerse en local, mediante una solución a medida o utilizando herramientas como Porcupine. Esto hace que el reconocimiento sea mucho más rápido y permitiría interrumpir una interacción cuando el usuario lo requiera, al separar el reconocimiento de voz del reconocimiento del comando de arranque. Además del ahorro de recursos, al no efectuar constantemente llamadas a servicios de coste alojados en la nube.

En el cliente detectamos dos principales mejoras. Por un lado, utilizar webworkers para evitar llamadas bloqueantes en la interfaz visual cuando se realizan comunicación externa, a una API. Por otro lado, usar un complemento como Vuex para gestionar el estado visual de la aplicación. En lugar de utilizar un componente no visual de Vue.js.

Como cierre, mencionar que se trata de un prototipo complejo, aunque no tenga un gran número de features. Construir desde cero un dispositivo que pueda comunicarse por voz, reconocer imágenes y además dar respuestas visuales en un espejo físico es una carrera de fondo. Se trata de construir un sistema operativo a nivel de interacción, una tarea difícil pero no imposible, al tener accesible servicios externos consumidos vía API que resuelven casi todas las tareas. Como la síntesis de voz, el reconocimiento de voz, un gestor de diálogo o un sistema de reconocimiento facial.

--

--

Marian C. Moldovan

Techie and researcher. I imagine, build and test technology