赞
踩
vue使用科大讯飞实时语音转写示例
官方文档:https://www.xfyun.cn/doc/asr/rtasr/API.html
1.需要申请先APPID、API_KEY
2.把官方案例js的示例下载下来
3.引入了下载的官方案例中的几个文件
4.示例代码
`<template>
<div class="home">
<button id="startBtn">
开始
</button>
<button id="endBtn">
结束
</button>
<div id="output"></div>
<div id="time" v-show="false">00: 00</div>
</div>
</template>`
export default { name: 'HomeView', components: { }, mounted() { this.audioInit() }, methods: { audioInit() { // 初始化语音转写 let startBtn = document.getElementById("startBtn") // 结束按钮 let endBtn = document.getElementById("endBtn") // 接收识别的文本 let output = document.getElementById("output") // 记时器 let time = document.getElementById("time") // 如果使用的是webpack,或者报错 请尝试这种写法 const recorderWorker = new Worker('../assets/js/transformpcm.worker.js') const recorderWorker = new Worker(new URL('../utils/transformpcm.worker.js', import.meta.url)) // 记录处理的缓存音频 let buffer = [] let AudioContext = window.AudioContext || window.webkitAudioContext navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia recorderWorker.onmessage = function (e) { buffer.push(...e.data.buffer) } class IatRecorder { constructor(config) { this.config = config this.state = 'ing' //以下信息在控制台-我的应用-实时语音转写 页面获取 this.appId = '5febed45' this.apiKey = 'a61ff9579e78926146465f9b48be93c2' } start() { this.stop() if (navigator.getUserMedia && AudioContext) { this.state = 'ing' if (!this.recorder) { var context = new AudioContext() this.context = context console.log(context) this.recorder = context.createScriptProcessor(0, 1, 1) var getMediaSuccess = (stream) => { var mediaStream = this.context.createMediaStreamSource(stream) this.mediaStream = mediaStream this.recorder.onaudioprocess = (e) => { this.sendData(e.inputBuffer.getChannelData(0)) } this.connectWebsocket() } var getMediaFail = (e) => { this.recorder = null this.mediaStream = null this.context = null console.log('请求麦克风失败') alert("请求麦克风失败") } if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then((stream) => { console.log(stream) getMediaSuccess(stream) }).catch((e) => { console.log(e) getMediaFail(e) }) } else { navigator.getUserMedia({ audio: true, video: false }, (stream) => { getMediaSuccess(stream) }, function (e) { console.log(e) getMediaFail(e) }) } } else { this.connectWebsocket() } } else { var isChrome = navigator.userAgent.toLowerCase().match(/chrome/) alert("暂不支持使用该浏览器,请使用chrome浏览器") } } stop() { this.state = 'end' try { this.mediaStream.disconnect(this.recorder) this.recorder.disconnect() } catch (e) { } } sendData(buffer) { recorderWorker.postMessage({ command: 'transform', buffer: buffer }) } // 生成握手参数 getHandShakeParams() { var appId = this.appId var secretKey = this.apiKey var ts = Math.floor(new Date().getTime() / 1000);//new Date().getTime()/1000+''; var signa = hex_md5(appId + ts)//hex_md5(encodeURIComponent(appId + ts));//EncryptUtil.HmacSHA1Encrypt(EncryptUtil.MD5(appId + ts), secretKey); var signatureSha = CryptoJSNew.HmacSHA1(signa, secretKey) var signature = CryptoJS.enc.Base64.stringify(signatureSha) signature = encodeURIComponent(signature) return "?appid=" + appId + "&ts=" + ts + "&signa=" + signature + '&pd=court'; } connectWebsocket() { var url = 'wss://rtasr.xfyun.cn/v1/ws' var urlParam = this.getHandShakeParams() url = `${url}${urlParam}` if ('WebSocket' in window) { this.ws = new WebSocket(url) } else if ('MozWebSocket' in window) { this.ws = new MozWebSocket(url) } else { alert(notSupportTip) return null } this.ws.onopen = (e) => { this.mediaStream.connect(this.recorder) this.recorder.connect(this.context.destination) setTimeout(() => { this.wsOpened(e) }, 500) this.config.onStart && this.config.onStart(e) } this.ws.onmessage = (e) => { // this.config.onMessage && this.config.onMessage(e) this.wsOnMessage(e) } this.ws.onerror = (e) => { this.stop() console.log("关闭连接ws.onerror"); this.config.onError && this.config.onError(e) } this.ws.onclose = (e) => { this.stop() console.log("关闭连接ws.onclose"); // $('.start-button').attr('disabled', false); this.config.onClose && this.config.onClose(e) } } wsOpened() { if (this.ws.readyState !== 1) { return } var audioData = buffer.splice(0, 1280) this.ws.send(new Int8Array(audioData)) this.handlerInterval = setInterval(() => { // websocket未连接 if (this.ws.readyState !== 1) { clearInterval(this.handlerInterval) return } if (buffer.length === 0) { if (this.state === 'end') { this.ws.send("{\"end\": true}") console.log("发送结束标识"); clearInterval(this.handlerInterval) } return false } var audioData = buffer.splice(0, 1280) if (audioData.length > 0) { this.ws.send(new Int8Array(audioData)) } }, 40) } wsOnMessage(e) { let jsonData = JSON.parse(e.data) if (jsonData.action == "started") { // 握手成功 console.log("握手成功"); } else if (jsonData.action == "result") { // 转写结果 if (this.config.onMessage && typeof this.config.onMessage == 'function') { this.config.onMessage(jsonData.data) } } else if (jsonData.action == "error") { // 连接发生错误 console.log("出错了:", jsonData); alert("连接发发生错误") } } ArrayBufferToBase64(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) } } class IatTaste { constructor() { var iatRecorder = new IatRecorder({ onClose: () => { this.stop() this.reset() }, onError: (data) => { this.stop() this.reset() alert('WebSocket连接失败') }, onMessage: (message) => { this.setResult(JSON.parse(message)) }, onStart: () => { this.counterDown(time) } }) this.iatRecorder = iatRecorder this.counterDownDOM = time this.counterDownTime = 0 } start() { this.iatRecorder.start() } stop() { this.iatRecorder.stop() } reset() { this.counterDownTime = 0 clearTimeout(this.counterDownTimeout) buffer = [] } init() { let self = this //开始按钮的事件 startBtn.onclick = function () { if (navigator.getUserMedia && AudioContext && recorderWorker) { self.start() } else { alert(notSupportTip) } } //结束按钮的事件 endBtn.onclick = function () { self.stop() //reset this.counterDownTime = 0 clearTimeout(this.counterDownTimeout) buffer = [] } } // 转写的结果 setResult(data) { let rtasrResult = [] rtasrResult[data.seg_id] = data rtasrResult.forEach(i => { let str = "" if (i.cn.st.type == 0) { i.cn.st.rt.forEach(j => { j.ws.forEach(k => { k.cw.forEach(l => { str += l.w }) }) }) console.log(output.value,str) console.log(str) if(str != '。' && str != '?'&& str != '?') { output.value += str } } }) } // 计时器 counterDown() { if (this.counterDownTime >= 0 && this.counterDownTime < 10) { this.counterDownDOM.innerText = '00: 0' + this.counterDownTime } else if (this.counterDownTime >= 10 && this.counterDownTime < 60) { this.counterDownDOM.innerText = '00: ' + this.counterDownTime } else if (this.counterDownTime % 60 >= 0 && this.counterDownTime % 60 < 10) { this.counterDownDOM.innerText = '0' + parseInt(this.counterDownTime / 60) + ': 0' + this.counterDownTime % 60 } else { this.counterDownDOM.innerText = '0' + parseInt(this.counterDownTime / 60) + ': ' + this.counterDownTime % 60 } this.counterDownTime++ this.counterDownTimeout = setTimeout(() => { this.counterDown() }, 1000) } } var iatTaste = new IatTaste() iatTaste.init() } } }
单纯记录使用过程,效果比paddlespeech转写效果要好
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。