Reconocimiento de Voz de IA en Unity

Reconocimiento de Voz IA en Unity.

Introducción

Este tutorial te guía a través del proceso de implementar Reconocimiento de Voz de última generación en tu juego Unity utilizando la API de Unity de Hugging Face. Esta característica se puede utilizar para dar comandos, hablar con un NPC, mejorar la accesibilidad o cualquier otra funcionalidad donde convertir palabras habladas a texto pueda ser útil.

Para probar el Reconocimiento de Voz en Unity por ti mismo, echa un vistazo a la demostración en vivo en itch.io .

Prerrequisitos

Este tutorial asume conocimientos básicos de Unity. También requiere que hayas instalado la API de Unity de Hugging Face. Para obtener instrucciones sobre cómo configurar la API, consulta nuestra publicación de blog anterior .

Pasos

1. Configurar la Escena

En este tutorial, configuraremos una escena muy simple donde el jugador puede comenzar y detener una grabación, y el resultado se convertirá en texto.

Comienza creando un proyecto de Unity, luego crea un Canvas con cuatro elementos de IU:

  1. Botón de Inicio: Esto iniciará la grabación.
  2. Botón de Detener: Esto detendrá la grabación.
  3. Texto (TextMeshPro): Aquí se mostrará el resultado del reconocimiento de voz.

2. Configurar el Script

Crea un script llamado SpeechRecognitionTest y adjúntalo a un GameObject vacío.

En el script, define referencias a tus componentes de IU:

[SerializeField] private Button startButton;
[SerializeField] private Button stopButton;
[SerializeField] private TextMeshProUGUI text;

Asígnalos en el inspector.

Luego, utiliza el método Start() para configurar los listeners para los botones de inicio y detener:

private void Start() {
    startButton.onClick.AddListener(StartRecording);
    stopButton.onClick.AddListener(StopRecording);
}

En este punto, tu script debería lucir algo así:

using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class SpeechRecognitionTest : MonoBehaviour {
    [SerializeField] private Button startButton;
    [SerializeField] private Button stopButton;
    [SerializeField] private TextMeshProUGUI text;

    private void Start() {
        startButton.onClick.AddListener(StartRecording);
        stopButton.onClick.AddListener(StopRecording);
    }

    private void StartRecording() {

    }

    private void StopRecording() {

    }
}

3. Grabar Entrada de Micrófono

Ahora vamos a grabar la entrada del micrófono y codificarla en formato WAV. Comienza definiendo las variables miembro:

private AudioClip clip;
private byte[] bytes;
private bool recording;

Luego, en StartRecording(), utiliza el método Microphone.Start() para comenzar a grabar:

private void StartRecording() {
    clip = Microphone.Start(null, false, 10, 44100);
    recording = true;
}

Esto grabará hasta 10 segundos de audio a 44100 Hz.

En caso de que la grabación alcance su duración máxima de 10 segundos, querremos detener la grabación automáticamente. Para hacerlo, escribe lo siguiente en el método Update():

private void Update() {
    if (recording && Microphone.GetPosition(null) >= clip.samples) {
        StopRecording();
    }
}

Luego, en StopRecording(), trunca la grabación y cámbiala al formato WAV:

private void StopRecording() {
    var position = Microphone.GetPosition(null);
    Microphone.End(null);
    var samples = new float[position * clip.channels];
    clip.GetData(samples, 0);
    bytes = EncodeAsWAV(samples, clip.frequency, clip.channels);
    recording = false;
}

Finalmente, necesitaremos implementar el método EncodeAsWAV() para preparar los datos de audio para la API de Hugging Face:

private byte[] EncodeAsWAV(float[] samples, int frequency, int channels) {
    using (var memoryStream = new MemoryStream(44 + samples.Length * 2)) {
        using (var writer = new BinaryWriter(memoryStream)) {
            writer.Write("RIFF".ToCharArray());
            writer.Write(36 + samples.Length * 2);
            writer.Write("WAVE".ToCharArray());
            writer.Write("fmt ".ToCharArray());
            writer.Write(16);
            writer.Write((ushort)1);
            writer.Write((ushort)channels);
            writer.Write(frequency);
            writer.Write(frequency * channels * 2);
            writer.Write((ushort)(channels * 2));
            writer.Write((ushort)16);
            writer.Write("data".ToCharArray());
            writer.Write(samples.Length * 2);

            foreach (var sample in samples) {
                writer.Write((short)(sample * short.MaxValue));
            }
        }
        return memoryStream.ToArray();
    }
}

El script completo debería verse algo así:

using System.IO;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class PruebaReconocimientoVoz : MonoBehaviour {
    [SerializeField] private Button botonInicio;
    [SerializeField] private Button botonDetener;
    [SerializeField] private TextMeshProUGUI texto;

    private AudioClip clip;
    private byte[] bytes;
    private bool grabando;

    private void Start() {
        botonInicio.onClick.AddListener(IniciarGrabacion);
        botonDetener.onClick.AddListener(DetenerGrabacion);
    }

    private void Update() {
        if (grabando && Microphone.GetPosition(null) >= clip.samples) {
            DetenerGrabacion();
        }
    }

    private void IniciarGrabacion() {
        clip = Microphone.Start(null, false, 10, 44100);
        grabando = true;
    }

    private void DetenerGrabacion() {
        var posicion = Microphone.GetPosition(null);
        Microphone.End(null);
        var muestras = new float[posicion * clip.channels];
        clip.GetData(muestras, 0);
        bytes = CodificarComoWAV(muestras, clip.frequency, clip.channels);
        grabando = false;
    }

    private byte[] CodificarComoWAV(float[] muestras, int frecuencia, int canales) {
        using (var memoryStream = new MemoryStream(44 + muestras.Length * 2)) {
            using (var writer = new BinaryWriter(memoryStream)) {
                writer.Write("RIFF".ToCharArray());
                writer.Write(36 + muestras.Length * 2);
                writer.Write("WAVE".ToCharArray());
                writer.Write("fmt ".ToCharArray());
                writer.Write(16);
                writer.Write((ushort)1);
                writer.Write((ushort)canales);
                writer.Write(frecuencia);
                writer.Write(frecuencia * canales * 2);
                writer.Write((ushort)(canales * 2));
                writer.Write((ushort)16);
                writer.Write("data".ToCharArray());
                writer.Write(muestras.Length * 2);

                foreach (var muestra in muestras) {
                    writer.Write((short)(muestra * short.MaxValue));
                }
            }
            return memoryStream.ToArray();
        }
    }
}

Para probar si este código funciona correctamente, puedes agregar la siguiente línea al final del método DetenerGrabacion():

File.WriteAllBytes(Application.dataPath + "/test.wav", bytes);

Ahora, si haces clic en el botón Iniciar, hablas por el micrófono y haces clic en Detener, se guardará un archivo test.wav en la carpeta de Assets de Unity con el audio grabado.

4. Reconocimiento de Voz

A continuación, querremos utilizar la API de Hugging Face Unity para ejecutar el reconocimiento de voz en nuestro audio codificado. Para hacerlo, crearemos un método EnviarGrabacion():

using HuggingFace.API;

private void EnviarGrabacion() {
    HuggingFaceAPI.ReconocimientoAutomaticoDeVoz(bytes, respuesta => {
        texto.color = Color.white;
        texto.text = respuesta;
    }, error => {
        texto.color = Color.red;
        texto.text = error;
    });
}

Esto enviará el audio codificado a la API, mostrando la respuesta en blanco si es exitosa, de lo contrario, el mensaje de error en rojo.

No olvides llamar a EnviarGrabacion() al final del método DetenerGrabacion():

private void DetenerGrabacion() {
    /* otro código */
    EnviarGrabacion();
}

5. Detalles Finales

Finalmente, vamos a mejorar un poco la experiencia de usuario de esta demostración utilizando la interacción de los botones y mensajes de estado.

Los botones de Iniciar y Detener solo deberían ser interactivos cuando sea apropiado, es decir, cuando se pueda iniciar/detener una grabación.

Luego, establece el texto de respuesta como un mensaje de estado simple mientras se graba o se espera a la API.

El script final debería verse algo así:

using System.IO;
using HuggingFace.API;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class PruebaReconocimientoVoz : MonoBehaviour {
    [SerializeField] private Button botonInicio;
    [SerializeField] private Button botonDetener;
    [SerializeField] private TextMeshProUGUI texto;

    private AudioClip clip;
    private byte[] bytes;
    private bool grabando;

    private void Start() {
        botonInicio.onClick.AddListener(IniciarGrabacion);
        botonDetener.onClick.AddListener(DetenerGrabacion);
        botonDetener.interactable = false;
    }

    private void Update() {
        if (grabando && Microphone.GetPosition(null) >= clip.samples) {
            DetenerGrabacion();
        }
    }

    private void IniciarGrabacion() {
        texto.color = Color.white;
        texto.text = "Grabando...";
        botonInicio.interactable = false;
        botonDetener.interactable = true;
        clip = Microphone.Start(null, false, 10, 44100);
        grabando = true;
    }

    private void DetenerGrabacion() {
        var posicion = Microphone.GetPosition(null);
        Microphone.End(null);
        var muestras = new float[posicion * clip.channels];
        clip.GetData(muestras, 0);
        bytes = CodificarComoWAV(muestras, clip.frequency, clip.channels);
        grabando = false;
        EnviarGrabacion();
    }

    private void EnviarGrabacion() {
        texto.color = Color.yellow;
        texto.text = "Enviando...";
        botonDetener.interactable = false;
        HuggingFaceAPI.ReconocimientoAutomaticoDeVoz(bytes, respuesta => {
            texto.color = Color.white;
            texto.text = respuesta;
            botonInicio.interactable = true;
        }, error => {
            texto.color = Color.red;
            texto.text = error;
            botonInicio.interactable = true;
        });
    }

    private byte[] CodificarComoWAV(float[] muestras, int frecuencia, int canales) {
        using (var memoryStream = new MemoryStream(44 + muestras.Length * 2)) {
            using (var writer = new BinaryWriter(memoryStream)) {
                writer.Write("RIFF".ToCharArray());
                writer.Write(36 + muestras.Length * 2);
                writer.Write("WAVE".ToCharArray());
                writer.Write("fmt ".ToCharArray());
                writer.Write(16);
                writer.Write((ushort)1);
                writer.Write((ushort)canales);
                writer.Write(frecuencia);
                writer.Write(frecuencia * canales * 2);
                writer.Write((ushort)(canales * 2));
                writer.Write((ushort)16);
                writer.Write("data".ToCharArray());
                writer.Write(muestras.Length * 2);

                foreach (var muestra in muestras) {
                    writer.Write((short)(muestra * short.MaxValue));
                }
            }
            return memoryStream.ToArray();
        }
    }
}

¡Felicitaciones, ahora puedes usar el reconocimiento de voz de última generación en Unity!

Si tienes alguna pregunta o quieres involucrarte más en el uso de Hugging Face para juegos, ¡únete a Hugging Face Discord!

We will continue to update Zepes; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

Inteligencia Artificial

Combatir la suplantación de identidad por la IA

Encontrar formas de determinar si un mensaje de voz es real o generado por una inteligencia artificial.

Inteligencia Artificial

El cucaracha cibernético puede navegar por un laberinto

Los investigadores han desarrollado un método para crear cucarachas ciborg para ser utilizadas en misiones de búsqued...

Inteligencia Artificial

Visión del PM Modi sobre la regulación de la IA en India Cumbre B20 2023

A medida que el B20 Summit India 2023 llegaba a su fin en Delhi, las palabras del primer ministro Narendra Modi conti...

Inteligencia Artificial

Tu guía para AI y ML generativos en AWS reInvent 2023

Sí, la temporada de AWS reInvent está sobre nosotros y como siempre, ¡el lugar para estar es Las Vegas! Marcaste tus ...

Inteligencia Artificial

Gorra de Ondas Cerebrales Salva Vidas al Identificar Derrames Cerebrales

El gorro StrokePointer de ondas cerebrales, diseñado por investigadores en los Países Bajos, puede diagnosticar un de...

Inteligencia Artificial

Principal Financial Group utiliza la solución de análisis posterior a la llamada de AWS para extraer información sobre los clientes omnicanal

Una empresa de servicios financieros establecida con más de 140 años en el negocio, Principal es líder mundial en ges...