speech.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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: '5', value: '5.mp3' },
  94. { lable: '4', value: '4.mp3' },
  95. { lable: '3', value: '3.mp3' },
  96. { lable: '2', value: '2.mp3' },
  97. { lable: '1', value: '1.mp3' },
  98. { lable: '各就位,预备!', value: 'runNew.mp3' },
  99. { lable: '跑', value: 'run.mp3' },
  100. { lable: '哨声', value: 'shaosheng.mp3' },
  101. { lable: '哨声2', value: 'shaosheng2.mp3' }
  102. ];
  103. speechText = '';
  104. console.log('播报', text);
  105. let obj = list.find((item: any) => {
  106. return item.lable == text;
  107. });
  108. if (obj != undefined) {
  109. //用本地文件
  110. let url = `./static/audio/${obj.value}`;
  111. myAudio = new Audio(url);
  112. myAudio.play();
  113. } else {
  114. if (browserSupport == true) {
  115. //用TTS
  116. speech.speak({ text: text.toString() }).then(() => {
  117. speech.cancel(); //播放结束后调用
  118. });
  119. } else {
  120. //用百度语音
  121. let tok = localStorage.getItem('tok') || '';
  122. 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`;
  123. myAudio = new Audio(url);
  124. myAudio.play();
  125. }
  126. }
  127. };
  128. //播放音乐
  129. export const playMusic = (url: any) => {
  130. let state = true;
  131. let voiceData: any = localStorage.getItem('voice');
  132. if (voiceData != undefined && voiceData == 'false') {
  133. state = false;
  134. }
  135. myMusic = new Audio(url);
  136. myMusic.muted = state ? false : true;
  137. myMusic.play();
  138. };
  139. //取消播放
  140. export const speckCancel = () => {
  141. if (speech && browserSupport == true) {
  142. speech?.cancel();
  143. } else {
  144. myAudio?.pause();
  145. }
  146. myMusic?.pause();
  147. };
  148. //控制音乐
  149. export const controlMusic = () => {
  150. let state = true;
  151. let voiceData: any = localStorage.getItem('voice');
  152. if (voiceData != undefined && voiceData == 'false') {
  153. state = false;
  154. }
  155. myMusic.muted = state ? false : true;
  156. };
  157. //小数播报格式
  158. export const chineseNumber = (num: any) => {
  159. const chineseNumbers = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
  160. let parts = String(num).split('.');
  161. let integerPart = parts[0];
  162. let decimalPart = parts[1];
  163. let chineseInteger = integerPart;
  164. let chineseDecimal = decimalPart
  165. ? '点' +
  166. decimalPart
  167. .split('')
  168. .map((digit) => chineseNumbers[parseInt(digit)])
  169. .join('')
  170. : '';
  171. return chineseInteger + chineseDecimal;
  172. };