需要https的才可以使用功能,不然报错‘不支持录音’
科大讯飞文档
下载的demo内js存放目录
![]() | ![]() |
1,CryptoJS我是安装的依赖形式
<template>
<div style="width: 100%;height: 100%;">
<div class="speechBut pr" :class="disDown ? 'ac' : ''" @click="startRecording">
<div
style="position: absolute;bottom: 5px;left: 50%;transform: translateX(-50%);text-align: center;">
<p style="margin: 0;">{{ btnText }}</p>
<!-- <div>{{ resultText }}</div> -->
</div>
</div>
</div>
</template>
<script>
import CryptoJS from 'crypto-js';
// import '../../../../public/xfyun/utilJS/crypto-js.js'; //鉴权的引用地址
// import '../../../../public/xfyun/utilJS/index.umd.js'; // 调用Web Speech API 的依赖,应该是官方的写的工具类
const RecorderManager = require('../../../../public/xfyun/dist/index.umd.js');
export default {
name: '',
components: {},
props: {
},
data() {
return {
disDown: false,
btnText: "开始录音",
btnStatus: "UNDEFINED", // "UNDEFINED" "CONNECTING" "OPEN" "CLOSING" "CLOSED"
recorder: new RecorderManager('../xfyun/dist'),// 这个指向不存在的文件夹也没事
APPID: "", // TODO 你的讯飞模型APPID
API_SECRET: "", // TODO 你的讯飞模型API_SECRET
API_KEY: "", // TODO 你的讯飞模型API_KEY
iatWS: null, //监听录音的变量
resultText: '', // 识别结果
resultTextTemp: '',
countdownInterval: null
};
},
computed: {
},
mounted() {
// 定义监听开始的函数
console.log('recorder:', this.recorder); // 打印 recorder 确认是否初始化成功
this.recorder.onStart = () => {
this.changeStatus("OPEN");
};
this.recorder.onFrameRecorded = this.onFrameRecorded;
this.recorder.onStop = this.onStop;
},
methods: {
// 按钮点击的启动 | 结束函数
startRecording() {
// console.log('当前状态',this.btnStatus)
if (this.btnStatus === "UNDEFINED" || this.btnStatus === "CLOSED") {
this.disDown = true;
this.connectWebSocket();
} else if (this.btnStatus === "CONNECTING" || this.btnStatus === "OPEN") {
// 结束录音
this.disDown = false;
this.recorder.stop();
}
},
// 生成 WebSocket URL 生成规则由平台决定
getWebSocketUrl() {
// 请求地址根据语种不同变化
var url = "wss://iat-api.xfyun.cn/v2/iat";
var host = "iat-api.xfyun.cn";
var apiKey = this.API_KEY;
var apiSecret = this.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;
},
// 加密工具函数
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);
},
// 计数函数
countdownFun() {
let seconds = 60;
this.btnText = `录音中(${seconds}s)`;
this.countdownInterval = setInterval(() => {
seconds = seconds - 1;
if (seconds <= 0) {
clearInterval(this.countdownInterval);
this.recorder.stop();
} else {
this.btnText = `录音中(${seconds}s)`;
}
}, 1000);
},
// 录音状态变化函数
changeStatus(status) {
this.btnStatus = status;
if (status === "CONNECTING") {
this.btnText = "建立连接中";
this.resultText = '';
this.resultTextTemp = "";
} else if (status === "OPEN") {
this.countdownFun();
} else if (status === "CLOSING") {
this.btnText = "关闭连接中";
} else if (status === "CLOSED") {
this.btnText = "开始录音";
}
},
// 结果解析函数
renderResult(resultData) {
let that = this
// 识别结束
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
that.resultText = that.resultTextTemp;
}
// 将结果存储在resultTextTemp中
that.resultTextTemp = that.resultText + str;
} else {
that.resultText = that.resultText + str;
}
// that.$emit('toTxt',that.resultText)
}
if (jsonData.code === 0 && jsonData.data.status === 2) {
this.iatWS.close();
}
if (jsonData.code !== 0) {
this.iatWS.close();
console.error(jsonData);
}
},
// 连接 WebSocket
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.changeStatus("CONNECTING");
this.iatWS.onopen = (e) => {
// 开始录音
this.recorder.start({
sampleRate: 16000,
frameSize: 1280,
});
var params = {
common: {
app_id: this.APPID,
},
business: {
language: "zh_cn",
domain: "iat",
accent: "mandarin",
vad_eos: 5000,
dwa: "wpgs",
},
data: {
status: 0,
format: "audio/L16;rate=16000",
encoding: "raw",
},
};
this.iatWS.send(JSON.stringify(params));
};
this.iatWS.onmessage = (e) => {
this.renderResult(e.data);
};
this.iatWS.onerror = (e) => {
console.error(e);
this.recorder.stop();
this.changeStatus("CLOSED");
};
this.iatWS.onclose = (e) => {
this.recorder.stop();
this.changeStatus("CLOSED");
};
},
// 处理回调的结果
onFrameRecorded({ isLastFrame, frameBuffer }) {
if (this.iatWS.readyState === this.iatWS.OPEN) {
this.iatWS.send(
JSON.stringify({
data: {
status: isLastFrame ? 2 : 1,
format: "audio/L16;rate=16000",
encoding: "raw",
audio: this.toBase64(frameBuffer),
},
})
);
if (isLastFrame) {
this.changeStatus("CLOSING");
}
}
},
// 停止录音的处理
onStop() {
clearInterval(this.countdownInterval);
},
}
};
</script>
<style scoped>
.speechBut {
cursor: pointer;
width: 100%;
height: 100%;
}
.speechBut.ac {}
</style>