Program.cs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. using AliFsmnVadSharp;
  2. using NAudio.Wave;
  3. using System.Collections.Concurrent;
  4. using WebSocketSpace;
  5. using NAudio.CoreAudioApi;
  6. using System.IO;
  7. using System.Collections.Specialized;
  8. namespace FunASRWSClient_Online
  9. {
  10. /// <summary>
  11. /// /主程序入口
  12. /// </summary>
  13. public class Program
  14. {
  15. private static void Main()
  16. {
  17. WSClient_Online m_funasrclient = new WSClient_Online();
  18. m_funasrclient.FunASR_Main();
  19. }
  20. }
  21. /// <summary>
  22. /// /主线程入口,初始化后读取数据
  23. /// </summary>
  24. public class WSClient_Online
  25. {
  26. /// <summary>
  27. /// FunASR客户端软件运行状态
  28. /// </summary>
  29. ///
  30. public static string host = "0.0.0.0";
  31. public static string port = "10095";
  32. public static string onlineasrmode = string.Empty;
  33. private static WaveCollect m_wavecollect = new WaveCollect();
  34. private static CWebSocketClient m_websocketclient = new CWebSocketClient();
  35. public static readonly ConcurrentQueue<byte[]> ActiveAudioSet = new ConcurrentQueue<byte[]>();
  36. public static readonly ConcurrentQueue<string> AudioFileQueue = new ConcurrentQueue<string>();
  37. [STAThread]
  38. public void FunASR_Main()
  39. {
  40. loadconfig();
  41. //麦克风状态监测
  42. string errorStatus = string.Empty;
  43. if (GetCurrentMicVolume() == -2)
  44. errorStatus = "注意:麦克风被设置为静音!";
  45. else if (GetCurrentMicVolume() == -1)
  46. errorStatus = "注意:麦克风未连接!";
  47. else if (GetCurrentMicVolume() == 0)
  48. errorStatus = "注意:麦克风声音设置为0!";
  49. //初始化通信连接
  50. string commstatus = ClientConnTest();
  51. if (commstatus != "通信连接成功")
  52. errorStatus = commstatus;
  53. //程序初始监测异常--报错、退出
  54. if (errorStatus != string.Empty)
  55. {
  56. Environment.Exit(0);//报错方式待加
  57. }
  58. //启动客户端向服务端发送音频数据线程
  59. Thread SendAudioThread = new Thread(SendAudioToSeverAsync);
  60. SendAudioThread.Start();
  61. //启动音频文件转录线程
  62. Thread AudioFileThread = new Thread(SendAudioFileToSeverAsync);
  63. AudioFileThread.Start();
  64. while (true)
  65. {
  66. Console.WriteLine("请选择语音识别方式:1.离线文件转写;2.实时语音识别");
  67. string str = Console.ReadLine();
  68. if (str != string.Empty)
  69. {
  70. if (str == "1")//离线文件转写
  71. {
  72. onlineasrmode = "offline";
  73. Console.WriteLine("请输入转录文件路径");
  74. str = Console.ReadLine();
  75. if (!string.IsNullOrEmpty(str))
  76. AudioFileQueue.Enqueue(str);
  77. }
  78. else if (str == "2")//实时语音识别
  79. {
  80. Console.WriteLine("请输入实时语音识别模式:1.online;2.2pass");
  81. str = Console.ReadLine();
  82. OnlineASR(str);
  83. }
  84. }
  85. }
  86. }
  87. private void loadconfig()
  88. {
  89. string filePath = "config.ini";
  90. NameValueCollection settings = new NameValueCollection();
  91. using (StreamReader reader = new StreamReader(filePath))
  92. {
  93. string line;
  94. while ((line = reader.ReadLine()) != null)
  95. {
  96. // 忽略空行和注释
  97. if (string.IsNullOrEmpty(line) || line.StartsWith(";") || line.StartsWith("#"))
  98. continue;
  99. // 解析键值对
  100. int equalsIndex = line.IndexOf('=');
  101. if (equalsIndex > 0)
  102. {
  103. string key = line.Substring(0, equalsIndex).Trim();
  104. string value = line.Substring(equalsIndex + 1).Trim();
  105. if (key == "host")
  106. host = value;
  107. else if (key == "port")
  108. port = value;
  109. }
  110. }
  111. }
  112. }
  113. private void OnlineASR(string str)
  114. {
  115. if (!string.IsNullOrEmpty(str))
  116. {
  117. if (str == "1")//实时语音识别
  118. onlineasrmode = "online";
  119. else if (str == "2")//实时语音识别-动态修正
  120. onlineasrmode = "2pass";
  121. }
  122. //开始录制声音、发送识别
  123. if (onlineasrmode != string.Empty)
  124. {
  125. m_wavecollect.StartRec();
  126. m_websocketclient.ClientFirstConnOnline(onlineasrmode);
  127. try
  128. {
  129. while (true)
  130. {
  131. if (!WaveCollect.voicebuff.IsEmpty)
  132. {
  133. byte[] buff;
  134. int buffcnt = WaveCollect.voicebuff.Count;
  135. WaveCollect.voicebuff.TryDequeue(out buff);
  136. if (buff != null)
  137. ActiveAudioSet.Enqueue(buff);
  138. }
  139. else
  140. {
  141. if (Console.KeyAvailable)
  142. {
  143. var key = Console.ReadKey(true);
  144. // 检测到按下Ctrl+C
  145. if ((key.Modifiers & ConsoleModifiers.Control) != 0 && key.Key == ConsoleKey.C)
  146. {
  147. // 执行相应的操作
  148. Console.WriteLine("Ctrl+C Pressed!");
  149. // 退出循环或执行其他操作
  150. break;
  151. }
  152. }
  153. else
  154. {
  155. Thread.Sleep(10);
  156. }
  157. }
  158. }
  159. }
  160. catch
  161. {
  162. Console.WriteLine("实时识别出现异常!");
  163. }
  164. finally
  165. {
  166. m_wavecollect.StopRec();
  167. m_websocketclient.ClientLastConnOnline();
  168. }
  169. }
  170. }
  171. private string ClientConnTest()
  172. {
  173. //WebSocket连接状态监测
  174. Task<string> websocketstatus = m_websocketclient.ClientConnTest();
  175. if (websocketstatus != null && websocketstatus.Result.IndexOf("成功") == -1)
  176. return websocketstatus.Result;
  177. return "通信连接成功";
  178. }
  179. private void SendAudioFileToSeverAsync()
  180. {
  181. while (true)
  182. {
  183. Thread.Sleep(1000);
  184. if (AudioFileQueue.Count > 0)
  185. {
  186. string filepath = string.Empty;
  187. AudioFileQueue.TryDequeue(out filepath);
  188. if (filepath != string.Empty && filepath != null)
  189. {
  190. m_websocketclient.ClientSendFileFunc(filepath);
  191. }
  192. }
  193. else
  194. {
  195. Thread.Sleep(100);
  196. }
  197. }
  198. }
  199. private void SendAudioToSeverAsync()
  200. {
  201. while (true)
  202. {
  203. if (ActiveAudioSet.Count > 0)
  204. {
  205. byte[] audio;
  206. ActiveAudioSet.TryDequeue(out audio);
  207. if (audio == null)
  208. continue;
  209. byte[] mArray = new byte[audio.Length];
  210. Array.Copy(audio, 0, mArray, 0, audio.Length);
  211. if (mArray != null)
  212. m_websocketclient.ClientSendAudioFunc(mArray);
  213. }
  214. else
  215. {
  216. Thread.Sleep(10);
  217. }
  218. }
  219. }
  220. private void SaveAsWav(byte[] pcmData, string fileName, int sampleRate, int bitsPerSample, int channels)
  221. {
  222. using (var writer = new WaveFileWriter(fileName, new WaveFormat(sampleRate, bitsPerSample, channels)))
  223. {
  224. writer.Write(pcmData, 0, pcmData.Length);
  225. }
  226. }
  227. private int GetCurrentMicVolume() //获取麦克风设置
  228. {
  229. int volume = -1;
  230. var enumerator = new MMDeviceEnumerator();
  231. //获取音频输入设备
  232. IEnumerable<MMDevice> captureDevices = enumerator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active).ToArray();
  233. if (captureDevices.Count() > 0)
  234. {
  235. MMDevice mMDevice = captureDevices.ToList()[0];
  236. if (mMDevice.AudioEndpointVolume.Mute)
  237. return -2;
  238. volume = (int)(mMDevice.AudioEndpointVolume.MasterVolumeLevelScalar * 100);
  239. }
  240. return volume;
  241. }
  242. }
  243. }