Conversaciones Cibernéticas
LINUX
Conversaciones Cibernéticas
2016-12-15
Por
Signul Floid

Todos le hablamos al ordenador. Eso es un hecho. Normalmente no para decirle nada bueno. Más bien todo lo contrario... Pero existe otro mundo. Un mundo en el que charlar con tu ordenador de una forma agradable y amena. Un mundo sin insultos y golpes a inertes pantallas e indefensos teclados...En este artículo os vamos a descubrir como utilizar pocketsphinx en Español y así, abriros la puerta a un nuevo mundo lleno de bonitas sensaciones... o no?
Por supuesto, Google Voice, Siri, Alexa... todos esos sistemas funcionan de vicio. Así que muchos de vosotros os estaréis preguntando... Pá qué?. Bueno, ahí van algunas razones:

  • Porque es super-güay hacer las cosas uno mismo :P
  • Algunos paranoicos no estamos muy cómodos compartiendo huellas biométricas y localizaciones físicas con corporaciones que siguen reglas cuestionables sobre como manejar información privada
  • A veces no tienes una conexión de red disponible para acceder a los servidores de esas compañías
  • He dicho ya que es güay?

Así que, los que estéis cómodos con esos servicios de reconocimiento de voz, podéis saltaros este artículo... eso sí, cuando vuestra privacidad se vea malamente comprometida no nos vengáis a llorar... Ajo y agua :P

Sin más preámbulos, vamos al tajo.... luego pasaremos por el Duero y, sin ninguna duda visitaremos el Ebro.

La Plataforma

Podéis utilizar cualquier tipo de ordenador para jugar con lo que estamos a punto de contaros, pero nos gustaría decir un par de palabras sobre el tema, basadas en nuestra experiencia durante la preparación del artículos.

La única restricción obligatoria es que el ordernador que elijáis tenga una entrada de audio... Vamos una tarjeta de audio y que funcione. Como os decíamos, hemos probado unas cuantas opciones con diferentes resultados.

  • PC. La primera plataforma que probamos fue nuestro querido PC con GNU/Linux, el cual, como era de esperar, funcionó perfectamente.
  • Raspberry Pi. La Rpi funciona perfectamente, incluso la primera generación. Sin embargo, es necesario utilizar una tarjeta de audio USB externa (o alguno de esos Hats) para poder capturar el audio
  • Banana Pi.La Banana Pi es un clon de la Rpi con algunas mejoras. Además de un interesante interfaz SATA para conectar discos duros externos, la tarjeta trae un micrófono incorporado de forma que no es necesario ningún HW adicional.
  • Android. También hemos probado pocketsphinx en Android, si bien, es un poco más complicado y no vamos a tratar ese tema en este artículo

Bueno, nosotros nos quedamos con la BananaPi para las pruebas, pero los pasos para utilizar pocketsphinx son los mismos para cualquier ordenador que funcione con GNU/Linux... Así que vamos a instalar.

INSTALACIÓN

La instalación es bastante sencilla. Las instrucciones son para sistemas basados en Debian, los más comunes hoy en día. Para otras distribuciones la forma de instalar los paquetes será diferente... Lo primero que necesitamos es el compilador. Probablemente eso ya lo tengas instalado, pero sino, el paquete build-essential suele ser todo lo que necesitamos:

sudo apt-get install build-essential

Además del compilador, vamos a necesitar bison y el paquete de desarrollo de ALSA:

sudo apt-get install bison libasound2-dev

Esas son todas las dependencias que deberíamos necesitar... No dudéis en dejar un comentario si descubrís que algún paquete extra necesita ser instalado.

Ahora debemos descargar y compilar pocketsphinx. Durante unos cuantos años, pocketsphinx no sacó nuevos releases, siendo la version 0.8 la última disponible. Parece ser que, recientemente, se a publicado una nueva versión. Nosotros la probamos rápidamente, pero no funcionó inmediatamente y por ello hemos decidido escribir este artículo sobre la versión 0.8.

Las instrucciones para instalar la nueva versión son prácticamente las mismas, sin embargo, esta nueva versión respondía de forma muy lenta, probablemente debido a alguna configuración nueva que no hemos visto. En cualquier caso, si la probáis y conseguís que funcione correctamente, enviadnos una nota... plis

Compilando PocketSphinx

Lo primero que debemos hacer es descargar los paquetes sphinxbase y pocketsphinx de la web de proyecto (https://sourceforge.net/projects/cmusphinx/files/).

Crearemos un directorio y descomprimiremos ambos paquetes en el:

~$ mkdir compilar
~$ cd compilar
~/compilar $ tar xzvf ~/Downloads/sphinxbase-0.8.tgz
~/compilar $ tar xzvf ~/Downloads/pocketsphinx-0.8.tgz

Es importante que los dos paquetes se encuentren en el mismo directorio. PocketSphinx utiliza algunos ficheros de sphinxbase y por ello necesita saber donde encontrarlos.

Ahora solo tenemos que compilar sphinxbase y luego pocketsphinx

~/compilar $ cd sphinxbase-0.8
~/compilar/sphinxbase-0.8 $ ./configure && make
~/compilar/sphinxbase-0.8 $ sudo make install
~/compilar/sphinxbase-0.8 $ cd ../../pocketsphinx-0.8
~/compilar/pocketsphinx-0.8 $ ./configure && make
~/compilar/pocketsphinx-0.8 $ sudo make install
~/compilar/pocketsphinx-0.8 $ sudo ldconfig -v

Ya estaría listo. Intentad ejecutar pocketsphinx_continuous. Por defecto utiliza el lenguaje inglés... y no es que funcione muy bien con los modelos distribuidos por defecto, pero si se ejecuta y reconoce algo, aunque sea mal, significa que nuestra instalación ha funcionado.

Ahora hablemos español.

Hablando en Español

Pocketsphinx viene con soporte para inglés (y creo que chino, pero ese no lo he probado :P). Lo que nos interesa a nosotros, es poder hablar en Español, o incluso gallego (el modelo acústico y de lenguaje es prácticamente el mismo), Así que tenemos que instalar algunos ficheros extra.

Los ficheros los podéis encontrar en esta página web:

http://www.speech.cs.cmu.edu/sphinx/models/hub4spanish_itesm/

Descargad los fichero y guardadlos en un lugar conveniente. Ahora solo tenemos escribir una línea de comandos pasándolo todos estos ficheros que nos acabamos de descargar.

pocketsphinx_continuous -mdef ./es/H4.2500.mdef -lm ./es/H4.arpa.Z.DMP -hmm ./es/H4.cd_continuous_8gau -dict ./es/h4.dict -feat s3_1x39

Ya os habréis dado cuenta de que el parámetro que pasamos con el flag hmm es uno de los ficheros tar que hemos descargado. Tendréis que descromprimirlo para poder usarlo. Estos ficheros son modelos acústicos... básicamente, probad el que mejor funciona para vosotros.

Si habéis seguido los pasos hasta aquí, y todo ha ido bien, dispondréis de un gracioso reconocedor de voz que parece un viejo medio sordo. Jamás hemos conseguido que el reconocimiento libre funcionara bien, si bien, también es cierto, que nunca hemos intentado entrenar modelos acústicos y de lenguaje específicos.

Podéis probar a entrenar vuestros modelos. La web de CMU Sphinx contiene todos los detalles. Nosotros vamos a dejar de lado el reconocimiento libre, vamos lo que sería el dictado, y vamos a concentrarnos en el uso de gramáticas.

UNA GRAMÁTICA

Cuando reducimos las palabras de nuestro lenguaje a una pequeña lista con reglas más estrictas, la cosa mejora un montón. Pocketsphinx nos permite definir gramáticas con las que restringir el número de palabras a reconocer.

Las gramáticas en pocketsphinx se definen utilizando el formato JSGF (Java Speech Grammar Format). El formato es muy sencillo así que vamos a ir directamente con un ejemplo que podáis probar:

#JSGF V1.0;
grammar test;
public <computer> = [PEPA] <command>;
<command> = <saludo> | <action> ;
<saludo> = (HOLA | BUENAS | ADIOS);
<action> = (MUSICA | INFORME);

El formato es muy sencillo. La definición de la gramática realmente empieza con la palabra clave public. Cualquier palabra entre los caracteres < y > es un identificador. Cualquier cadena entre corchetes representa un palabra opcional. La barra vertical (|) es un OR y más o menos esa es la cosa. La gramática que hemos definido más arriba, se podría explicar de la siguiente forma:

  • Cualquier comando esta formado por la palabra PEPA, que puede omitirse seguida de uno de los siguientes comandos ()
  • Los posibles comandos están agrupados en dos categorias: <saludo>; representa posibles saludos y <action> representa acciones que queremos que nuestro sistema lleve a cabo
  • Los posibles <saludos> que queremos reconocer son las palabras: "HOLA", "BUENAS" y "ADIOS"
  • Las posibles acciones son "MUSICA" e "INFORME"

Con esta gramática el reconocedor de voz solo va a intentar reconocer las palabras que hemos indicado en el fichero, y además con las condiciones indicadas. Por ejemplo, los saludos son excluyentes. Podemos decir: "HOLA", "BUENAS" y "ADIOS", pero no podemos decir "HOLA BUENAS" ya que esa combinación no está recogida en la gramática.

Si probáis esta gramática comprobaréis que no funciona. La razón es que, el diccionario que viene con el paquete de Español que hemos instalado es bastante limitado. Así que tendremos que añadir las palabras que no aparezcan en el diccionario.

Comenzaremos haciendo una copia del fichero original (h4.dict) a la que llamaremos mi.dict. Ahora vamos a añadir la palabra PEPA, que no se encuentra en el fichero original. Abrimos el fichero con un editor de texto y buscamos la parte del fichero donde se encuentran las palabras que empiezan por P (está ordenado alfabéticamente). Realmente no es necesario añadir la palabra en el orden alfabético correcto, pero es conveniente para poder encontrarla fácilmente si tenemos que hacer alguna modificación.

El diccionario no es más que la transcripción fonética de una lista de palabras. En Español, la transcripción fonética es bastante directa. En caso de duda, buscad una palabra que suene igual en el diccionario y comprobad su transcripción.

Las líneas que hemos añadido al diccionario para soportar nuestra gramática son:

(....)
ADIOS     A D I O S
(...)
MUSICA     M U S I K A
(....)
PEPA     P E P A
(...)

Como podéis ver, para el caso de la palabra música, utilizamos la K en lugar de la C. La Ka suena distinto que la Ce. Bueno, ahora podéis probar el reconicimiento usando nuestra nueva gramática y diccionario:

 pocketsphinx_continuous -mdef ./es/H4.2500.mdef -lm ./es/H4.arpa.Z.DMP -hmm ./es/H4.cd_continuous_8gau -dict ./es/mi.dict -feat s3_1x39 -jsgf simple.jsgf

Ahora debería funcionar perfecto.

MODIFICANDO CONTINUOUS

Hasta ahora hemos estado utilizando el programa pocketsphinx_continuous que viene con PocketSphinx y mola mucho. Pero lo que realmente queremos es que el ordenador haga cosas cuando le hablemos.

Una forma de conseguirlo es filtrando la salida de pocketsphinx_continuous con algún tipo de script que localice el texto reconocido. Aún así, el programa imprime un montón de mensajes que son un poco difíciles de filtar, así que mejor, vamos a cambiar el programa un poco para que podamos obtener el resultado del reconocimiento de una forma mucho más sencilla. Realmente no necesitamos hacer esto para filtrar la salida, pero así os enseñamos la parte del programa que os va a interesar modificar en vuestras aplicaciones.

Ya estáis yendo al directorio con el código fuente de PocketSphinx y abriendo el código fuente. La función que nos interesa se llama recognize_from_microphone. Esta función inicializa el reconocedor y lee las muestras de audio del micrófono, utilizando unas funciones que proporciona SphinxBase. Bueno, lee audio hasta que detecta un silencio y en ese momento intenta reconocer el texto.

Busquemos la llamada a la función ps_get_hyp dentro de recognize_from_microphone. Hay un printf:

printf("%s: %s\n", uttid, hyp);

Esta es la línea que imprime el resultado del reconocimiento tal que así:

000000002: PEPA ADIOS

Lo que vamos a hacer es cambiar esa línea por

printf("##RESULT: %s\n", hyp);

De tal forma que un simple "grep "##" nos muestre solo las líneas que nos interesan. Así que comentemos el printf original. Cambiémoslo por el nuevo y a recompilar se ha dicho:

gcc -o continuous continuous.c -lsphinxbase -lsphinxad -lpocketsphinx -I /usr/local/include/sphinxbase/ -I /usr/local/include/pocketsphinx/

Probemos que tal funciona ahora:

 ./continuous -mdef ./es/H4.2500.mdef -lm ./es/H4.arpa.Z.DMP -hmm ./es/H4.cd_continuous_8gau -dict ./es/mi.dict -feat s3_1x39 -jsgf simple.jsgf 2> /dev/null | grep "##"

Estupendo!. Ahora solo tenemos que enviar esos comando a algún programa para que haga algo útiles con ellos. Alternativamente, podemos procesar los mensajes directamente en el programa C...

El Cielo es el límite

A partir de aquí solo vuestra imaginación puede poner límites a lo que hacer con esta tecnología. Ahí van algunos ejemplos:

Alexa?... que Alexa ni que porras. Pepa, Manuela, Gumersinda... usad el nombre que queráis. Una pequeña modificación de la gramática y un poco de código para modificar el programa y que la salida de comandos solo se active si pronunciamos el nombre correcto. Un flag, un temporizador, un if y ya estamos listos

Y si hacemos el servicio accesible sobre la red?. Nada más fácil. Solo hay que empipar la salida de grep a NetKitty en modo hub servidor (nk -hub -s T,5000). Nos conectamos al puerto y obtenemos el resultado del reconocimiento en cualquier máquina de nuestra red

Dejad un comentario sobre vuestro proyecto con reconocimiento de voz.

SOBRE Signul Floid
Tras abandonar sus estudios de psiquiatría, Signul se volcó en el apasionante mundo del procesado de señales convirtíendose en una de las eminencias mundiales en el tema. Cuando no está transformando o aplicando complejos algorithmos a cualquier señal que se le ponga por delante, Signul disfruta psicoanalizando a cualquier persona que se le cruce.

 
Tu publicidad aquí :)