speech.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. import Speech from 'speak-tts';
  2. import http from '@/api';
  3. let speech: any = null;
  4. let myAudio: any = null;
  5. let myMusic: any = null;
  6. let browserSupport: boolean = false;
  7. let speechText: string = '';
  8. //初始化语音
  9. export const initSpeech = () => {
  10. speech = new Speech();
  11. // 检测浏览器是否支持
  12. if (speech.hasBrowserSupport()) {
  13. browserSupport = true;
  14. speech
  15. .init({
  16. volume: 1, // 音量
  17. lang: 'zh-CN', // 语言
  18. rate: 1.5, // 语速
  19. pitch: 1.0, // 音调
  20. splitSentences: true, // 在句子结束时暂停
  21. listeners: {
  22. // 事件
  23. onvoiceschanged: (voices: any) => {
  24. // console.log('事件声音已更改', voices);
  25. }
  26. }
  27. })
  28. .then(() => {
  29. console.log('语音播报初始化完成');
  30. });
  31. } else {
  32. browserSupport = false;
  33. let baiduTok = localStorage.getItem('tok');
  34. if (!baiduTok) {
  35. http?.common.baiduToken({}).then((res: any) => {
  36. let tok = res.token;
  37. localStorage.setItem('tok', tok);
  38. });
  39. }
  40. }
  41. };
  42. //播放语音
  43. export const speckText = (text: any) => {
  44. //console.log('text', text);
  45. //静音
  46. let voiceData: any = localStorage.getItem('voice');
  47. if (voiceData != undefined && voiceData == 'false') {
  48. return false;
  49. }
  50. console.log('speechText', speechText);
  51. if (speechText == text) {
  52. return false;
  53. }
  54. speechText = text;
  55. let list: any = [
  56. // '请看摄像头进行人脸识别': 'PleaseIdentify.mp3',
  57. // '腿部违规': 'LegViolation.mp3',
  58. // '手部违规': 'HandViolation.mp3',
  59. // '背部违规': 'BackViolation.mp3',
  60. // '臀部违规': 'HipViolation.mp3',
  61. // '踩线违规': 'LineViolation.mp3',
  62. // '肘部违规': 'Elbowiolation.mp3',
  63. // '下颌违规': 'HeightViolation.mp3',
  64. // '单脚跳违规': 'SingleLegJumpViolation.mp3',
  65. // '跳出测试区域违规': 'JumpAreaViolation.mp3',
  66. // '您已踩线违规': 'LineViolationed.mp3',
  67. // '测试结束,请下一位准备': 'TestEnd.mp3',
  68. // '开始': 'Start.mp3',
  69. // '测试完成': 'End.mp3',
  70. // '请开始测试': 'PleaseStartTest.mp3',
  71. // '请准备': 'PleaseReady.mp3',
  72. // '该摄像头已启用': 'CameraOpen.mp3',
  73. // '该考点已接受请求,请5秒后刷新考点状态后重试.': 'Accepted.mp3',
  74. // '工作站登录失败': 'WorkFailLogin.mp3',
  75. // '摄像头打开失败': 'openFail.mp3',
  76. // '网络错误,请检查网络': 'NetworkError.mp3',
  77. // '非法操作': 'IllegalOperation.mp3',
  78. // '工作站已断开!': 'WorkDisconnect.mp3',
  79. // '无可用工作站': 'NoWork.mp3',
  80. // '考试项目不存在': 'NoExam.mp3',
  81. // '该场地已被其他页面抢占': 'OtherPages.mp3',
  82. // '重连失败,对应工作站已被占用': 'ReconnectionFailed.mp3',
  83. // '自动人脸抓取返回result_id不正确': 'ResultIdFalse.mp3',
  84. // '系统错误!': 'SystemError.mp3',
  85. // '工作站已关闭,请重新上课!': 'WorkDown.mp3',
  86. // '初始化成功': 'InitializationSuccessful.mp3',
  87. // '有非测试人员进入测试区': 'InterferencePersonnel.mp3',
  88. // '布点文件视频尺寸和当前摄像头尺寸不一致': 'MarkInconsistency.mp3',
  89. // '各就位,预备': 'Ready.mp3',
  90. // '还有30秒,加油!': 'countdown30s.mp3',
  91. // '还有10秒,坚持住!': 'countdown10s.mp3',
  92. // '预备': 'Ready.mp3',
  93. // { lable: '预备2', value: 'Ready2.mp3' },
  94. { lable: '请看摄像头进行人脸识别', value: 'PleaseIdentify3.mp3' },
  95. { lable: '请举右手看摄像头进行人脸识别', value: 'PleaseIdentify4.mp3' },
  96. { lable: '5', value: '5.mp3' },
  97. { lable: '4', value: '4.mp3' },
  98. { lable: '3', value: '3.mp3' },
  99. { lable: '2', value: '2.mp3' },
  100. { lable: '1', value: '1.mp3' },
  101. { lable: '各就位,预备!', value: 'runNew.mp3' },//短跑口令
  102. { lable: '各就位!', value: 'longRun.mp3' },//长跑口令
  103. { lable: '跑', value: 'run.mp3' },
  104. { lable: '哨声', value: 'shaosheng.mp3' },
  105. { lable: '哨声2', value: 'shaosheng2.mp3' },
  106. { lable: '预备3', value: 'Ready3.mp3' },
  107. { lable: '请开始测试', value: 'startTesting.mp3' },
  108. { lable: '测试结束', value: 'testCompleted.mp3' },
  109. ];
  110. speechText = '';
  111. let obj = list.find((item: any) => {
  112. return item.lable == text;
  113. });
  114. if (obj != undefined) {
  115. console.log('音频播报', text);
  116. //用本地文件
  117. let url = `./static/audio/${obj.value}`;
  118. myAudio = new Audio(url);
  119. myAudio.play();
  120. } else {
  121. let state = localStorage.getItem('ttsState');
  122. if (browserSupport == true && state!='1') {
  123. console.log('TTS播报', text);
  124. //用TTS
  125. speech.speak({ text: text.toString() }).then(() => {
  126. speech.cancel(); //播放结束后调用
  127. });
  128. } else {
  129. console.log('百度播报', text);
  130. //用百度语音
  131. let tok = localStorage.getItem('tok') || '';
  132. let url = `https://tsn.baidu.com/text2audio?tex=${encodeURI(text)}&tok=${tok}&cuid=baike&lan=ZH&ctp=1&vol=15&rate=32&per=0&spd=7&pit=4`;
  133. myAudio = new Audio(url);
  134. myAudio.play();
  135. }
  136. }
  137. };
  138. //播放音乐
  139. export const playMusic = (url: any) => {
  140. let state = true;
  141. let voiceData: any = localStorage.getItem('voice');
  142. if (voiceData != undefined && voiceData == 'false') {
  143. state = false;
  144. }
  145. myMusic = new Audio(url);
  146. myMusic.muted = state ? false : true;
  147. myMusic.play();
  148. };
  149. //取消播放
  150. export const speckCancel = () => {
  151. speechText = '';
  152. if (speech && browserSupport == true) {
  153. speech?.cancel();
  154. } else {
  155. myAudio?.pause();
  156. }
  157. myMusic?.pause();
  158. };
  159. //控制音乐
  160. export const controlMusic = () => {
  161. let state = true;
  162. let voiceData: any = localStorage.getItem('voice');
  163. if (voiceData != undefined && voiceData == 'false') {
  164. state = false;
  165. }
  166. if(myMusic){
  167. myMusic.muted = state ? false : true;
  168. }
  169. };
  170. //小数播报格式
  171. export const chineseNumber = (num: any) => {
  172. const chineseNumbers = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
  173. let parts = String(num).split('.');
  174. let integerPart = parts[0];
  175. let decimalPart = parts[1];
  176. let chineseInteger = integerPart;
  177. let chineseDecimal = decimalPart
  178. ? '点' +
  179. decimalPart
  180. .split('')
  181. .map((digit) => chineseNumbers[parseInt(digit)])
  182. .join('')
  183. : '';
  184. return chineseInteger + chineseDecimal;
  185. };