This commit is contained in:
parent
ee064c2c55
commit
2fd4cd8798
239
index.js
239
index.js
|
@ -1,6 +1,5 @@
|
|||
// (function () {
|
||||
|
||||
|
||||
// // btnControl.onclick = function () {
|
||||
// // if (btnStatus === "UNDEFINED" || btnStatus === "CLOSED") {
|
||||
// // connectWebSocket();
|
||||
|
@ -11,19 +10,20 @@
|
|||
// // };
|
||||
// })();
|
||||
|
||||
let btnStatus = "UNDEFINED"; // "UNDEFINED" "CONNECTING" "OPEN" "CLOSING" "CLOSED"
|
||||
let btnStatus = 'UNDEFINED' // "UNDEFINED" "CONNECTING" "OPEN" "CLOSING" "CLOSED"
|
||||
|
||||
// const btnControl = document.getElementById("btn_control");
|
||||
const btnControl = {};
|
||||
const btnControl = {}
|
||||
|
||||
const recorder = new RecorderManager("./dists");
|
||||
const recorder = new RecorderManager('./dists')
|
||||
recorder.onStart = () => {
|
||||
changeBtnStatus("OPEN");
|
||||
changeBtnStatus('OPEN')
|
||||
}
|
||||
let iatWS;
|
||||
let resultText = "";
|
||||
let resultTextTemp = "";
|
||||
let countdownInterval;
|
||||
let iatWS
|
||||
let resultText = ''
|
||||
let resultTextTemp = ''
|
||||
let countdownInterval
|
||||
window.winText = ''
|
||||
|
||||
/**
|
||||
* 获取websocket url
|
||||
|
@ -31,145 +31,154 @@ let btnStatus = "UNDEFINED"; // "UNDEFINED" "CONNECTING" "OPEN" "CLOSING" "CLOSE
|
|||
*/
|
||||
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;
|
||||
let url = 'wss://iat-api.xfyun.cn/v2/iat'
|
||||
const host = 'iat-api.xfyun.cn'
|
||||
const apiKey = API_KEY
|
||||
const apiSecret = API_SECRET
|
||||
const date = new Date().toGMTString()
|
||||
const algorithm = 'hmac-sha256'
|
||||
const headers = 'host date request-line'
|
||||
const signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v2/iat HTTP/1.1`
|
||||
const signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret)
|
||||
const signature = CryptoJS.enc.Base64.stringify(signatureSha)
|
||||
const authorizationOrigin = `api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`
|
||||
const 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);
|
||||
let binary = ''
|
||||
const bytes = new Uint8Array(buffer)
|
||||
const len = bytes.byteLength
|
||||
for (let i = 0; i < len; i++)
|
||||
binary += String.fromCharCode(bytes[i])
|
||||
|
||||
return window.btoa(binary)
|
||||
}
|
||||
|
||||
function countdown() {
|
||||
let seconds = 60;
|
||||
btnControl.innerText = `录音中(${seconds}s)`;
|
||||
let seconds = 60
|
||||
btnControl.innerText = `录音中(${seconds}s)`
|
||||
countdownInterval = setInterval(() => {
|
||||
seconds = seconds - 1;
|
||||
seconds = seconds - 1
|
||||
if (seconds <= 0) {
|
||||
clearInterval(countdownInterval);
|
||||
recorder.stop();
|
||||
} else {
|
||||
btnControl.innerText = `录音中(${seconds}s)`;
|
||||
clearInterval(countdownInterval)
|
||||
recorder.stop()
|
||||
}
|
||||
}, 1000);
|
||||
else {
|
||||
btnControl.innerText = `录音中(${seconds}s)`
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
function changeBtnStatus(status) {
|
||||
btnStatus = status;
|
||||
if (status === "CONNECTING") {
|
||||
btnControl.innerText = "建立连接中";
|
||||
document.getElementById("result").innerText = "";
|
||||
resultText = "";
|
||||
resultTextTemp = "";
|
||||
} else if (status === "OPEN") {
|
||||
countdown();
|
||||
} else if (status === "CLOSING") {
|
||||
btnControl.innerText = "关闭连接中";
|
||||
} else if (status === "CLOSED") {
|
||||
btnControl.innerText = "开始录音";
|
||||
btnStatus = status
|
||||
if (status === 'CONNECTING') {
|
||||
btnControl.innerText = '建立连接中'
|
||||
document.getElementById('result').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);
|
||||
const 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;
|
||||
}
|
||||
const data = jsonData.data.result
|
||||
let str = ''
|
||||
const 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") {
|
||||
if (data.pgs === 'apd') {
|
||||
// 将resultTextTemp同步给resultText
|
||||
resultText = resultTextTemp;
|
||||
resultText = resultTextTemp
|
||||
}
|
||||
// 将结果存储在resultTextTemp中
|
||||
resultTextTemp = resultText + str;
|
||||
} else {
|
||||
resultText = resultText + str;
|
||||
resultTextTemp = resultText + str
|
||||
}
|
||||
document.getElementById("result").innerText =
|
||||
resultTextTemp || resultText || "";
|
||||
console.log(resultTextTemp);
|
||||
else {
|
||||
resultText = resultText + str
|
||||
}
|
||||
if (jsonData.code === 0 && jsonData.data.status === 2) {
|
||||
iatWS.close();
|
||||
document.getElementById('result').innerText
|
||||
= resultTextTemp || resultText || ''
|
||||
console.log('录音结果:', resultTextTemp || resultText || '')
|
||||
window.winText = resultTextTemp || resultText || ''
|
||||
window.dispatchEvent(new Event('test'))
|
||||
}
|
||||
if (jsonData.code === 0 && jsonData.data.status === 2)
|
||||
iatWS.close()
|
||||
|
||||
if (jsonData.code !== 0) {
|
||||
iatWS.close();
|
||||
console.error(jsonData);
|
||||
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;
|
||||
const websocketUrl = getWebSocketUrl()
|
||||
if ('WebSocket' in window) {
|
||||
iatWS = new WebSocket(websocketUrl)
|
||||
}
|
||||
changeBtnStatus("CONNECTING");
|
||||
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 = {
|
||||
})
|
||||
const params = {
|
||||
common: {
|
||||
app_id: APPID,
|
||||
},
|
||||
business: {
|
||||
language: "zh_cn",
|
||||
domain: "iat",
|
||||
accent: "mandarin",
|
||||
language: 'zh_cn',
|
||||
domain: 'iat',
|
||||
accent: 'mandarin',
|
||||
vad_eos: 5000,
|
||||
dwa: "wpgs",
|
||||
dwa: 'wpgs',
|
||||
},
|
||||
data: {
|
||||
status: 0,
|
||||
format: "audio/L16;rate=16000",
|
||||
encoding: "raw",
|
||||
format: 'audio/L16;rate=16000',
|
||||
encoding: 'raw',
|
||||
},
|
||||
};
|
||||
iatWS.send(JSON.stringify(params));
|
||||
};
|
||||
}
|
||||
iatWS.send(JSON.stringify(params))
|
||||
}
|
||||
iatWS.onmessage = (e) => {
|
||||
renderResult(e.data);
|
||||
};
|
||||
renderResult(e.data)
|
||||
}
|
||||
iatWS.onerror = (e) => {
|
||||
console.error(e);
|
||||
recorder.stop();
|
||||
changeBtnStatus("CLOSED");
|
||||
};
|
||||
console.error(e)
|
||||
recorder.stop()
|
||||
changeBtnStatus('CLOSED')
|
||||
}
|
||||
iatWS.onclose = (e) => {
|
||||
recorder.stop();
|
||||
changeBtnStatus("CLOSED");
|
||||
};
|
||||
recorder.stop()
|
||||
changeBtnStatus('CLOSED')
|
||||
}
|
||||
}
|
||||
|
||||
recorder.onFrameRecorded = ({ isLastFrame, frameBuffer }) => {
|
||||
|
@ -178,30 +187,28 @@ let btnStatus = "UNDEFINED"; // "UNDEFINED" "CONNECTING" "OPEN" "CLOSING" "CLOSE
|
|||
JSON.stringify({
|
||||
data: {
|
||||
status: isLastFrame ? 2 : 1,
|
||||
format: "audio/L16;rate=16000",
|
||||
encoding: "raw",
|
||||
format: 'audio/L16;rate=16000',
|
||||
encoding: 'raw',
|
||||
audio: toBase64(frameBuffer),
|
||||
},
|
||||
})
|
||||
);
|
||||
if (isLastFrame) {
|
||||
changeBtnStatus("CLOSING");
|
||||
}),
|
||||
)
|
||||
if (isLastFrame)
|
||||
changeBtnStatus('CLOSING')
|
||||
}
|
||||
}
|
||||
};
|
||||
recorder.onStop = () => {
|
||||
clearInterval(countdownInterval);
|
||||
};
|
||||
clearInterval(countdownInterval)
|
||||
}
|
||||
function RecordXunfei() {
|
||||
if (btnStatus === "UNDEFINED" || btnStatus === "CLOSED") {
|
||||
console.log('开始录音');
|
||||
connectWebSocket();
|
||||
} else if (btnStatus === "CONNECTING" || btnStatus === "OPEN") {
|
||||
console.log('结束录音');
|
||||
|
||||
if (btnStatus === 'UNDEFINED' || btnStatus === 'CLOSED') {
|
||||
console.log('开始录音')
|
||||
connectWebSocket()
|
||||
}
|
||||
else if (btnStatus === 'CONNECTING' || btnStatus === 'OPEN') {
|
||||
console.log('结束录音')
|
||||
// 结束录音
|
||||
recorder.stop();
|
||||
recorder.stop()
|
||||
}
|
||||
return window.winText
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang='ts'>
|
||||
import type { Ref } from 'vue'
|
||||
import { computed, onMounted, onUnmounted, reactive, ref, watch } from 'vue'
|
||||
import { computed, onMounted, onUnmounted, reactive, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import {
|
||||
|
@ -36,6 +36,9 @@ const connection = new Push({
|
|||
auth: '/plugin/webman/push/auth', // 订阅鉴权(仅限于私有频道)
|
||||
})
|
||||
|
||||
// 是否正在录音
|
||||
let recordFalg = 0
|
||||
|
||||
// 假设用户uid为1
|
||||
const uid = 1
|
||||
// 浏览器监听user-1频道的消息,也就是用户uid为1的用户消息
|
||||
|
@ -45,6 +48,15 @@ console.log(user_channel)
|
|||
user_channel.on('message', (data: any) => {
|
||||
// data里是消息内容
|
||||
console.log('收到命令', data)
|
||||
if (recordFalg == 0) {
|
||||
RecordXunfei()
|
||||
recordFalg = 1
|
||||
}
|
||||
else {
|
||||
RecordXunfei()
|
||||
handleSubmit()
|
||||
recordFalg = 0
|
||||
}
|
||||
})
|
||||
|
||||
let controller = new AbortController()
|
||||
|
@ -545,51 +557,35 @@ onUnmounted(() => {
|
|||
controller.abort()
|
||||
})
|
||||
const iatRecorder = reactive(new IatRecorder())
|
||||
let a = true
|
||||
const a = true
|
||||
|
||||
watch(() => iatRecorder.resultText, (n, o) => {
|
||||
console.log('监听', n)
|
||||
prompt.value = n
|
||||
// watch(() => iatRecorder.resultText, (n, o) => {
|
||||
// console.log('监听', n)
|
||||
// prompt.value = n
|
||||
// })
|
||||
|
||||
window.winText = ''
|
||||
|
||||
window.addEventListener('test', (e) => {
|
||||
if (recordFalg == 1)
|
||||
prompt.value = window.winText
|
||||
})
|
||||
|
||||
const click = () => {
|
||||
// new RecordXunfei();
|
||||
if (a) {
|
||||
iatRecorder.start(prompt.value)
|
||||
a = !a
|
||||
console.log('录音开始')
|
||||
}
|
||||
else {
|
||||
iatRecorder.stop()
|
||||
a = !a
|
||||
console.log('录音结束')
|
||||
console.log('最终结果', iatRecorder)
|
||||
}
|
||||
}
|
||||
// prompt.value = window.winText
|
||||
RecordXunfei()
|
||||
|
||||
const result = ref('')
|
||||
|
||||
// 录音
|
||||
const recordReady = () => {
|
||||
console.info('按钮就绪!')
|
||||
}
|
||||
const recordStart = () => {
|
||||
console.info('录音开始')
|
||||
}
|
||||
const showResult = (text) => {
|
||||
console.info('收到识别结果:', text)
|
||||
}
|
||||
const recordStop = () => {
|
||||
console.info('录音结束')
|
||||
}
|
||||
const recordNoResult = (text) => {
|
||||
console.info('没有录到什么,请重试')
|
||||
}
|
||||
const recordComplete = (text) => {
|
||||
console.info('识别完成! 最终结果:', text)
|
||||
}
|
||||
const recordFailed = (error) => {
|
||||
console.info('识别失败,错误栈:', error)
|
||||
// if (a) {
|
||||
// iatRecorder.start(prompt.value)
|
||||
// a = !a
|
||||
// console.log('录音开始')
|
||||
// }
|
||||
// else {
|
||||
// iatRecorder.stop()
|
||||
// a = !a
|
||||
// console.log('录音结束')
|
||||
// console.log('最终结果', iatRecorder)
|
||||
// }
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -619,7 +615,7 @@ const recordFailed = (error) => {
|
|||
</button>
|
||||
</div>
|
||||
<br>
|
||||
<div id="result" />
|
||||
<div id="result" ref="resultRef" />
|
||||
|
||||
<template v-if="!dataSources.length">
|
||||
<div
|
||||
|
|
Loading…
Reference in New Issue