当前位置: 首页 > web >正文

基于科大讯飞语音识别组件(Vue3)

        在之前的文章中讲了科大讯飞语音识别的基础使用,那么如果想将它作为组件放入我们的页面中该如何操作呢?

1、安装crypto-js

npm install crypto-js

        crypto-js是用JavaScript编写的加密库,支持多种加密算法,如AES、DES、RC4、SHA-1、SHA-256等,在科大讯飞提供的语音识别(转文字)接口中需要使用SHA-256加密算法传输数据来保障数据安全

2、下载科大讯飞提供的iat-js-demo

下载地址

下载之后文件结构是这样的

我们只需要提取dist中的index.esm即可,iat-js-demo文件夹可删除

3、导入RecorderManager方法

        index.esm中有一个RecorderManager方法,我们将他与crypto-js一起导入到我们的组件中(核心)

import RecorderManager from '../utils/index.esm'
import CryptoJS from 'crypto-js'

        由于文件结构的规范性的要求,创建utils文件夹,并且将index.esm.js与processor.worker.js两个文件放入utils文件夹(src/utils)

4、更改vite.config.js

        我们需要关闭ws代理以及确保worker文件可以被正确打包

devServer: {host: '0.0.0.0',port: 5173,proxy: {'/': {ws: false, // 这里把ws代理给关闭target: 'wss://iat-api.xfyun.cn/v2/iat',changeOrigin: true}}},
build: {rollupOptions: {output: {// 确保worker文件被正确打包assetFileNames: (assetInfo) => {if (assetInfo.name.endsWith('.worker.js')) {return assetInfo.name;}return `${assetInfo.name}.${assetInfo.ext}`;},},},},

5、初始化recorder

        由于Vue3无法使用require导入,所以用下面的方法进行初始化(new URL方法中第一个参数的路径为下载后文件的上级位置)

const recorder = new RecorderManager(new URL('@/utils', import.meta.url));

6、定义变量

let btnStatus = "UNDEFINED"; // "UNDEFINED" "CONNECTING" "OPEN" "CLOSING" "CLOSED"const recorder = new RecorderManager(new URL('@/utils', import.meta.url));
recorder.onStart = () => {changeBtnStatus("OPEN");
}
let iatWS;
let resultText = "";
let resultTextTemp = "";
let countdownInterval;
let user_input_msg = ref("")

7、定义方法

/*** 获取websocket url* 该接口需要后端提供,这里为了方便前端处理*/
function getWebSocketUrl() {// 请求地址根据语种不同变化var url = "wss://iat-api.xfyun.cn/v2/iat";var host = "iat-api.xfyun.cn";var apiKey = "自己的apikey";var apiSecret = "自己的apiSecret";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 = encryption();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;countdownInterval = setInterval(() => {seconds = seconds - 1;if (seconds <= 0) {clearInterval(countdownInterval);recorder.stop();}}, 1000);
}function changeBtnStatus(status) {btnStatus = status;if (status === "CONNECTING") {resultText = "";resultTextTemp = "";} else if (status === "OPEN") {countdown();} else if (status === "CLOSING") {} else if (status === "CLOSED") {}
}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"时表示该片结果是追加到前面singleData的最终结果;取值为"rpl" 时表示替换前面的部分结果,替换范围为rg字段if (data.pgs) {if (data.pgs === "apd") {// 将resultTextTemp同步给resultTextresultText = resultTextTemp;}// 将结果存储在resultTextTemp中resultTextTemp = resultText + str;} else {resultText = resultText + str;}user_input_msg.value = resultTextTemp || resultText || "";console.log(resultTextTemp);console.log(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: "1846696d",},business: {language: "zh_cn",domain: "iat",accent: "mandarin",vad_eos: 1000,dwa: "wpgs",},data: {status: 0,format: "audio/L16;rate=16000",encoding: "raw",},};iatWS.send(JSON.stringify(params));};iatWS.onmessage = (e) => {renderResult(e.data);};iatWS.onerror = (e) => {console.error(e);recorder.stop();changeBtnStatus("CLOSED");};iatWS.onclose = (e) => {recorder.stop();changeBtnStatus("CLOSED");};
}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);
};const start = () => {if (btnStatus === "UNDEFINED" || btnStatus === "CLOSED") {user_input_msg.value = ""connectWebSocket();} else if (btnStatus === "CONNECTING" || btnStatus === "OPEN") {// 结束录音recorder.stop();}};const audioEnd = () => {if (singleData.value.length == 0) {if (btnStatus === "UNDEFINED" || btnStatus === "CLOSED") {user_input_msg.value = ""connectWebSocket();} else if (btnStatus === "CONNECTING" || btnStatus === "OPEN") {// 结束录音recorder.stop();}}}

注明:核心方法为start()方法,需要触发该方法以实现语音转换文字

http://www.xdnf.cn/news/8117.html

相关文章:

  • PyInstaller 如何在mac电脑上生成在window上可执行的exe文件
  • AI 招聘系统科普:如何辨别真智能与伪自动化
  • 什么是VR实景?有哪些高价值场景?
  • 微信小程序学习基础:从入门到精通
  • 5G 网络中 DNN 的深度解析:从基础概念到核心应用
  • NMEA定位测试,硬件验证
  • 【工具】Quicker/VBA|PPT 在指定位置添加参考线
  • [Memory] 01.QEMU 内存虚拟化概览
  • Python实现PDB文件预处理
  • uniapp使用sse连接后端,接收后端推过来的消息
  • Rust 学习笔记:关于生命周期的练习题
  • Win11怎样禁止程序开机启动
  • 车载以太网网络测试-27【SOME/IP-SD简述】
  • MySQL中实现大数据量的快速插入
  • 游戏引擎学习第304天:构建与遍历图
  • 第六届电子通讯与人工智能国际学术会议(ICECAI 2025)
  • 语音控制设备的仿真/语音调试
  • Linux问题排查-磁盘IO使用率满如何分析
  • lambda表达式详解
  • leetcode 83和84 Remove Duplicates from Sorted List 和leetcode 1836
  • 设计模式-工厂模式和策略模式
  • Keil5 MDK LPC1768 RT-Thread KSZ8041NL uIP1.3.1实现UDP网络通讯(服务端接收并发数据)
  • 【web应用】vue3前端框架怎么修改logo?
  • 硬件产品死机问题
  • 蓝牙低功耗(BLE)的通信信道和包类型
  • HarmonyOS 鸿蒙应用开发基础:父组件和子组件的通信方法总结
  • linux系统启动脚本(格式问题)
  • 分布式系统设计 - 性能优化
  • Spring Cloud Gateway高并发限流——基于Redis实现方案解析
  • 【LeetCode 热题 100】二分查找 系列