Guest User

Untitled

a guest
Mar 26th, 2026
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.97 KB | None | 0 0
  1. using System;
  2. using System.Diagnostics;
  3. using System.IO;
  4. using System.Net.Http;
  5. using System.Net.Http.Headers;
  6. using System.Runtime.InteropServices;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10. using NAudio.Wave;
  11. using Newtonsoft.Json.Linq;
  12.  
  13. namespace VkVoiceTyper
  14. {
  15. class Program
  16. {
  17. // === СЕРВИСНЫЙ ТОКЕН VK CLOUD ===
  18. // Вставьте токен из настроек проекта VK Cloud
  19. private const string ServiceToken = "ВАШ_СЕРВИСНЫЙ_ТОКЕН_VC_...";
  20.  
  21. private const string OutputFileName = "voice_temp.wav";
  22.  
  23. // === ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ ===
  24. private static WaveInEvent? waveIn;
  25. private static WaveFileWriter? writer;
  26. private static bool isRecording = false;
  27. private static bool isProcessing = false;
  28.  
  29. // === HOOK API ===
  30. private const int WH_KEYBOARD_LL = 13;
  31. private const int WM_KEYDOWN = 0x0100;
  32. private const int WM_KEYUP = 0x0101;
  33. private const int VK_RCONTROL = 0xA3;
  34. private const int VK_ESCAPE = 0x1B;
  35.  
  36. private static LowLevelKeyboardProc proc = HookCallback;
  37. private static IntPtr hookID = IntPtr.Zero;
  38.  
  39. // HttpClient с таймаутом
  40. private static readonly HttpClient httpClient = new HttpClient()
  41. {
  42. Timeout = TimeSpan.FromSeconds(15)
  43. };
  44.  
  45. static void Main(string[] args)
  46. {
  47. Console.WriteLine("🎙️ VK VoiceTyper (Service Token)");
  48. Console.WriteLine("👉 Удерживайте ПРАВЫЙ CTRL для записи");
  49. Console.WriteLine("🔚 ESC — выход");
  50. Console.WriteLine("================================\n");
  51.  
  52. // Проверка токена при старте
  53. if (string.IsNullOrEmpty(ServiceToken) || ServiceToken == "ВАШ_СЕРВИСНЫЙ_ТОКЕН_VC_...")
  54. {
  55. Console.WriteLine("❌ Ошибка: Вставьте сервисный токен в код!");
  56. Console.WriteLine("Нажмите любую клавишу для выхода...");
  57. Console.ReadKey();
  58. return;
  59. }
  60.  
  61. Console.WriteLine("✅ Токен загружен. Сервис готов.\n");
  62.  
  63. hookID = SetHook(proc);
  64. Application.Run();
  65. }
  66.  
  67. // === HOOK CALLBACK ===
  68. private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
  69. {
  70. if (nCode >= 0)
  71. {
  72. int vkCode = Marshal.ReadInt32(lParam);
  73.  
  74. if (wParam == (IntPtr)WM_KEYDOWN && vkCode == VK_RCONTROL)
  75. {
  76. if (!isRecording && !isProcessing)
  77. Task.Run(() => StartRecordingAsync());
  78. }
  79. else if (wParam == (IntPtr)WM_KEYUP && vkCode == VK_RCONTROL)
  80. {
  81. if (isRecording)
  82. Task.Run(() => StopRecordingAndProcessAsync());
  83. }
  84. else if (wParam == (IntPtr)WM_KEYDOWN && vkCode == VK_ESCAPE)
  85. {
  86. UnhookWindowsHookEx(hookID);
  87. Application.Exit();
  88. return (IntPtr)1;
  89. }
  90. }
  91. return CallNextHookEx(hookID, nCode, wParam, lParam);
  92. }
  93.  
  94. private static IntPtr SetHook(LowLevelKeyboardProc proc)
  95. {
  96. using Process curProcess = Process.GetCurrentProcess();
  97. using ProcessModule? curModule = curProcess.MainModule;
  98. return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
  99. GetModuleHandle(curModule?.ModuleName), 0);
  100. }
  101.  
  102. private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
  103.  
  104. [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  105. private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
  106.  
  107. [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  108. [return: MarshalAs(UnmanagedType.Bool)]
  109. private static extern bool UnhookWindowsHookEx(IntPtr hhk);
  110.  
  111. [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  112. private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
  113.  
  114. [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  115. private static extern IntPtr GetModuleHandle(string? lpModuleName);
  116.  
  117. // === ЗАПИСЬ ===
  118. private static void StartRecordingAsync()
  119. {
  120. if (isRecording) return;
  121. isRecording = true;
  122. Console.WriteLine("🔴 Запись... (отпустите RCtrl)");
  123.  
  124. var waveFormat = new WaveFormat(16000, 16, 1);
  125. waveIn = new WaveInEvent { WaveFormat = waveFormat };
  126. writer = new WaveFileWriter(OutputFileName, waveIn.WaveFormat);
  127.  
  128. waveIn.DataAvailable += (s, e) => writer?.Write(e.Buffer, 0, e.BytesRecorded);
  129. waveIn.StartRecording();
  130. }
  131.  
  132. private static async Task StopRecordingAndProcessAsync()
  133. {
  134. if (!isRecording) return;
  135. isRecording = false;
  136. Console.WriteLine("⏹️ Остановка...");
  137.  
  138. waveIn?.StopRecording();
  139. waveIn?.Dispose();
  140. writer?.Dispose();
  141. waveIn = null;
  142. writer = null;
  143.  
  144. await Task.Delay(200);
  145.  
  146. if (!File.Exists(OutputFileName))
  147. {
  148. Console.WriteLine("⚠️ Файл не создан");
  149. return;
  150. }
  151.  
  152. long fileSize = new FileInfo(OutputFileName).Length;
  153. if (fileSize < 1000)
  154. {
  155. Console.WriteLine($"⚠️ Слишком короткая запись ({fileSize} байт)");
  156. return;
  157. }
  158.  
  159. isProcessing = true;
  160. Console.WriteLine("🔄 Распознавание...");
  161.  
  162. try
  163. {
  164. string? recognizedText = await RecognizeSpeechAsync(ServiceToken, OutputFileName);
  165.  
  166. if (!string.IsNullOrWhiteSpace(recognizedText))
  167. {
  168. Console.WriteLine($"✅ Распознано: \"{recognizedText}\"");
  169. InsertTextInStaThread(recognizedText);
  170. }
  171. else
  172. {
  173. Console.WriteLine("⚠️ Текст не распознан");
  174. System.Media.SystemSounds.Beep.Play();
  175. }
  176. }
  177. catch (TaskCanceledException)
  178. {
  179. Console.WriteLine("❌ Таймаут! Сервер не ответил за 15 секунд.");
  180. System.Media.SystemSounds.Beep.Play();
  181. }
  182. catch (Exception ex)
  183. {
  184. Console.WriteLine($"❌ Ошибка: {ex.Message}");
  185. if (ex.InnerException != null)
  186. Console.WriteLine($" Детали: {ex.InnerException.Message}");
  187. System.Media.SystemSounds.Beep.Play();
  188. }
  189. finally
  190. {
  191. isProcessing = false;
  192. if (File.Exists(OutputFileName))
  193. File.Delete(OutputFileName);
  194. }
  195. }
  196.  
  197. // === ВСТАВКА ТЕКСТА ===
  198. private static void InsertTextInStaThread(string text)
  199. {
  200. Thread staThread = new Thread(() =>
  201. {
  202. try
  203. {
  204. Clipboard.SetText(text, TextDataFormat.Text);
  205. Thread.Sleep(150);
  206. Console.WriteLine("📋 Текст скопирован в буфер обмена (Ctrl+V для вставки)");
  207. }
  208. catch (Exception ex)
  209. {
  210. Console.WriteLine($"⚠️ Ошибка буфера: {ex.Message}");
  211. }
  212. });
  213.  
  214. staThread.SetApartmentState(ApartmentState.STA);
  215. staThread.Start();
  216. staThread.Join();
  217. }
  218.  
  219. // === РАСПОЗНАВАНИЕ (с сервисным токеном) ===
  220. private static async Task<string?> RecognizeSpeechAsync(string token, string filePath)
  221. {
  222. try
  223. {
  224. byte[] fileBytes = File.ReadAllBytes(filePath);
  225. var content = new ByteArrayContent(fileBytes);
  226. content.Headers.ContentType = new MediaTypeHeaderValue("audio/wave");
  227.  
  228. var request = new HttpRequestMessage(HttpMethod.Post, "https://voice.mcs.mail.ru/asr");
  229.  
  230. // ✅ Сервисный токен используется напрямую
  231. request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
  232. request.Content = content;
  233.  
  234. Console.WriteLine("📤 Отправка в VK Cloud Voice...");
  235. var response = await httpClient.SendAsync(request);
  236.  
  237. if (response.IsSuccessStatusCode)
  238. {
  239. var json = await response.Content.ReadAsStringAsync();
  240. var jobject = JObject.Parse(json);
  241.  
  242. if (jobject["result"]?["texts"] is JArray texts && texts.Count > 0)
  243. {
  244. return texts[0]["punctuated_text"]?.ToString();
  245. }
  246. else
  247. {
  248. Console.WriteLine($"⚠️ Ответ сервера: {json}");
  249. return null;
  250. }
  251. }
  252. else
  253. {
  254. var error = await response.Content.ReadAsStringAsync();
  255. Console.WriteLine($"🔌 API ошибка: {response.StatusCode}");
  256. Console.WriteLine($" Детали: {error}");
  257.  
  258. // Проверка на истёкший токен
  259. if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
  260. {
  261. Console.WriteLine("⚠️ Токен недействителен. Получите новый в VK Cloud.");
  262. }
  263.  
  264. return null;
  265. }
  266. }
  267. catch (Exception ex)
  268. {
  269. Console.WriteLine($"🔌 Ошибка распознавания: {ex.Message}");
  270. throw;
  271. }
  272. }
  273. }
  274. }
Advertisement
Add Comment
Please, Sign In to add comment