Zpět na domů

C# rozpoznávání řeči VK Cloud s hooks

Článek popisuje implementaci nástroje pro rozpoznávání řeči v C# s využitím VK Cloud API, NAudio a globálních klávesových hooks. Aplikace nahrává audio podle klávesových zkratek, odesílá na server a vkládá text přes schránku. Kompletní kód s zpracováním chyb.

Hlasový vstup v C#: hooks + VK Cloud ASR
Advertisement 728x90

Rozpoznávání řeči v C# s VK Cloud: nízkoúrovňové hooky a NAudio

Vývojář vytvořil konzolovou aplikaci v C#, která zachycuje hlas přes mikrofon, odesílá zvukový signál do služby VK Cloud Speech API a vkládá rozpoznaný text do schránky. Ovládání probíhá prostřednictvím globálních klávesových hooků: podržení pravého Ctrl aktivuje nahrávání, puštění jej zahájí zpracování. Pro nahrávání se používá NAudio pro formát WAV (16 kHz, 16 bitů, mono), požadavky na API jsou odesílány pomocí HttpClient s časovým limitem 15 sekund.

Kód je určen pro Windows a vyžaduje spuštění s oprávněními správce kvůli funkci SetWindowsHookEx. Klíč VK Cloud je vložen jako konstanta – jedná se o služební klíč z osobního účtu.

Globální hooky pro aktivaci nahrávání

Nízkoúrovňový keyboard hook (WH_KEYBOARD_LL) zachytává události WM_KEYDOWN/WM_KEYUP. Pravý Ctrl (0xA3) spustí/zastaví nahrávání asynchronně. Stisknutí ESC ukončí aplikaci.

Google AdInline article slot

Klíčové deklarace P/Invoke:

[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);

Ve funkci HookCallback se kontroluje vkCode z parametru lParam. Pokud !isRecording && !isProcessing, spustí se Task.Run(() => StartRecordingAsync()).

Zachycení a zpracování zvuku

WaveInEvent je nastaveno na 16 000 Hz. Událost DataAvailable zapisuje do WaveFileWriter do dočasného souboru voice_temp.wav. Po zastavení se ověří velikost souboru (>1000 bajtů), poté následuje rozpoznání.

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);

Ve StopRecordingAndProcessAsync: uvolnění prostředků, zpoždění 200 ms, volání RecognizeSpeechAsync s Bearer-tokenu.

Integrace s VK Cloud Speech API

POST na https://voice.mcs.mail.ru/asr s obsahem typu audio/wave. Odpověď se analyzuje pomocí 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);

Zpracování chyb: Unauthorized (vypršel token), časový limit, HTTP stavy. Logy se zobrazují v konzoli s emoji pro indikaci stavu.

Google AdInline article slot
  • Úspěch: text vložen do schránky, log "✅ Rozpoznáno".
  • Krátce záznam: přeskočeno (<1000 bajtů).
  • Chyba API: zvukový signál + detaily.

Vložení textu prostřednictvím STA vlákna

Clipboard.SetText vyžaduje STA (Single-Threaded Apartment). Vytvoří se samostatné vlákno s nastavením SetApartmentState(STA), Join() čeká na dokončení.

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

Alternativa: SendKeys nebo UI Automation, ale současný přístup funguje přes Ctrl+V.

Důležité informace

  • Globální hooky: WH_KEYBOARD_LL vyžaduje oprávnění správce a injektuje do jakéhokoli procesu.
  • Formát zvuku: 16 kHz / 16 bitů / mono – ideální pro VK Cloud ASR.
  • Asynchronnost: Task.Run zabrání blokování hooku.
  • Bezpečnost: token je v kódu – určený pro osobní použití, neposílejte ho do repozitáře.
  • Omezení: pouze vložení do schránky místo přímého vkládání, náklady cca 3 Kč za článek na uchování.

— Editorial Team

Advertisement 728x90

Číst dál