|
@@ -0,0 +1,142 @@
|
|
|
|
+import Speech from 'speak-tts';
|
|
|
|
+import http from '@/api';
|
|
|
|
+let speech: any = null;
|
|
|
|
+let browserSupport: boolean = false;
|
|
|
|
+let speechText: string = '';
|
|
|
|
+
|
|
|
|
+//初始化语音
|
|
|
|
+export const initSpeech = () => {
|
|
|
|
+ speech = new Speech();
|
|
|
|
+ // 检测浏览器是否支持
|
|
|
|
+ if (speech.hasBrowserSupport()) {
|
|
|
|
+ browserSupport = true;
|
|
|
|
+ speech
|
|
|
|
+ .init({
|
|
|
|
+ volume: 1, // 音量
|
|
|
|
+ lang: 'zh-CN', // 语言
|
|
|
|
+ rate: 1.5, // 语速
|
|
|
|
+ pitch: 1.0, // 音调
|
|
|
|
+ splitSentences: true, // 在句子结束时暂停
|
|
|
|
+ listeners: {
|
|
|
|
+ // 事件
|
|
|
|
+ onvoiceschanged: (voices: any) => {
|
|
|
|
+ // console.log('事件声音已更改', voices);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ .then(() => {
|
|
|
|
+ console.log('语音播报初始化完成');
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ browserSupport = false;
|
|
|
|
+ let baiduTok = localStorage.getItem('tok');
|
|
|
|
+ if (!baiduTok) {
|
|
|
|
+ http?.common.baiduToken({}).then((res: any) => {
|
|
|
|
+ let tok = res.token;
|
|
|
|
+ localStorage.setItem('tok', tok);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//播放语音
|
|
|
|
+export const speckText = (text: any) => {
|
|
|
|
+ //console.log('text', text);
|
|
|
|
+ console.log('speechText', speechText);
|
|
|
|
+ if (speechText == text) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ speechText = text;
|
|
|
|
+ let obj: any = {
|
|
|
|
+ // '请看摄像头进行人脸识别': 'PleaseIdentify.mp3',
|
|
|
|
+ // '腿部违规': 'LegViolation.mp3',
|
|
|
|
+ // '手部违规': 'HandViolation.mp3',
|
|
|
|
+ // '背部违规': 'BackViolation.mp3',
|
|
|
|
+ // '臀部违规': 'HipViolation.mp3',
|
|
|
|
+ // '踩线违规': 'LineViolation.mp3',
|
|
|
|
+ // '肘部违规': 'Elbowiolation.mp3',
|
|
|
|
+ // '下颌违规': 'HeightViolation.mp3',
|
|
|
|
+ // '单脚跳违规': 'SingleLegJumpViolation.mp3',
|
|
|
|
+ // '跳出测试区域违规': 'JumpAreaViolation.mp3',
|
|
|
|
+ // '您已踩线违规': 'LineViolationed.mp3',
|
|
|
|
+ // '测试结束,请下一位准备': 'TestEnd.mp3',
|
|
|
|
+ // '开始': 'Start.mp3',
|
|
|
|
+ // '测试完成': 'End.mp3',
|
|
|
|
+ // '请开始测试': 'PleaseStartTest.mp3',
|
|
|
|
+ // '请准备': 'PleaseReady.mp3',
|
|
|
|
+ // '该摄像头已启用': 'CameraOpen.mp3',
|
|
|
|
+ // '该考点已接受请求,请5秒后刷新考点状态后重试.': 'Accepted.mp3',
|
|
|
|
+ // '工作站登录失败': 'WorkFailLogin.mp3',
|
|
|
|
+ // '摄像头打开失败': 'openFail.mp3',
|
|
|
|
+ // '网络错误,请检查网络': 'NetworkError.mp3',
|
|
|
|
+ // '非法操作': 'IllegalOperation.mp3',
|
|
|
|
+ // '工作站已断开!': 'WorkDisconnect.mp3',
|
|
|
|
+ // '无可用工作站': 'NoWork.mp3',
|
|
|
|
+ // '考试项目不存在': 'NoExam.mp3',
|
|
|
|
+ // '该场地已被其他页面抢占': 'OtherPages.mp3',
|
|
|
|
+ // '重连失败,对应工作站已被占用': 'ReconnectionFailed.mp3',
|
|
|
|
+ // '自动人脸抓取返回result_id不正确': 'ResultIdFalse.mp3',
|
|
|
|
+ // '系统错误!': 'SystemError.mp3',
|
|
|
|
+ // '工作站已关闭,请重新上课!': 'WorkDown.mp3',
|
|
|
|
+ // '初始化成功': 'InitializationSuccessful.mp3',
|
|
|
|
+ // '有非测试人员进入测试区': 'InterferencePersonnel.mp3',
|
|
|
|
+ // '布点文件视频尺寸和当前摄像头尺寸不一致': 'MarkInconsistency.mp3',
|
|
|
|
+ // '各就位,预备': 'Ready.mp3',
|
|
|
|
+ // '还有30秒,加油!': 'countdown30s.mp3',
|
|
|
|
+ // '还有10秒,坚持住!': 'countdown10s.mp3',
|
|
|
|
+ // '5': '5.mp3',
|
|
|
|
+ // '4': '4.mp3',
|
|
|
|
+ // '3': '3.mp3',
|
|
|
|
+ // '2': '2.mp3',
|
|
|
|
+ // '1': '1.mp3',
|
|
|
|
+ // '预备和哨声': 'PrepareWhistle.mp3',
|
|
|
|
+ 跑: 'run.mp3',
|
|
|
|
+ 哨声: 'shaosheng.mp3',
|
|
|
|
+ 哨声2: 'shaosheng2.mp3'
|
|
|
|
+ };
|
|
|
|
+ console.log('播报', text);
|
|
|
|
+ if (obj[text]) {
|
|
|
|
+ //用本地文件
|
|
|
|
+ let url = `./static/audio/${obj[text]}`;
|
|
|
|
+ new Audio(url).play();
|
|
|
|
+ speechText = '';
|
|
|
|
+ } else {
|
|
|
|
+ if (browserSupport == true) {
|
|
|
|
+ //用TTS
|
|
|
|
+ speech.speak({ text: text.toString() }).then(() => {
|
|
|
|
+ speech.cancel(); //播放结束后调用
|
|
|
|
+ speechText = '';
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ //用百度语音
|
|
|
|
+ let tok = localStorage.getItem('tok') || '';
|
|
|
|
+ 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`;
|
|
|
|
+ new Audio(url).play();
|
|
|
|
+ speechText = '';
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//取消播放
|
|
|
|
+export const speckCancel = () => {
|
|
|
|
+ if (speech && browserSupport == true) {
|
|
|
|
+ speech.cancel();
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+//小数播报格式
|
|
|
|
+export const chineseNumber = (num: any) => {
|
|
|
|
+ const chineseNumbers = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
|
|
|
|
+ let parts = String(num).split('.');
|
|
|
|
+ let integerPart = parts[0];
|
|
|
|
+ let decimalPart = parts[1];
|
|
|
|
+ let chineseInteger = integerPart;
|
|
|
|
+ let chineseDecimal = decimalPart
|
|
|
|
+ ? '点' +
|
|
|
|
+ decimalPart
|
|
|
|
+ .split('')
|
|
|
|
+ .map((digit) => chineseNumbers[parseInt(digit)])
|
|
|
|
+ .join('')
|
|
|
|
+ : '';
|
|
|
|
+ return chineseInteger + chineseDecimal;
|
|
|
|
+};
|