Volver al inicio

Reconocimiento de voz C# VK Cloud con hooks

El artículo describe la implementación de una utilidad para reconocimiento de voz en C# usando VK Cloud API, NAudio y hooks de teclado globales. La aplicación graba audio con atajos de teclado, envía al servidor e inserta texto vía portapapeles. Código completo con manejo de errores.

Entrada de voz en C#: hooks + VK Cloud ASR
Advertisement 728x90

Reconocimiento de voz en C# con VK Cloud: Ganchos de bajo nivel y NAudio

Un desarrollador creó una aplicación de consola en C# que captura voz mediante micrófono, envía el audio a la API de reconocimiento de voz de VK Cloud y inserta el texto reconocido en el portapapeles. La activación se gestiona mediante ganchos de teclado globales: mantener presionada la tecla Ctrl derecha inicia la grabación, soltarla desencadena el procesamiento. NAudio maneja la grabación WAV (16 kHz, 16 bits, mono), mientras HttpClient gestiona las solicitudes a la API con un tiempo de espera de 15 segundos.

El código es específico de Windows y requiere ejecutarse como administrador debido a SetWindowsHookEx. El token de VK Cloud está codificado como una constante — se trata de una clave de servicio desde tu panel personal.

Ganchos globales para activar la grabación

El gancho de teclado de bajo nivel (WH_KEYBOARD_LL) intercepta los eventos WM_KEYDOWN/WM_KEYUP. Presionar la tecla Ctrl derecha (0xA3) inicia o detiene la grabación de forma asíncrona. Presionar ESC cierra la aplicación.

Google AdInline article slot

Declaraciones P/Invoke clave:

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);

En HookCallback, se verifica vkCode desde lParam. Si !isRecording && !isProcessing, se inicia un Task.Run(() => StartRecordingAsync()).

Captura y procesamiento de audio

WaveInEvent se configura a 16.000 Hz. DataAvailable escribe los datos en un archivo temporal voice_temp.wav usando WaveFileWriter. Tras detenerse, se comprueba el tamaño del archivo (>1.000 bytes), luego se procede al reconocimiento.

Google AdInline article slot
var waveFormat = new WaveFormat(16000, 16, 1);
waveIn = new WaveInEvent { WaveFormat = waveFormat };
writer = new WaveFileWriter(OutputFileName, waveIn.WaveFormat);
waveIn.DataAvailable += (s, e) => writer?.Write(e.Buffer, 0, e.BytesRecorded);

En StopRecordingAndProcessAsync: se liberan los recursos, se espera 200 ms, luego se llama a RecognizeSpeechAsync con un token Bearer.

Integración con la API de reconocimiento de voz de VK Cloud

Solicitud POST a https://voice.mcs.mail.ru/asr con tipo de contenido audio/wave. La respuesta se parsea usando Newtonsoft.Json.Linq: result.texts[0].punctuated_text.

var request = new HttpRequestMessage(HttpMethod.Post, "https://voice.mcs.mail.ru/asr");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
request.Content = content;
var response = await httpClient.SendAsync(request);

El manejo de errores incluye Unauthorized (token caducado), tiempos de espera y códigos de estado HTTP. Los registros aparecen en la consola con emojis para retroalimentación visual.

Google AdInline article slot
  • Éxito: El texto se coloca en el portapapeles, el registro muestra "✅ Reconocido".
  • Archivo corto: Se omite si tiene menos de 1.000 bytes.
  • Error de API: Sonido de alerta + detalles mostrados.

Inserción de texto mediante hilo STA

Clipboard.SetText requiere un contexto STA (Single-Threaded Apartment). Se crea un hilo separado con SetApartmentState(STA), luego Join() espera la finalización.

Thread staThread = new Thread(() => {
    Clipboard.SetText(text, TextDataFormat.Text);
});
staThread.SetApartmentState(ApartmentState.STA);
staThread.Start();
staThread.Join();

Otras alternativas incluyen SendKeys o Automatización de interfaz, pero este método funciona de forma confiable mediante Ctrl+V.

Puntos clave

  • Ganchos globales: WH_KEYBOARD_LL requiere privilegios de administrador e inyecta en cualquier proceso.
  • Formato de audio: 16 kHz / 16 bits / mono — óptimo para ASR de VK Cloud.
  • Asincronía: Task.Run evita bloqueos en el gancho.
  • Seguridad: Token incrustado en el código — pensado solo para uso personal; nunca lo subas a repositorios.
  • Limitaciones: Salida basada en portapapeles en lugar de entrada directa; costo de almacenamiento ~3 rublos por artículo.

— Editorial Team

Advertisement 728x90

Leer después