Google Assistant: Cómo utilizar un micrófono y un altavoz Bluetooth en la plataforma Ubuntu ODROID-XU4 y ODROID-HC1

ODROID Magazine Google Assistant SDK

Este artículo describe cómo poner en marcha un Altavoz IA (Inteligencia Artificial) sobre ODROID-HC1 utilizando Google Assistant SDK.

Requisitos de Hardware

ODROID Magazine Figure 1 - Hardware requirements for the Google Assistant project
Figura 1 - Requisitos de hardware para el proyecto Google Assistant

IConecta el dongle Bluetooth al puerto USB del ODROID-HC1, luego enciende el ODROID-HC1 y el altavoz Bluetooth para empezar.

Ajustes de Sonido

Para acceder a la consola del ODROID-HC1, consigue la dirección IP de la placa tal y como se describe en http://bit.ly/2yXFLwp. Esta guía está basada en el último sistema operativo Ubuntu 16.04 Minimal. Puedes descargar la imagen del sistema operativo desde http://bit.ly/2yXYs3h. Antes de empezar con la configuración del sistema, añade la nueva cuenta de usuario ODROID como un usuario sudo, porque Ubuntu Minimal no tiene ninguna cuenta de usuario:

# adduser odroid
# usermod -aG sudo odroid
# su - odroid
Instala los paquetes relacionados con el sonido pulseaudio y alza:
$ sudo apt update
$ sudo apt install libasound2 libasound2-plugins alsa-utils alsa-oss
$ sudo apt install pulseaudio pulseaudio-utils pulseaudio-module-bluetooth
Añade permisos pulseaudio a la cuenta de usuario. Agrega la línea "load-module module-switch-on-connect" al archivo de configuración de pulseaudio. Esta configuración cambia la salida de audio al altavoz Bluetooth automáticamente:
$ sudo usermod -aG pulse,pulse-access odroid
$ sudo nano /etc/pulse/default.pa
/etc/pulse/default.pa
.ifexists module-bluetooth-discover.so
load-module module-bluetooth-discover
load-module module-switch-on-connect # this is new!
.endif
Inicia pulseaudio:
$ pulseaudio --start

Configuración de Bluetooth

Instala el paquete relacionado con el Bluetooth. En este caso, usa el paquete bluez para bluetooth:

$ sudo apt install bluez
$ bluetoothctl
Si el comando bluetoothctl no funciona con la cuenta de usuario, modifica el archivo de configuración de dbus añadiendo las siguientes configuraciones al archivo:
$ sudo nano /etc/dbus-1/system.d/bluetooth.conf
/etc/dbus-1/system.d/bluetooth.conf
 
< policy user="odroid">
    < allow send_destination="org.bluez"/>
    < allow send_interface="org.bluez.Agent1"/>
    < allow send_interface="org.bluez.GattCharacteristic1"/>
    < allow send_interface="org.bluez.GattDescriptor1"/>
    < allow send_interface="org.freedesktop.DBus.ObjectManager"/>
    < allow send_interface="org.freedesktop.DBus.Properties"/>
  < /policy>
Introduce los siguientes comandos en la consola bluetoothctl. Ten en cuenta que la dirección MAC del altavoz Bluetooth debe cambiarse de 00:11:67:AE:25:C6 a tu propia dirección MAC. Esta dirección es diferente para cada dispositivo Bluetooth, así que asegúrate de reemplazar la dirección MAC por la suya:
[bluetooth]# agent on
[bluetooth]# default-agent
[bluetooth]# scan on
[bluetooth]# pair 00:11:67:AE:25:C6
[bluetooth]# trust 00:11:67:AE:25:C6
[bluetooth]# connect 00:11:67:AE:25:C6
[bluetooth]# quit
El altavoz Bluetooth debería tener una configuración por defecto. Para ajustar el A2DP (Advanced Audio Distribution Profile) como predeterminado, cambia el perfil a HSP (Head Set Profile) porque A2DP no puede usar el micrófono.
$ pacmd ls
Consulta el fichero del altavoz Bluetooth, suponemos que el index es 1:
$ pacmd set-card-profile 1 headset_head_unit
Para verificar que hay sonido y que la configuración de Bluetooth se ha realizado correctamente, reproduce un sonido de prueba:
$ speaker-test -t wav
Graba y reproduzca algo de audio utilizando las herramientas de línea de comandos ALSA:
$ arecord --format=S16_LE --duration=5 --rate=16k --file-type=raw out.raw
 $ aplay --format=S16_LE --rate=16k --file-type=raw out.raw
Para facilitar el uso del altavoz Bluetooth, es necesario realizar algunas configuraciones:

/etc/bluetooth/main.conf

[Policy]
AutoEnable=true
($HOME)/.bashrc
pulseaudio --start
echo "connect 00:11:67:AE:25:C6" | bluetoothctl

Activar la API de Google Assistant

Para habilitar la API de Google Assistant, consulta la página de Guías de Google Assistant SDK en http://bit.ly/2pXwqfC. Usa una cuenta de Google para iniciar sesión. Si todavía no dispones de una cuenta de Google, cree una. Probar la API de Google Assistant es gratis para uso personal.

Configurar un Proyecto Desarrollador Google 

Un Proyecto desarrollador Google permite que cualquier dispositivo ODROID tenga acceso a la API de Google Assistant. El proyecto rastrea el uso de cuota y proporciona valiosas métricas de las peticiones realizadas desde dispositivos ODROID en la red.

Para habilitar el acceso a la API de Google Assistant, primero dirígete a la página de Proyectos dentro de Cloud Platform Console y selecciona un proyecto existente o cree un nuevo proyecto. Ve a la página de Proyectos en http://bit.ly/2gY7pSV. A continuación, activa la API de Google Assistant en el proyecto que has seleccionado y haz clic en Habilitar. Puedes obtener más información sobre cómo activar la API en http://bit.ly/2A1ewic.

Después, crea un ID de Cliente OAuth creando primero la ID del cliente, tal y como se describe en http://bit.ly/2xBjII6. Puede que necesites definir un nombre de producto en la pantalla de aprobación de producto. En la pestaña aprobación de OAuth, asigna un nombre al producto y haga clic en Guardar, luego haz clic en Otro y asigna un nombre al ID del cliente y haz clic en Crear. Aparecerá un cuadro de diálogo que te mostrará el ID de cliente y un secret. No hay necesidad de recordar o guardar esto, simplemente cierra el cuadro de diálogo. A continuación, haz clic en el extremo derecho de la pantalla para que la ID del cliente descargue el archivo JSON del cliente (client_secret_.json). El archivo client_secret_.json debe estar ubicado en el dispositivo para autorizar a que la muestra de Google Assistant SDK pueda realizar consultas a Google Assistant, y no debe cambiarse de nombre. Finalmente, copia client_secret_.json en el ODROID-HC1:

$ scp ~/Downloads/client_secret_client-id.json odroid@:~/

Definir los controles de actividad para tu cuenta de Google

Para poder usar Google Assistant, hay determinados datos de actividad que tienen que ser compartidos con Google. Google Assistant necesita que estos datos funcionen correctamente, no son específicos del SDK. Para hacer esto, abre la página de Controles de actividad de la cuenta de Google que se usará con el Asistente en http://bit.ly/2ig4QIB. Cualquier cuenta de Google tiene esta opción y no necesita ser tu cuenta de desarrollador. Asegúrate de que las siguientes opciones estén activadas (azul):

  • Web & App Activity
  • Device Information
  • Voice & Audio Activity

Descargar y ejecutar la muestra de la API de Google Assistant

Utiliza un entorno virtual Python para aislar el SDK y sus dependencias de los paquetes Python del sistema:

$ sudo apt update
$ sudo apt install python-dev python-virtualenv git portaudio19-dev libffi-dev libssl-dev
$ virtualenv env --no-site-packages
Si tienes problemas con la configuración regional tal y como se muestra a continuación, configura la variable de entorno LC_ALL:
Complete output from command /home/odroid/env/bin/python2 - setuptools pkg_resources pip wheel:
Traceback (most recent call last):
File "", line 24, in 
File "/usr/share/python-wheels/pip-8.1.1-py2.py3-none-any.whl/pip/__init__.py", line 215, in main
File "/home/odroid/env/lib/python2.7/locale.py", line 581, in setlocale
return _setlocale(category, locale)
locale.Error: unsupported locale setting
$ export LC_ALL=C
$ virtualenv env --no-site-packages
Activate Python virtual environment.
$ env/bin/python -m pip install --upgrade pip setuptools
$ source env/bin/activate
Tras activar el entorno virtual de Python, aparecerá la cadena "(env)" delante del prompt.

Autoriza que la muestra de SDK de Google Assistant pueda realizar consultas a Google Assistant para la cuenta de Google especificada. Haz referencia al archivo JSON que ha sido copiado en el dispositivo en un paso anterior e instala la herramienta de autorización:

(env) $ python -m pip install --upgrade google-auth-oauthlib[tool]
Ejecute la herramienta, asegurándote de quitar el parámetro –headless si estás ejecutando esto desde una terminal en el dispositivo (no usas una sesión SSH):
(env) $ google-oauthlib-tool --client-secrets /path/to/client_secret_client-id.json --scope https://www.googleapis.com/auth/assistant-sdk-prototype --save --headless
Debería ver una URL que se muestra en el terminal:
Please go to this URL: https://
Copia la URL y pégala en un navegador. Esto se puede hacer en la máquina de desarrollo o en cualquier otra máquina. Una vez aceptada, aparecerá un código en el navegador, algo así como "4/XXXX". Copia y pega este código en el terminal:
Enter the authorization code:
Si la autorización ha tenido exito, las credenciales de OAuth se activarán en la terminal. Si en su lugar aparece InvalidGrantError, entonces es que se ha introducido un código no valido. Si esto ocurre, inténtalo de nuevo, teniendo cuidado de copiar y pegar todo el código. Si se introduce el código de autorización correcto, se genera el archivo credentials.json:
credentials saved: /home/odroid/.config/google-oauthlib-tool/credentials.json
Hazte con los códigos de muestra del repositorio de github:
$ git clone https://github.com/googlesamples/assistant-sdk-python
$ cd assistant-sdk-python
Instala los requisitos de paquetes de Python para el programa de ejemplo. Usamos la muestra pushtotalk.
$ cd google-assistant-sdk
$ python setup.py install
$ cd googlesamples/assistant/grpc
$ pip install --upgrade -r requirements.txt
$ nano pushtotalk.py
Para ejecutar el ejemplo, tenemos que modificar el código. Cambia el tipo de excepción SystemError a ValueError en el código de ejemplo (línea 35):

pushtotalk.py

except ValueError:
import assistant_helpers
import audio_helpers
Ejecuta y prueba la muestra pushtotalk. Si el programa de ejemplo funciona bien, está hecho casi todo trabajo:
(env) $ python pushtotalk.py
INFO:root:Connecting to embeddedassistant.googleapis.com

Press Enter to send a new request...
Copia la muestra en el directorio de trabajo. Desactiva el entorno virtual de Python. Hay que realizar una serie de pasos adicionales para dar forma a un interlocutor IA de provecho. Para eso, dirígete al directorio $ (HOME)/ai_speaker:
(env) $ cd ..
(env) $ cp -r grpc ~/ai_speaker
(env) $ cd ~/ai_speaker
(env) $ cp pushtotalk.py ai_speaker.py
(env) $ deactivate
$ cd

Wake-Up-Word

La muestra Wake-Up-Word parece que interactúa con el asistente de inteligencia artificial. Sin embargo, antes de comunicarse con el asistente IA, primero hay que presionar la tecla Intro. Para detectar un Wake-Up-Word como "Okay, Google", "Alexa" o "Jarvis", usa CMUSphinx de https://cmusphinx.github.io , que es el kit de herramientas de reconocimiento de voz local de código abierto. Lo mejor es compilar e instalar SphinxBase, ya que éste proporciona una funcionalidad común para todos los proyectos CMUSphinx:

$ sudo apt install libtool bison swig python-dev autoconf libtool automake
$ git clone --depth 1 https://github.com/cmusphinx/sphinxbase.git
$ cd sphinxbase
$ ./autogen.sh
$ make -j8
$ sudo make install
$ cd
Sphinxbase se instalará en el directorio "/usr/local/" por defecto. No todos los sistemas cargan las librerías automáticamente desde esta carpeta. Para cargarlas, configura la ruta para localizar las librerías compartidas. Esto se puede hacer en el archivo "/etc/ld.so.conf" o exportando las variables de entorno:
export LD_LIBRARY_PATH=/usr/local/lib
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
Compila e instala PocketSphinx. PocketSphinx es un liviano motor de reconocimiento de voz específialmente diseñado para dispositivos portátiles y dispositivos móviles, aunque funciona igual de bien en los PC de escritorio:
$ git clone --depth 1 https://github.com/cmusphinx/pocketsphinx.git
$ cd pocketsphinx
$ make -j8
$ sudo make install
$ cd
Para probar la instalación, ejecuta pocketsphinx_continuous y comprueba que se reconoce tus palabras a través del micrófono:
$ pocketsphinx_continuous -inmic yes
Para obtener más información sobre el desarrollo de PocketSphinx, consulte la página "Building an application with PocketSphinx " en http://bit.ly/2gZhHT5.

Añade el programa pocketsphinx_continuous como un subproceso del programa del Altavoz IA. El programa pocketsphinx_continuous es una buena herramienta para detectar palabras clave ya que reconoce el habla de forma asincrónica. Procede a eliminar las líneas relacionadas wait_for_user_trigger puesto que las propias palabras clave son el activador:

$ source env/bin/activate
(env) $ pip install --upgrade subprocess
$(HOME)/ai_speaker/ai_speaker.py

 """Sample that implements gRPC client for Google Assistant API."""

# Add subprocess module
 import subprocess
 import json
 import logging
 import os.path

(......)

# Add below's routines in the 'While True:' loop
 while True:
 p = subprocess.Popen(args = ['pocketsphinx_continuous','-inmic', 'yes', '-kws_threshold', '1e-16', '-keyphrase', 'hey dude'],
 stdin = subprocess.PIPE,
 stdout = subprocess.PIPE,
 universal_newlines=True)
 while p.poll() is None:
 data = p.stdout.readline()
 if data.find("hey dude") is not -1:
 print "Detected Hotwords"
 p.stdout.flush()
 break
 p.terminate()
El Wake-Up-Word es "hey dude". Ejecuta el programa, pronuncia "hey dude" y luego dile todo lo que quieras al asistente IA:
(env) $ cd ai_speaker
(env) $ python ai_speaker.py

Sonido de detección

Existe un problema tras añadir inicialmente los Wake-Up-Words, porque no hay ningún mecanismo en situ para darnos cuenta si el altavoz IA está detectando o no las palabras clave. Se debe conocer la sincronización para poder controlar el asistente IA por voz. Esto puede solucionarse añadiendo un sonido de detección al programa. Descarga el sonido de detección de muestra en http://bit.ly/2zkSV3b, luego copia el archivo detect.wav al ODROID-HC1:

$ scp ~/Downloads/detect.wav odroid@:~/
Utiliza el módulo wave y pyaudio para reproducir el archivo .wav en el código fuente de Python:
(env) $ pip install --upgrade pyaudio wave
Agrega la rutina para reproducir el sonido de detección al programa. Todas las posibles variedades, incluidas las rutinas Wake-Up-Words son las siguientes:
(env) $ nano ai_speaker.py
Archivo diff entre el código de muestra original pushtotalk.py y el programa modificado ai_speaker.py
 --- pushtotalk.py 2017-10-19 15:42:12.164741800 +0000
 +++ ai_speaker.py 2017-10-19 15:41:49.644811151 +0000
 @@ -14,6 +14,9 @@

"""Sample that implements gRPC client for Google Assistant API."""

+import pyaudio
+import wave
+import subprocess
import json
import logging
import os.path
@@ -310,14 +313,38 @@
# keep recording voice requests using the microphone
# and playing back assistant response using the speaker.
# When the once flag is set, don't wait for a trigger. Otherwise, wait.
- wait_for_user_trigger = not once
+ chunk = 1024
+ pa = pyaudio.PyAudio()
+ while True:
- if wait_for_user_trigger:
- click.pause(info='Press Enter to send a new request...')
+ p = subprocess.Popen(args = ['pocketsphinx_continuous','-inmic', 'yes', '-kws_threshold', '1e-16', '-keyphrase', 'hey dude'],
+ stdin = subprocess.PIPE,
+ stdout = subprocess.PIPE,
+ universal_newlines=True)
+ while p.poll() is None:
+ data = p.stdout.readline()
+ if data.find("hey dude") is not -1:
+ print "Detected Hotwords"
+ p.stdout.flush()
+ break
+ p.terminate()
+
+ # Play the detection sound
+ f = wave.open(r"/home/odroid/detect.wav","rb")
+ stream = pa.open(format = pa.get_format_from_width(f.getsampwidth()),
+ channels = f.getnchannels(),
+ rate = f.getframerate(),
+ output = True)
+ wav_data = f.readframes(chunk)
+
+ while wav_data:
+ stream.write(wav_data)
+ wav_data = f.readframes(chunk)
+ stream.stop_stream()
+ stream.close()
+ f.close()
+
continue_conversation = assistant.converse()
- # wait for user trigger if there is no follow-up turn in
- # the conversation.
- wait_for_user_trigger = not continue_conversation

# If we only want one conversation, break.
if once and (not continue_conversation):
# Run the AI speaker program.
(env) $ python ai_speaker.py
Para ver el altavoz en acción, consulta el video en https://youtu.be/6Ez782BxxdQ.

El paso final

La tasa de detección de Wake-Up-Words es algo inferior a la ideal. Tanto si usa Pocketsphinx como cualquier otra solución, la rutina Wake-Up-Words necesita mejoras, así que añadir comandos personalizados va a resultar muy útil en este proyecto en concreto. Por ejemplo, es fácil controlar los dispositivos IoT por voz mediante el Google Assistant SDK. Se pueden localizar diferentes soluciones recurrirendo a la búsqueda "action on google " para obtener más información sobre la extensión de Google Assistant.

Para ahorrar tiempo, se puede utilizar una sencilla solución de comando personalizado simplemente añadiendo el comando al programa ai_speaker.py. En la muestra pushtotalk, busca el texto de solicitud que ya está reconocido por voz:

--- pushtotalk.py 2017-10-19 16:07:46.753689882 +0000
+++ pushtotalk_new.py 2017-10-19 16:09:58.165799271 +0000
@@ -119,6 +119,15 @@
logging.info('Transcript of user request: "%s".',
resp.result.spoken_request_text)
logging.info('Playing assistant response.')
+ #Add your custom voice commands here
+ #Ex>
+ #import os
+ #r_text = resp.resut.spoken_request_text
+ #if r_text.find("play music") is not -1:
+ # os.system("mplayer ~/Music/*&")
+ #if r_text.find("turn on light") is not -1:
+ # os.system("echo 1 > /sys/class/gpio/gpio1/value")
+
if len(resp.audio_out.audio_data) > 0:
self.conversation_stream.write(resp.audio_out.audio_data)
if resp.result.spoken_response_text:
Después de guardar esta modificación, puede empezar a experimentar con el control de dispositivos electrónicos domésticos utilizando el controlador IOT con comandos de voz. Para comentarios, preguntas y sugerencias, visita el artículo original en http://bit.ly/2iQ629K.

Be the first to comment

Leave a Reply