홈으로 돌아가기

C# 음성 인식 VK Cloud 후크 포함

이 기사는 VK Cloud API, NAudio 및 전역 키보드 후크를 사용한 C# 음성 인식 유틸리티 구현을 설명합니다. 이 애플리케이션은 단축키로 오디오를 녹음하고 서버로 전송하며 클립보드를 통해 텍스트를 삽입합니다. 오류 처리와 함께 전체 코드.

C# 음성 입력: 후크 + VK Cloud ASR
Advertisement 728x90

VK 클라우드와 함께 C#으로 음성 인식: 저수준 훅과 NAudio 활용

개발자가 마이크를 통해 음성을 캡처하고, VK 클라우드 음성 인식 API로 전송한 후 결과 텍스트를 클립보드에 삽입하는 콘솔 애플리케이션을 만들었습니다. 녹음은 오른쪽 Ctrl 키를 누르면 시작되고, 떼면 처리가 실행됩니다. 전역 키보드 훅을 통해 활성화되며, NAudio는 16kHz, 16비트, 모노 형식의 WAV 파일을 녹음하고, HttpClient는 15초 타임아웃으로 API 요청을 관리합니다.

코드는 Windows 전용이며, SetWindowsHookEx 사용 시 관리자 권한으로 실행해야 합니다. VK 클라우드 토큰은 상수로 하드코딩되어 있으며, 개인 대시보드에서 발급받은 서비스 키입니다.

녹음 활성화를 위한 전역 훅

저수준 키보드 훅(WH_KEYBOARD_LL)은 WM_KEYDOWN/WM_KEYUP 이벤트를 가로챕니다. 오른쪽 Ctrl 키(0xA3)를 누르면 비동기적으로 녹음을 시작하거나 중지합니다. ESC 키를 누르면 애플리케이션이 종료됩니다.

Google AdInline article slot

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

HookCallback 내부에서 lParam의 vkCode를 확인합니다. 만약 !isRecording && !isProcessing라면, Task.Run(() => StartRecordingAsync())를 실행합니다.

오디오 캡처 및 처리

WaveInEvent는 16,000Hz로 설정됩니다. DataAvailable 이벤트는 WaveFileWriter를 사용해 임시 voice_temp.wav 파일에 데이터를 기록합니다. 녹음이 중지된 후 파일 크기를 검사(1,000바이트 이상)한 후 인식 작업을 진행합니다.

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

StopRecordingAndProcessAsync에서는 리소스를 해제하고 200밀리초 지연 후, Bearer 토큰을 포함해 RecognizeSpeechAsync를 호출합니다.

VK 클라우드 음성 인식 API 연동

https://voice.mcs.mail.ru/asr로 POST 요청을 보내며, 컨텐츠 타입은 audio/wave입니다. 응답은 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);

에러 처리에는 인증 실패(토큰 만료), 타임아웃, HTTP 상태 코드 등이 포함됩니다. 콘솔에 이모티콘을 사용해 시각적 피드백을 제공합니다.

Google AdInline article slot
  • 성공: 텍스트가 클립보드에 삽입되고, 로그에 "✅ 인식됨" 표시.
  • 짧은 파일: 1,000바이트 미만일 경우 건너뜁니다.
  • API 오류: 베이프 소리 + 상세 정보 출력.

STA 스레드를 통한 텍스트 삽입

Clipboard.SetText는 단일 스레드 아파트(STA) 환경에서만 작동합니다. 별도의 스레드를 생성하고 SetApartmentState(STA)를 설정한 후 Join()으로 완료를 기다립니다.

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

SendKeys나 UI 자동화 방식도 가능하지만, 이 방법은 Ctrl+V를 통해 신뢰성 있게 동작합니다.

핵심 포인트

  • 전역 훅: WH_KEYBOARD_LL는 관리자 권한 필요, 모든 프로세스에 주입 가능.
  • 오디오 형식: 16kHz / 16비트 / 모노 — VK 클라우드 ASR 최적.
  • 비동기 처리: Task.Run으로 훅 차단 방지.
  • 보안: 토큰이 코드에 내장됨 — 개인용으로만 사용; 절대 저장소에 커밋 금지.
  • 제한 사항: 직접 입력 대신 클립보드 기반 출력; 저장 비용 약 3루블/문서.

— Editorial Team

Advertisement 728x90

다음 읽기