Control por voz en PC y RaspberryPi con Whisper

NUEVO PROYECTO: Recibe una curiosidad diaria con nuestra Newsletter. Pequeños asombros diarios para Personas Altamente Curiosas
control por voz en pc y raspberry pi

La idea del proyecto es dar instrucciones de voz para interactuar a través de nuestro PC o de nuestra Raspberry Pi utilizando el modelo Voice-to-text Whisper.

Daremos una orden que será transcrita, convertida a texto, con Whisper y entonces analizada para ejecutar la orden adecuada que puede ser desde ejecutar algún programa a dar voltaje a los pines de la RaspberryPi.

Yo voy a utilizar una vieja Raspberry Pi 2, un micro USB y utilizaré el modelo de Voice-to-text recién liberado por OpenAI, Whisper. Al finl del artículo puedes ver un poquito más de Whisper.

Todo programado en Python.

Te dejo una demostración de como funciona en este vídeo, controlando por voz el PC.

Montaje

Para usarlo con el PC, tan solo necesitaremos un micrófono.

Si vas a hacer el montaje en la RaspberryPi, necesitarás un micrófono USB, porque el jack que tiene solo es de salida.

NUEVO PROYECTO: Recibe una curiosidad diaria con nuestra Newsletter. Pequeños asombros diarios para Personas Altamente Curiosas

Necesitamos:

Como el propósito general de la herramienta es la identificación de voz. Me parece muy útil para integrarlo en el funcionamiento de otros dispositivos.

  • Micro USB
  • Raspberry PI con sistema operativo (Raspbian pro ejemplo)
  • Electrónica (LED, cables, resistencia 480 ohm y placa protoboard)

Conectamos el LED en el pin 17 qeu es el que activaremos y desactivaremos para esta experiencia.

Desarrollo del código

Se divide en tres partes, la primera, la grabación de audio para la que he cogido un código de Geeksforgeeks, porque esas librerías no las conozco. La segunda, la conversión del audio a texto con Whisper y la tercera el tratamiento de ese texto y respuesta en la RaspberryPi

En el ejemplo de prueba solo voy a interactuar con un Led, haciendo que se encienda o parpadee, pero podríamos desarrollar el script para ajustarlo a nuestras necesidades.

Soy consciente de que esto es una Raspberry Pi 2 y va a ir mucho más lento que en una Raspberry Pi 4, pero para las pruebas me vale.

Antes de hacerlo funcionar, tendrás que instalar lo siguiente

#Instalar whisper
pip install git+https://github.com/openai/whisper.git
sudo apt update && sudo apt install ffmpeg

#para que funcione la grabación de audio
python3 -m pip install sounddevice --user
pip install git+https://github.com/WarrenWeckesser/wavio.git

#si vas a instalarlo en la raspberry
#dar permisos para usar la GPIO
sudo apt install python3-gpiozero
sudo usermode -aG gpio <username>

Todo el código

#!/usr/bin/env python3
import whisper
import time
from gpiozero import LED
import sounddevice as sd
from scipy.io.wavfile import write
import wavio as wv

        
def main ():
    inicio = time.time()
    record_audio ()

    model = whisper.load_model("tiny")
    result = model.transcribe("audio1.wav")
    words = result["text"].split()

    for word in words:
        word = word.replace(',', '').replace('.', '').lower()
        if word == 'enciende' or 'encender':
            encender()
            break
        if word == 'parpadea' or 'parpadear':
            parpadear()
            break      
    fin = time.time()
    print(fin-inicio)

def encender ():
    LED(17).on()

def parpadear ():
    light = LED(17)
    while True:
        light.on()
        sleep(1)
        light.off()
        sleep(1)

def record_audio ():
    # Sampling frequency
    freq = 44100
    # Recording duration
    duration = 5
    # Start recorder with the given values
    # of duration and sample frequency
    recording = sd.rec(int(duration * freq),
                    samplerate=freq, channels=2)
    # Record audio for the given number of seconds
    sd.wait()
    # This will convert the NumPy array to an audio
    # file with the given sampling frequency
    write("audio0.wav", freq, recording)
    # Convert the NumPy array to audio file
    wv.write("audio1.wav", recording, freq, sampwidth=2)
        
main ()


#dar permisos para usar la GPIO
#sudo apt install python3-gpiozero
#sudo usermode -aG gpio <username>

#Instalar whisper
#pip install git+https://github.com/openai/whisper.git
#sudo apt update &amp;&amp; sudo apt install ffmpeg

No he podido testearlo porque no tengo microSD para la RaspberryPi, ni altavoz USB para conectar, pero en cuanto lo pruebe corrijo algún error que es fácil que se haya colado.

Explicación paso a paso del código

#!/usr/bin/env python3

El Shebang para decirle al dispositivo en qué lenguaje hemos programado y qué intérprete debe de utilizar. Aunque parece algo trivial, no ponerlo causa errores en muchas ocasiones.

Librerías importadas

import whisper
import time
from gpiozero import LED
import sounddevice as sd
from scipy.io.wavfile import write
import wavio as wv

Whisper para trabajar con el modelo

time, porque la utilizao para controla el teimpo que tarda en ejecutarse el script, gpiozero para trabajar con los piens GPIO de la Raspberry y sounddevice, scipy y wavio para grabar el audio

Las funciones

He creado 4 funciones:

  • main ()
  • encender ()
  • parpadear ()
  • record_audio ()

encender () simplemente da tensión al pin 17 de la raspberry donde tenemos conectado en este caso el LED para probar

def encender ():
    LED(17).on()

parpadear () es como encender () pero hace que parpadee el led encendiéndolo y apagándolo dentro de un bucle.

def parpadear ():
    light = LED(17)
    while True:
        light.on()
        sleep(1)
        light.off()
        sleep(1)

Con record_audio() grabamos el archivo de audio

def record_audio ():
    # Sampling frequency
    freq = 44100
    # Recording duration
    duration = 5
    # Start recorder with the given values
    # of duration and sample frequency
    recording = sd.rec(int(duration * freq),
                    samplerate=freq, channels=2)
    # Record audio for the given number of seconds
    sd.wait()
    # This will convert the NumPy array to an audio
    # file with the given sampling frequency
    write("audio0.wav", freq, recording)
    # Convert the NumPy array to audio file
    wv.write("audio1.wav", recording, freq, sampwidth=2)

Main es la función principal, fíjate que lo único que tenemos fuera de funciones es la llamada a main () al final del script. De esta forma al iniciarse, importará las librerías y luego hace la llamada a la función.

def main ():
    inicio = time.time()
    record_audio ()

    model = whisper.load_model("tiny")
    result = model.transcribe("audio1.wav")
    words = result["text"].split()

    for word in words:
        word = word.replace(',', '').replace('.', '').lower()
        if word == 'enciende' or 'encender':
            encender()
            break
        if word == 'parpadea' or 'parpadear':
            parpadear()
            break      
    fin = time.time()
    print(fin-inicio)

Guardamos la hora a la que empezamos a ejecutar la función y luego llamamos a la función de grabar audio que grabará nuestra instrucción en un archivo .wav, .mp3, etc que convertiremos luego a texto

    inicio = time.time()
    record_audio ()

  

Una vez tenemos el audio, se llamará a whisper y le decimos el modelo que queremos utilizar, hay 5 disponibles, y usaremos tiny aunque es el más impreciso porque es el más rápido y el audio va a ser sencillo, tan solo 3 o 4 palabras.

     model = whisper.load_model("tiny")
    result = model.transcribe("audio1.wav")

  

Con esto tenemos el audio convertido a texto y guardado en una variable. Vamos a modificarla un poco.

Convertimos result en una lista con cada una de las palabras del audio

     words = result["text"].split()

  

Y todo listo para interactuar con nuestro dispositivo. Ahora solo tentemos que crear las condiciones que queramos.

Si el audio tiene la palabra X hacer Y. Como tenemos las palabras en una lista resulta muy sencillo ir agregando condiciones

         for word in words:
        word = word.replace(',', '').replace('.', '').lower()
        if word == 'enciende' or 'encender':
            encender()
            break
        if word == 'parpadea' or 'parpadear':
            parpadear()
            break   

  

La línea

         
        word = word.replace(',', '').replace('.', '').lower()


  

La utilizo para convertir las palabras del audio en minúsculas y quitar las comas y puntos. Y de esta forma evitar que haya errores en las comparaciones

En cada if si se cumple la condición de tener alguna delas palabras que hemos elegido llama a una función que hará lo que queramos,

Es ahí donde le decimos que active un PIN que encenderá un LED o que lo haga parpadear. O bien que ejecute un código, o apague el ordenador.

Todo esto es una idea básica. A partir de aquí puedes desarrollar el proyecto y mejorarlo como quieras. Cada persona puede encontrarle una utilidad diferente.

Cosas que podemos hacer con este montaje

Esto son ideas que que me surgen para aprovechar este montaje. Una vez con el esqueleto armado ya podemos utilizarlo para activar por voz todo lo que se nos ocurra, podemos activar un relé que ponga en marcha un motor o podemos lanzar un script que ejecute algún script, un mail o lo que sea.

Qué es Whisper

Whisper es un modelo de reconocimiento de vol, trabaja en multidioma con una gran cantidad de lenguajes y permite la traducción al inglés. Es lo que conocemos como una herramienta text-to-voice, liberada por el equipo de OpenAI, los creadores de Dall-e.

Deja un comentario