初始化
This commit is contained in:
282
rg-09112127/js/speechSensation.js
Normal file
282
rg-09112127/js/speechSensation.js
Normal file
@@ -0,0 +1,282 @@
|
||||
//
|
||||
let barrierFreeOpenSpeech;
|
||||
|
||||
(function () {
|
||||
var APPID = "43341b7e";
|
||||
var API_SECRET = "MWQzMWEyYTAyYzVlZWRjOTM1NjE0MjI4";
|
||||
var API_KEY = "a46e1fc5d062a14b28cde0ff2c0046e1";
|
||||
let btnStatus = "UNDEFINED"; // "UNDEFINED" "CONNECTING" "OPEN" "CLOSING" "CLOSED"
|
||||
|
||||
const btnControl = document.getElementById("speechStartButton");
|
||||
|
||||
const recorder = new RecorderManager("./dist");
|
||||
recorder.onStart = () => {
|
||||
changeBtnStatus("OPEN");
|
||||
}
|
||||
let iatWS;
|
||||
let resultText = "";
|
||||
let resultTextTemp = "";
|
||||
let countdownInterval;
|
||||
|
||||
/**
|
||||
* 获取websocket url
|
||||
* 该接口需要后端提供,这里为了方便前端处理
|
||||
*/
|
||||
function getWebSocketUrl() {
|
||||
// 请求地址根据语种不同变化
|
||||
var url = "wss://iat-api.xfyun.cn/v2/iat";
|
||||
var host = "iat-api.xfyun.cn";
|
||||
var apiKey = API_KEY;
|
||||
var apiSecret = API_SECRET;
|
||||
var date = new Date().toGMTString();
|
||||
var algorithm = "hmac-sha256";
|
||||
var headers = "host date request-line";
|
||||
var signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v2/iat HTTP/1.1`;
|
||||
var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret);
|
||||
var signature = CryptoJS.enc.Base64.stringify(signatureSha);
|
||||
var authorizationOrigin = `api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`;
|
||||
var authorization = btoa(authorizationOrigin);
|
||||
url = `${url}?authorization=${authorization}&date=${date}&host=${host}`;
|
||||
return url;
|
||||
}
|
||||
|
||||
function toBase64(buffer) {
|
||||
var binary = "";
|
||||
var bytes = new Uint8Array(buffer);
|
||||
var len = bytes.byteLength;
|
||||
for (var i = 0; i < len; i++) {
|
||||
binary += String.fromCharCode(bytes[i]);
|
||||
}
|
||||
return window.btoa(binary);
|
||||
}
|
||||
|
||||
function countdown() {
|
||||
let seconds = 60;
|
||||
btnControl.innerText = `录音中(${seconds}s)`;
|
||||
countdownInterval = setInterval(() => {
|
||||
seconds = seconds - 1;
|
||||
if (seconds <= 0) {
|
||||
clearInterval(countdownInterval);
|
||||
recorder.stop();
|
||||
} else {
|
||||
btnControl.innerText = `录音中(${seconds}s)`;
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function changeBtnStatus(status) {
|
||||
btnStatus = status;
|
||||
if (status === "CONNECTING") {
|
||||
btnControl.innerText = "建立连接中";
|
||||
document.getElementById("speechPartialResult").innerText = "";
|
||||
resultText = "";
|
||||
resultTextTemp = "";
|
||||
} else if (status === "OPEN") {
|
||||
countdown();
|
||||
} else if (status === "CLOSING") {
|
||||
btnControl.innerText = "关闭连接中";
|
||||
} else if (status === "CLOSED") {
|
||||
btnControl.innerText = "开始录音";
|
||||
}
|
||||
}
|
||||
|
||||
function renderResult(resultData) {
|
||||
// 识别结束
|
||||
let jsonData = JSON.parse(resultData);
|
||||
if (jsonData.data && jsonData.data.result) {
|
||||
let data = jsonData.data.result;
|
||||
let str = "";
|
||||
let ws = data.ws;
|
||||
for (let i = 0; i < ws.length; i++) {
|
||||
str = str + ws[i].cw[0].w;
|
||||
}
|
||||
// 开启wpgs会有此字段(前提:在控制台开通动态修正功能)
|
||||
// 取值为 "apd"时表示该片结果是追加到前面的最终结果;取值为"rpl" 时表示替换前面的部分结果,替换范围为rg字段
|
||||
if (data.pgs) {
|
||||
if (data.pgs === "apd") {
|
||||
// 将resultTextTemp同步给resultText
|
||||
resultText = resultTextTemp;
|
||||
}
|
||||
// 将结果存储在resultTextTemp中
|
||||
resultTextTemp = resultText + str;
|
||||
} else {
|
||||
resultText = resultText + str;
|
||||
}
|
||||
document.getElementById("speechPartialResult").innerText =
|
||||
resultTextTemp || resultText || "";
|
||||
|
||||
// 调用方法传输文字
|
||||
// console.log("sendSpeechText", resultTextTemp || resultText || "");
|
||||
checkVoiceCommand(resultTextTemp || resultText || "");
|
||||
// 网页间通信
|
||||
htmlPostMessage(
|
||||
{
|
||||
type: "语音识别",
|
||||
status: "process",
|
||||
data: resultTextTemp || resultText || "",
|
||||
}
|
||||
);
|
||||
}
|
||||
if (jsonData.code === 0 && jsonData.data.status === 2) {
|
||||
iatWS.close();
|
||||
}
|
||||
if (jsonData.code !== 0) {
|
||||
iatWS.close();
|
||||
console.error(jsonData);
|
||||
}
|
||||
}
|
||||
|
||||
function connectWebSocket() {
|
||||
const websocketUrl = getWebSocketUrl();
|
||||
if ("WebSocket" in window) {
|
||||
iatWS = new WebSocket(websocketUrl);
|
||||
} else if ("MozWebSocket" in window) {
|
||||
iatWS = new MozWebSocket(websocketUrl);
|
||||
} else {
|
||||
alert("浏览器不支持WebSocket");
|
||||
return;
|
||||
}
|
||||
changeBtnStatus("CONNECTING");
|
||||
iatWS.onopen = (e) => {
|
||||
// 开始录音
|
||||
recorder.start({
|
||||
sampleRate: 16000,
|
||||
frameSize: 1280,
|
||||
});
|
||||
var params = {
|
||||
common: {
|
||||
app_id: APPID,
|
||||
},
|
||||
business: {
|
||||
language: "zh_cn",
|
||||
domain: "iat",
|
||||
accent: "mandarin",
|
||||
vad_eos: 5000,
|
||||
dwa: "wpgs",
|
||||
},
|
||||
data: {
|
||||
status: 0,
|
||||
format: "audio/L16;rate=16000",
|
||||
encoding: "raw",
|
||||
},
|
||||
};
|
||||
iatWS.send(JSON.stringify(params));
|
||||
|
||||
// 网页间通信
|
||||
htmlPostMessage(
|
||||
{
|
||||
type: "语音识别",
|
||||
status: "start",
|
||||
data: "",
|
||||
}
|
||||
);
|
||||
|
||||
};
|
||||
iatWS.onmessage = (e) => {
|
||||
renderResult(e.data);
|
||||
// console.log(e.data);
|
||||
};
|
||||
iatWS.onerror = (e) => {
|
||||
console.error(e);
|
||||
recorder.stop();
|
||||
changeBtnStatus("CLOSED");
|
||||
};
|
||||
iatWS.onclose = (e) => {
|
||||
recorder.stop();
|
||||
changeBtnStatus("CLOSED");
|
||||
|
||||
// 网页间通信
|
||||
htmlPostMessage(
|
||||
{
|
||||
type: "语音识别",
|
||||
status: "end",
|
||||
data: "",
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
recorder.onFrameRecorded = ({ isLastFrame, frameBuffer }) => {
|
||||
if (iatWS.readyState === iatWS.OPEN) {
|
||||
iatWS.send(
|
||||
JSON.stringify({
|
||||
data: {
|
||||
status: isLastFrame ? 2 : 1,
|
||||
format: "audio/L16;rate=16000",
|
||||
encoding: "raw",
|
||||
audio: toBase64(frameBuffer),
|
||||
},
|
||||
})
|
||||
);
|
||||
if (isLastFrame) {
|
||||
changeBtnStatus("CLOSING");
|
||||
}
|
||||
}
|
||||
};
|
||||
recorder.onStop = () => {
|
||||
clearInterval(countdownInterval);
|
||||
};
|
||||
|
||||
btnControl.onclick = function () {
|
||||
if (btnStatus === "UNDEFINED" || btnStatus === "CLOSED" || btnStatus === "CONNECTING") {
|
||||
connectWebSocket();
|
||||
} else {
|
||||
// 结束录音
|
||||
recorder.stop();
|
||||
}
|
||||
};
|
||||
|
||||
barrierFreeOpenSpeech = function () {
|
||||
// console.log("barrierFreeOpenSpeech", btnStatus);
|
||||
if (btnStatus === "UNDEFINED" || btnStatus === "CLOSED" || btnStatus === "OPEN") {
|
||||
connectWebSocket();
|
||||
} else {
|
||||
// 结束录音
|
||||
recorder.stop();
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
function showSpeech() {
|
||||
let speechDom = document.getElementsByClassName("box-speech")[0];
|
||||
speechDom.style.display = speechDom.style.display == 'none' ? 'block' : 'none';
|
||||
|
||||
voiceBroadcast(`${speechDom.style.display == 'block' ? '开启' : '关闭'}语音识别`);
|
||||
|
||||
// 无障碍模式
|
||||
if (window.location.href.indexOf("courseHomeBarrierFree.html") !== -1) {
|
||||
barrierFreeOpenSpeech();
|
||||
}
|
||||
}
|
||||
|
||||
// 检查语音命令
|
||||
function checkVoiceCommand(text) {
|
||||
if (!text) return false;
|
||||
|
||||
// 语音命令配置
|
||||
const voiceCommands = [
|
||||
{ keywords: ['打开首页', '跳转首页', '回到首页'], action: () => { window.open('./indexHome.html', '_blank'); }, description: '打开首页' },
|
||||
{ keywords: ['打开百度', '跳转百度', '搜索'], action: () => { window.open('https://www.baidu.com', '_blank'); }, description: '打开百度' },
|
||||
];
|
||||
|
||||
// 将文本转换为小写,去除标点符号和空格,以便更好地匹配
|
||||
const cleanText = text.toLowerCase().replace(/[.,,。?!、;:""''()]/g, '').replace(/\s+/g, '');
|
||||
|
||||
console.log("checkVoiceCommand", cleanText);
|
||||
|
||||
// 检查是否匹配任何命令
|
||||
for (const command of voiceCommands) {
|
||||
for (const keyword of command.keywords) {
|
||||
// 同样处理关键词,去除空格
|
||||
const cleanKeyword = keyword.replace(/\s+/g, '');
|
||||
if (cleanText.includes(cleanKeyword)) {
|
||||
// 执行命令动作
|
||||
command.action();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user