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

Obteniendo audio de imágenes estáticas, videos silenciosos

Una herramienta de aprendizaje automático desarrollada en la Universidad Northeastern puede obtener audio de imágenes...

Inteligencia Artificial

¿Podemos transformar texto en gráficos vectoriales científicos? Este artículo de IA presenta AutomaTikZ y explica el poder de TikZ

Los últimos avances en la generación de texto a imagen han hecho posible la creación de gráficos detallados a partir ...

Inteligencia Artificial

Conoce Quivr Un proyecto de código abierto diseñado para almacenar y recuperar información desestructurada como un segundo cerebro

Ha habido un crecimiento continuo en el dominio de OpenAI en los últimos años. Investigadores de muchas universidades...

Inteligencia Artificial

Investigadores del MIT presentan LILO un marco neuro-simbólico para aprender bibliotecas interpretables para la síntesis de programas

Los grandes modelos de lenguaje (LLMs) se están volviendo cada vez más expertos en programación en varios contextos, ...

Inteligencia Artificial

Confrontación de modelos de chat GPT-4 vs GPT-3.5 vs LLaMA-2 en un debate simulado - Parte 1

Con Meta revelando recientemente planes para construir un modelo de chat que competirá con GPT-4, y el lanzamiento de...