index.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. "use strict";
  2. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  3. function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
  4. function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
  5. function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
  6. function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
  7. function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
  8. function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
  9. function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
  10. function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
  11. /**
  12. * Created by iflytek on 2019/11/12.
  13. *
  14. * 实时转写调用demo
  15. * 此demo只是一个简单的调用示例,不适合用到实际生产环境中
  16. *
  17. * 实时语音转写 WebAPI 接口调用示例 接口文档(必看):https://www.xfyun.cn/doc/asr/rtasr/API.html
  18. * 错误码链接:
  19. * https://www.xfyun.cn/doc/asr/rtasr/API.html
  20. * https://www.xfyun.cn/document/error-code (code返回错误码时必看)
  21. *
  22. */
  23. // 音频转码worker
  24. var recorderWorker = new Worker(catchUrl); // 记录处理的缓存音频
  25. var buffer = [];
  26. var AudioContext = window.AudioContext || window.webkitAudioContext;
  27. var notSupportTip = 'localhost';
  28. /*alert("navigator.getUserMedia:"+navigator.getUserMedia);
  29. alert("navigator.webkitGetUserMedia:"+navigator.webkitGetUserMedia);
  30. alert("navigator.mozGetUserMedia:"+navigator.mozGetUserMedia);
  31. alert("navigator.msGetUserMedia:"+navigator.msGetUserMedia);*/
  32. navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
  33. recorderWorker.onmessage = function (e) {
  34. var _buffer;
  35. (_buffer = buffer).push.apply(_buffer, _toConsumableArray(e.data.buffer));
  36. };
  37. var IatRecorder = /*#__PURE__*/function () {
  38. function IatRecorder(config) {
  39. _classCallCheck(this, IatRecorder);
  40. this.config = config;
  41. this.state = 'ing'; //以下信息在控制台-我的应用-实时语音转写 页面获取
  42. this.appId = '5fbb2638';
  43. this.apiKey = 'a9c84fafc02560e48b4f9b1d930afd1c';
  44. }
  45. _createClass(IatRecorder, [{
  46. key: "start",
  47. value: function start() {
  48. var _this = this;
  49. this.stop();
  50. if (navigator.getUserMedia && AudioContext) {
  51. this.state = 'ing';
  52. if (!this.recorder) {
  53. var context = new AudioContext();
  54. this.context = context;
  55. this.recorder = context.createScriptProcessor(0, 1, 1);
  56. var getMediaSuccess = function getMediaSuccess(stream) {
  57. var mediaStream = _this.context.createMediaStreamSource(stream);
  58. _this.mediaStream = mediaStream;
  59. _this.recorder.onaudioprocess = function (e) {
  60. _this.sendData(e.inputBuffer.getChannelData(0));
  61. };
  62. _this.connectWebsocket();
  63. };
  64. var getMediaFail = function getMediaFail(e) {
  65. _this.recorder = null;
  66. _this.mediaStream = null;
  67. _this.context = null;
  68. console.log('请求麦克风失败');
  69. };
  70. if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
  71. navigator.mediaDevices.getUserMedia({
  72. audio: true,
  73. video: false
  74. }).then(function (stream) {
  75. getMediaSuccess(stream);
  76. }).catch(function (e) {
  77. getMediaFail(e);
  78. });
  79. } else {
  80. navigator.getUserMedia({
  81. audio: true,
  82. video: false
  83. }, function (stream) {
  84. getMediaSuccess(stream);
  85. }, function (e) {
  86. getMediaFail(e);
  87. });
  88. }
  89. } else {
  90. this.connectWebsocket();
  91. }
  92. } else {
  93. var isChrome = navigator.userAgent.toLowerCase().match(/chrome/);
  94. }
  95. }
  96. }, {
  97. key: "stop",
  98. value: function stop() {
  99. this.state = 'end';
  100. try {
  101. this.mediaStream.disconnect(this.recorder);
  102. this.recorder.disconnect();
  103. } catch (e) {}
  104. }
  105. }, {
  106. key: "sendData",
  107. value: function sendData(buffer) {
  108. recorderWorker.postMessage({
  109. command: 'transform',
  110. buffer: buffer
  111. });
  112. } // 生成握手参数
  113. }, {
  114. key: "getHandShakeParams",
  115. value: function getHandShakeParams() {
  116. var appId = this.appId;
  117. var secretKey = this.apiKey;
  118. var ts = Math.floor(new Date().getTime() / 1000); //new Date().getTime()/1000+'';
  119. var signa = hex_md5(appId + ts); //hex_md5(encodeURIComponent(appId + ts));//EncryptUtil.HmacSHA1Encrypt(EncryptUtil.MD5(appId + ts), secretKey);
  120. var signatureSha = CryptoJSNew.HmacSHA1(signa, secretKey);
  121. var signature = CryptoJS.enc.Base64.stringify(signatureSha);
  122. signature = encodeURIComponent(signature);
  123. return "?appid=" + appId + "&ts=" + ts + "&signa=" + signature;
  124. }
  125. }, {
  126. key: "connectWebsocket",
  127. value: function connectWebsocket() {
  128. var _this2 = this;
  129. var url = 'wss://rtasr.xfyun.cn/v1/ws';
  130. var urlParam = this.getHandShakeParams();
  131. url = "".concat(url).concat(urlParam);
  132. if ('WebSocket' in window) {
  133. this.ws = new WebSocket(url);
  134. } else if ('MozWebSocket' in window) {
  135. this.ws = new MozWebSocket(url);
  136. } else {
  137. alert(notSupportTip+" 11111111111111111");
  138. return null;
  139. }
  140. this.ws.onopen = function (e) {
  141. _this2.mediaStream.connect(_this2.recorder);
  142. _this2.recorder.connect(_this2.context.destination);
  143. setTimeout(function () {
  144. _this2.wsOpened(e);
  145. }, 500);
  146. _this2.config.onStart && _this2.config.onStart(e);
  147. };
  148. this.ws.onmessage = function (e) {
  149. // this.config.onMessage && this.config.onMessage(e)
  150. _this2.wsOnMessage(e);
  151. };
  152. this.ws.onerror = function (e) {
  153. _this2.stop();
  154. console.log("关闭连接ws.onerror");
  155. _this2.config.onError && _this2.config.onError(e);
  156. };
  157. this.ws.onclose = function (e) {
  158. _this2.stop();
  159. console.log("关闭连接ws.onclose");
  160. $('.start-button').attr('disabled', false);
  161. _this2.config.onClose && _this2.config.onClose(e);
  162. };
  163. }
  164. }, {
  165. key: "wsOpened",
  166. value: function wsOpened() {
  167. var _this3 = this;
  168. if (this.ws.readyState !== 1) {
  169. return;
  170. }
  171. var audioData = buffer.splice(0, 1280);
  172. this.ws.send(new Int8Array(audioData));
  173. this.handlerInterval = setInterval(function () {
  174. // websocket未连接
  175. if (_this3.ws.readyState !== 1) {
  176. clearInterval(_this3.handlerInterval);
  177. return;
  178. }
  179. if (buffer.length === 0) {
  180. if (_this3.state === 'end') {
  181. _this3.ws.send("{\"end\": true}");
  182. console.log("发送结束标识");
  183. clearInterval(_this3.handlerInterval);
  184. }
  185. return false;
  186. }
  187. var audioData = buffer.splice(0, 1280);
  188. if (audioData.length > 0) {
  189. _this3.ws.send(new Int8Array(audioData));
  190. }
  191. }, 40);
  192. }
  193. }, {
  194. key: "wsOnMessage",
  195. value: function wsOnMessage(e) {
  196. var jsonData = JSON.parse(e.data);
  197. if (jsonData.action == "started") {
  198. // 握手成功
  199. console.log("握手成功");
  200. } else if (jsonData.action == "result") {
  201. // 转写结果
  202. if (this.config.onMessage && typeof this.config.onMessage == 'function') {
  203. this.config.onMessage(jsonData.data);
  204. }
  205. } else if (jsonData.action == "error") {
  206. // 连接发生错误
  207. console.log("出错了:", jsonData);
  208. }
  209. }
  210. }, {
  211. key: "ArrayBufferToBase64",
  212. value: function ArrayBufferToBase64(buffer) {
  213. var binary = '';
  214. var bytes = new Uint8Array(buffer);
  215. var len = bytes.byteLength;
  216. for (var i = 0; i < len; i++) {
  217. binary += String.fromCharCode(bytes[i]);
  218. }
  219. return window.btoa(binary);
  220. }
  221. }]);
  222. return IatRecorder;
  223. }();
  224. var IatTaste = /*#__PURE__*/function () {
  225. function IatTaste() {
  226. var _this4 = this;
  227. _classCallCheck(this, IatTaste);
  228. var iatRecorder = new IatRecorder({
  229. onClose: function onClose() {
  230. _this4.stop();
  231. _this4.reset();
  232. },
  233. onError: function onError(data) {
  234. _this4.stop();
  235. _this4.reset();
  236. alert('WebSocket连接失败');
  237. },
  238. onMessage: function onMessage(message) {
  239. _this4.setResult(JSON.parse(message));
  240. },
  241. onStart: function onStart() {
  242. $('hr').addClass('hr');
  243. var dialect = $('.dialect-select').find('option:selected').text();
  244. $('.taste-content').css('display', 'none');
  245. $('.start-taste').addClass('flex-display-1');
  246. $('.dialect-select').css('display', 'none');
  247. $('.start-button').text('暂停/结束转写');
  248. $('.time-box').addClass('flex-display-1');
  249. $('.dialect').text(dialect).css('display', 'inline-block');
  250. _this4.counterDown($('.used-time'));
  251. }
  252. });
  253. this.iatRecorder = iatRecorder;
  254. this.counterDownDOM = $('.used-time');
  255. this.counterDownTime = 0;
  256. this.text = {
  257. start: '继续转写',
  258. stop: '暂停/结束转写'
  259. };
  260. this.resultText = '';
  261. }
  262. _createClass(IatTaste, [{
  263. key: "start",
  264. value: function start() {
  265. this.iatRecorder.start();
  266. }
  267. }, {
  268. key: "stop",
  269. value: function stop() {
  270. $('hr').removeClass('hr');
  271. this.iatRecorder.stop();
  272. }
  273. }, {
  274. key: "reset",
  275. value: function reset() {
  276. this.counterDownTime = 0;
  277. clearTimeout(this.counterDownTimeout);
  278. buffer = [];
  279. $('.time-box').removeClass('flex-display-1').css('display', 'none');
  280. $('.start-button').text(this.text.start);
  281. $('.dialect').css('display', 'none');
  282. $('.dialect-select').css('display', 'inline-block');
  283. $('.taste-button').css('background', '#0b99ff');
  284. }
  285. }, {
  286. key: "init",
  287. value: function init() {
  288. var self = this; //开始
  289. $('#taste_button').click(function () {
  290. /*alert("navigator.getUserMedia:"+navigator.getUserMedia);
  291. alert("AudioContext:"+AudioContext);
  292. alert("recorderWorker:"+recorderWorker);*/
  293. if (navigator.getUserMedia && AudioContext && recorderWorker) {
  294. self.start();
  295. } else {
  296. alert(notSupportTip+" 2222222222222");
  297. }
  298. $("#taste_button").hide();
  299. }); //结束
  300. $('.start-button').click(function () {
  301. if ($(this).text() === self.text.start && !$(this).prop('disabled')) {
  302. $('#result_output').text('');
  303. self.resultText = '';
  304. self.start(); //console.log("按钮非禁用状态,正常启动" + $(this).prop('disabled'))
  305. } else {
  306. //$('.taste-content').css('display', 'none')
  307. $('.start-button').attr('disabled', true);
  308. self.stop(); //reset
  309. this.counterDownTime = 0;
  310. clearTimeout(this.counterDownTimeout);
  311. buffer = [];
  312. $('.time-box').removeClass('flex-display-1').css('display', 'none');
  313. $('.start-button').text('转写停止中...');
  314. $('.dialect').css('display', 'none');
  315. $('.taste-button').css('background', '#8E8E8E');
  316. $('.dialect-select').css('display', 'inline-block'); //console.log("按钮非禁用状态,正常停止" + $(this).prop('disabled'))
  317. }
  318. });
  319. }
  320. }, {
  321. key: "setResult",
  322. value: function setResult(data) {
  323. var rtasrResult = [];
  324. var currentText = $('#result_output').html();
  325. var zxCont=$('#zxCont').val();
  326. rtasrResult[data.seg_id] = data;
  327. rtasrResult.forEach(function (i) {
  328. var str = "实时转写";
  329. var str_cont="";
  330. str += i.cn.st.type == 0 ? "【最终】识别结果:" : "【中间】识别结果:";
  331. i.cn.st.rt.forEach(function (j) {
  332. j.ws.forEach(function (k) {
  333. k.cw.forEach(function (l) {
  334. str += l.w;
  335. /*str_cont+= l.w;*/
  336. });
  337. });
  338. });
  339. if(i.cn.st.type == 0){
  340. i.cn.st.rt.forEach(function (j) {
  341. j.ws.forEach(function (k) {
  342. k.cw.forEach(function (l) {
  343. str_cont+= l.w;
  344. });
  345. });
  346. });
  347. }
  348. if (currentText.length == 0) {
  349. $('#result_output').html(str+"-----------");
  350. } else {
  351. $('#result_output').html(currentText + "<br>" + str+'=========================');
  352. }
  353. if (zxCont.length == 0) {
  354. $('#zxCont').val(str_cont);
  355. } else {
  356. $('#zxCont').val(zxCont+str_cont);
  357. }
  358. var ele = document.getElementById('result_output');
  359. ele.scrollTop = ele.scrollHeight;
  360. });
  361. }
  362. }, {
  363. key: "counterDown",
  364. value: function counterDown() {
  365. var _this5 = this;
  366. /*//计时5分钟
  367. if (this.counterDownTime === 300) {
  368. this.counterDownDOM.text('05: 00')
  369. this.stop()
  370. } else if (this.counterDownTime > 300) {
  371. this.reset()
  372. return false
  373. } else */
  374. if (this.counterDownTime >= 0 && this.counterDownTime < 10) {
  375. this.counterDownDOM.text('00: 0' + this.counterDownTime);
  376. } else if (this.counterDownTime >= 10 && this.counterDownTime < 60) {
  377. this.counterDownDOM.text('00: ' + this.counterDownTime);
  378. } else if (this.counterDownTime % 60 >= 0 && this.counterDownTime % 60 < 10) {
  379. this.counterDownDOM.text('0' + parseInt(this.counterDownTime / 60) + ': 0' + this.counterDownTime % 60);
  380. } else {
  381. this.counterDownDOM.text('0' + parseInt(this.counterDownTime / 60) + ': ' + this.counterDownTime % 60);
  382. }
  383. this.counterDownTime++;
  384. this.counterDownTimeout = setTimeout(function () {
  385. _this5.counterDown();
  386. }, 1000);
  387. }
  388. }]);
  389. return IatTaste;
  390. }();
  391. var iatTaste = new IatTaste();
  392. iatTaste.init();