当前位置:   article > 正文

C#(WPF)通过WebAPI方式调用科大讯飞实现语音识别_.net webapi语音播报

.net webapi语音播报

参考连接:

语音听写(流式版)WebAPI 文档 | 讯飞开放平台文档中心 (xfyun.cn)

http://t.csdnimg.cn/4zSMA

http://t.csdnimg.cn/1IXfO

        在用WPF做上位机的时候需要用到科大讯飞的语音识别功能,看了看官方文档在Windows上想要实现语音识别可以通过WebAPI或者SDK的方式实现。

        在网上对比了两种方法,SDK好像不能直接用到C#上面,而且还要往文件里引入好几个库,本着偷懒的想法就选择了WebAPI的方法,相对来说会简洁一点。

        使用的是.NET Framework 4.7.2

        如果将修改成以下参数,识别速度会大大加快但是没有经过大量测试不能保证稳定性。

        int frameSize = 6400;
        int intervel = 10;

3.14更新:

        主要是在接收返回结果的函数中,对是否接收到服务器的结果全部返回标识做了判断,并断开与服务器的连接

  1. using HandyControl.Controls;
  2. using Newtonsoft.Json;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Net.WebSockets;
  8. using System.Security.Cryptography;
  9. using System.Text;
  10. using System.Threading;
  11. using System.Threading.Tasks;
  12. using System.Windows;
  13. using System.Windows.Controls;
  14. using System.Windows.Data;
  15. using System.Windows.Documents;
  16. using System.Windows.Input;
  17. using System.Windows.Media;
  18. using System.Windows.Media.Imaging;
  19. using System.Windows.Navigation;
  20. using System.Windows.Shapes;
  21. namespace HandyControlTest
  22. {
  23. /// <summary>
  24. /// MainWindow.xaml 的交互逻辑
  25. /// </summary>
  26. public partial class MainWindow : System.Windows.Window
  27. {
  28. recorder r = new recorder();
  29. public MainWindow()
  30. {
  31. InitializeComponent();
  32. }
  33. private void Button_Click(object sender, RoutedEventArgs e)
  34. {
  35. r.SendFileToWebSocket();
  36. r.receiveMessage();
  37. }
  38. }
  39. }
  40. class recorder
  41. {
  42. private string _appID = "6f28cdb3";
  43. private string _apiSecret = "Mzc3OWJjYjQxYjI5YzVhNWMwYzdiNmFk";
  44. private string _apiKey = "bf7d03b453328d790a0d2efabe47a1db";
  45. private string _wss = "wss://iat-api.xfyun.cn/v2/iat";
  46. private string _host = "iat-api.xfyun.cn";
  47. private string _request_line = "GET /v2/iat HTTP/1.1";
  48. private bool _isConnected = false;//连接服务器标志位
  49. private bool _isSendDone = false;//已经完成发送
  50. private WebSocket _ws;
  51. //创建url
  52. private string GetUrl()
  53. {
  54. string date = DateTime.Now.ToString("R");
  55. string signature_origin = $"host: {_host}\ndate: {date}\n{_request_line}";
  56. HMACSHA256 mac = new HMACSHA256(Encoding.UTF8.GetBytes(_apiSecret));
  57. string signature = Convert.ToBase64String(mac.ComputeHash(Encoding.UTF8.GetBytes(signature_origin)));
  58. string authorization_origin = $"api_key=\"{_apiKey}\",algorithm=\"hmac-sha256\",headers=\"host date request-line\",signature=\"{signature}\"";
  59. string authorization = Convert.ToBase64String(Encoding.UTF8.GetBytes(authorization_origin));
  60. string url = $"{_wss}?authorization={authorization}&date={date}&host={_host}";
  61. return url;
  62. }
  63. //连接WebSocket服务器
  64. private async void ConnectWebSocket()
  65. {
  66. try
  67. {
  68. Uri url = new Uri(this.GetUrl());
  69. ClientWebSocket webSocket = new ClientWebSocket();
  70. CancellationToken ct = new CancellationToken();
  71. await webSocket.ConnectAsync(url, ct);
  72. _isConnected = true;
  73. _ws = webSocket;
  74. }
  75. catch (Exception ex)
  76. {
  77. System.Windows.MessageBox.Show(ex.Message);
  78. }
  79. }
  80. //发送音频至服务器
  81. public async void SendFileToWebSocket()
  82. {
  83. int frameSize = 6400;//每次发送音频字节数6400B
  84. int intervel = 5;//每次发送音频间隔5ms
  85. int pcmCount = 0;//记录音频已发送的大小
  86. int pcmSize = 0;//剩余音频大小
  87. int status = 0;//音频的发送状态;0:第一帧;1:继续帧;2:最后一帧
  88. string filePath = "E:\\SystemData\\desktop\\recorded.wav";//录音文件路径
  89. ConnectWebSocket();
  90. try
  91. {
  92. while (!_isConnected)
  93. {
  94. await Task.Delay(intervel);//异步等待服务器连接
  95. }
  96. byte[] arr = File.ReadAllBytes(filePath);//读取文件所有字节
  97. if (arr == null)
  98. {
  99. return;
  100. }
  101. pcmSize = arr.Length;//获取音频总长
  102. while (true)
  103. {
  104. if (pcmSize <= frameSize)//若剩余音频小于等于1280B,则视为最后帧发送
  105. {
  106. frameSize = pcmSize;
  107. status = 2;
  108. if (frameSize <= 0)
  109. break;
  110. }
  111. byte[] buffer = new byte[frameSize];
  112. Array.Copy(arr, pcmCount, buffer, 0, frameSize);
  113. pcmCount += frameSize;
  114. pcmSize -= frameSize;
  115. switch (status)
  116. {
  117. case 0:
  118. onSend(0, Convert.ToBase64String(buffer));
  119. status = 1;
  120. break;
  121. case 1:
  122. onSend(1, Convert.ToBase64String(buffer));
  123. break;
  124. case 2:
  125. onSend(1, Convert.ToBase64String(buffer));
  126. onSend(2, null);//告诉服务器已经发送结束,本应该需要隔40ms再发送
  127. _isSendDone = true;
  128. break;
  129. }
  130. await Task.Delay(intervel);//延时40ms
  131. }
  132. }
  133. catch (Exception e)
  134. {
  135. System.Windows.MessageBox.Show(e.Message);
  136. }
  137. }
  138. //每次发送数据
  139. //curStatus:用于记录发送过程
  140. //0:首次发送;1:发送中;2:结束发送
  141. private void onSend(int curStatus, string data)
  142. {
  143. if (curStatus == 0)
  144. {
  145. var json = new
  146. {
  147. common = new
  148. {
  149. app_id = $"{_appID}"
  150. },
  151. business = new
  152. {
  153. language = "zh_cn",
  154. domain = "iat",
  155. accent = "mandarin"
  156. },
  157. data = new
  158. {
  159. status = 0,
  160. format = "audio/L16;rate=16000",
  161. encoding = "raw",
  162. audio = $"{data}"
  163. }
  164. };
  165. string jsonStr = JsonConvert.SerializeObject(json, Formatting.Indented);
  166. _ws.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(jsonStr)), WebSocketMessageType.Binary, true, new CancellationToken());
  167. }
  168. else if (curStatus == 1)
  169. {
  170. var json = new
  171. {
  172. data = new
  173. {
  174. status = 1,
  175. format = "audio/L16;rate=16000",
  176. encoding = "raw",
  177. audio = $"{data}"
  178. }
  179. };
  180. string jsonStr = JsonConvert.SerializeObject(json, Formatting.Indented);
  181. _ws.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(jsonStr)), WebSocketMessageType.Binary, true, new CancellationToken());
  182. }
  183. else if (curStatus == 2)
  184. {
  185. var json = new
  186. {
  187. data = new
  188. {
  189. status = 2
  190. }
  191. };
  192. string jsonStr = JsonConvert.SerializeObject(json, Formatting.Indented);
  193. _ws.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(jsonStr)), WebSocketMessageType.Binary, true, new CancellationToken());
  194. }
  195. }
  196. public async void receiveMessage()
  197. {
  198. while (!_isSendDone)
  199. {
  200. await Task.Delay(10);//异步等待服务器连接
  201. }
  202. byte[] buffer = new byte[1024];//可以给大一点,如果识别长时间音频可以会出bug
  203. string str = null;//拼接整句话
  204. while (_ws.State == WebSocketState.Open)
  205. {
  206. WebSocketReceiveResult result = await _ws.ReceiveAsync(new ArraySegment<byte>(buffer),CancellationToken.None);//等待返回结果
  207. if(result.MessageType == WebSocketMessageType.Text)
  208. {
  209. string jsonData = Encoding.UTF8.GetString(buffer,0,result.Count);
  210. var jsonObject = JsonConvert.DeserializeObject<dynamic>(jsonData);//转换为json格式
  211. var data = jsonObject["data"]["result"]["ws"];//提取听写结果
  212. foreach (var item in data)
  213. {
  214. foreach (var item2 in item["cw"])
  215. {
  216. str += item2["w"];
  217. }
  218. }
  219. bool done = jsonObject["data"]["result"]["ls"];//是否完成所有返回结果的接收
  220. if(done)
  221. {
  222. await _ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "closing", CancellationToken.None);//断开与服务器的连接
  223. _isSendDone = false;
  224. _isConnected = false;
  225. break;
  226. }
  227. }
  228. }
  229. HandyControl.Controls.MessageBox.Show(str);
  230. }
  231. }

         这是我用来实现语音识别的测试,空出来的几个参数是需要自己注册科大讯飞账号然后在控制台获取

private string _appID = ;
private string _apiSecret = ;
private string _apiKey = ;

        科大讯飞对于音频有要求,具体可到官方文档查阅,我使用开源库NAudio能够录制到符合要求的音频

GitHub - naudio/NAudio: Audio and MIDI library for .NET

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号