<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>测试实时语音转写</title>
</head>
<body>
<div id="app">
{{message}}
<div>浏览器录音听写:<button @click.stop="startLuyin">{{btnTxt}}</button></div>
<div>输出结果:{{resultText}}</div>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="./js/hmac-sha256.js"></script>
<script src="./js/HmacSHA1.js"></script>
<script src="./js/md5.js"></script>
<script src="./js/enc-base64-min.js"></script>
<script src="./js/index.umd.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!',
btnStatus:"UNDEFINED", // "UNDEFINED" "CONNECTING" "OPEN" "CLOSING" "CLOSED"
recorder:null,
resultText:'',
resultTextTemp:'',
countdownInterval:null,
iatWS:null,
btnTxt:'开始录音',
APPID:'7f54738e',
API_KEY:'7bba811baafd0ef0ab8d076a9598a76d'
},
mounted(){
this.recorder = new RecorderManager("./js");
this.recorder.onStart = () => {
this.changeBtnStatus("OPEN");
}
this.recorder.onFrameRecorded = ({ isLastFrame, frameBuffer }) => {
if (this.iatWS.readyState === this.iatWS.OPEN) {
this.iatWS.send(new Int8Array(frameBuffer));
if (isLastFrame) {
this.iatWS.send('{"end": true}');
this.changeBtnStatus("CLOSING");
}
}
}
this.recorder.onStop = () => {
clearInterval(this.countdownInterval);
};
},
methods:{
startLuyin(){
if (this.btnStatus === "UNDEFINED" || this.btnStatus === "CLOSED") {
this.connectWebSocket();
} else if (this.btnStatus === "CONNECTING" || this.btnStatus === "OPEN") {
// 结束录音
this.recorder.stop();
}
},
changeBtnStatus(status) { //改变状态
this.btnStatus = status;
if (status === "CONNECTING") {
this.btnTxt = "建立连接中";
this.resultText = "";
this.resultTextTemp = "";
} else if (status === "OPEN") {
this.btnTxt = "录音中";
} else if (status === "CLOSING") {
this.btnTxt = "关闭连接中";
} else if (status === "CLOSED") {
this.btnTxt = "开始录音";
}
},
getWebSocketUrl(){
var url = "wss://rtasr.xfyun.cn/v1/ws";
var appId = this.APPID;
var secretKey = this.API_KEY;
var ts = Math.floor(new Date().getTime() / 1000);
var signa = hex_md5(appId + ts);
var signatureSha = CryptoJSNew.HmacSHA1(signa, secretKey);
var signature = CryptoJS.enc.Base64.stringify(signatureSha);
signature = encodeURIComponent(signature);
return `${url}?appid=${appId}&ts=${ts}&signa=${signature}`;
},
renderResult(resultData){
let jsonData = JSON.parse(resultData);
if (jsonData.action == "started") {
console.log("握手成功");
} else if (jsonData.action == "result") {
const data = JSON.parse(jsonData.data)
// 转写结果
let resultTextTemp = ""
data.cn.st.rt.forEach((j) => {
j.ws.forEach((k) => {
k.cw.forEach((l) => {
resultTextTemp += l.w;
});
});
});
if (data.cn.st.type == 0) {
// 【最终】识别结果:
this.resultText += resultTextTemp;
resultTextTemp = ""
}
this.resultText = resultText + resultTextTemp
} else if (jsonData.action == "error") {
// 连接发生错误
console.log("出错了:", jsonData);
}
},
connectWebSocket(){
const websocketUrl = this.getWebSocketUrl();
if ("WebSocket" in window) {
this.iatWS = new WebSocket(websocketUrl);
} else if ("MozWebSocket" in window) {
this.iatWS = new MozWebSocket(websocketUrl);
} else {
alert("浏览器不支持WebSocket");
return;
}
this.changeBtnStatus("CONNECTING");
this.iatWS.onopen = (e) => {
// 开始录音
this.recorder.start({
sampleRate: 16000,
frameSize: 1280,
});
};
this.iatWS.onmessage = (e) => {
this.renderResult(e.data);
};
this.iatWS.onerror = (e) => {
console.error(e);
this.recorder.stop();
this.changeBtnStatus("CLOSED");
};
this.iatWS.onclose = (e) => {
this.recorder.stop();
this.changeBtnStatus("CLOSED");
};
},
}
})
</script>
</html>