1.要求:做语音,然后转成文字

2.使用api:科大讯飞语音听写

3.在 vue 项目中配置文件

4.配置后处理iatrecorder JS中new Woeker()会报错的问题

现在:

第一步:下载一个js版本的demo,获取iatrecorder js和转码worker。复制。 js文件到src

转码.worker.js:

// (函数(){

self.onmessage u003d 函数(e){

transAudioData.transcode(e.data)

}

让 transAudioData u003d {

转码(音频数据){

让输出 u003d transAudioData.to16kHz(audioData)

输出 u003d transAudioData.to16BitPCM(输出)

输出 u003d Array.from(new Uint8Array(output.buffer))

self.postMessage(输出)

// 返回输出

},

to16kHz(音频数据){

var 数据 u003d 新 Float32Array(audioData)

var fitCount u003d Math.round(data.length * (16000 / 44100))

var newData u003d new Float32Array(fitCount)

var springFactor u003d (data.length - 1) / (fitCount - 1)

新数据[0] u003d 数据[0]

for (让 i u003d 1; i < fitCount - 1; i++) {

var tmp u003d i * springFactor

var before u003d Math.floor(tmp).toFixed()

var after u003d Math.ceil(tmp).toFixed()

var atPoint u003d tmp - 之前

newData[i] u003d data[before] + (data[after] - data[before]) * atPoint

}

newData[fitCount - 1] u003d 数据[data.length - 1]

返回新数据

},

至 16 位 PCM(输入){

var dataLength u003d input.length * (16 / 8)

var dataBuffer u003d new ArrayBuffer(dataLength)

var 数据视图 u003d 新数据视图(数据缓冲区)

其中偏移量 u003d 0

for (var i u003d 0; i < input.length; i++, offset +u003d 2) {

var s u003d Math.max(-1, Math.min(1, input[i]))

dataView.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true)

}

返回数据视图

},

}

// })()

IatRecorder.js:

这里需要手动安装crypto JS,然后从'crypto JS'导入cryptojs

npm install crypto-js --save-dev

const APPID u003d '你的 APPID'

const API_SECRET u003d '你的 API_SECRET '

const API_KEY u003d '你的 API_KEY'

从“crypto-js”导入 CryptoJS

从 './transcode.worker.js' 导入 Worker

常量 transWorker u003d new Worker()

控制台.log(transWorker)

变量开始时间 u003d ""

变量结束时间 u003d ""

函数 getWebSocketUrl(){

返回新的承诺((解决,拒绝)u003d> {

// 请求地址根据不同语言变化

var url u003d 'wss://iat-api.xfyun.cn/v2/iat'

var 主机 u003d 'iat-api.xfyun.cn'

var apk u003d apk_key

var apiSecret u003d API_SECRET

var date u003d new Date().toGMTString()

远算法 u003d 最重要的شئ

var headers u003d '主机日期请求行'

变体签名来源 u003d `host: ${host}\ndate: ${date}\nGET /v2/iat HTTP/1.1`

var signatureSha u003d CryptoJS.HmacSHA256(signatureOrigin, apiSecret)

var 签名 u003d CryptoJS.enc.Base64.stringify(signatureSha)

var 授权来源 u003d `api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`

var 授权 u003d btoa(authorizationOrigin)

网址 u003d `${url}?authorization=${authorization}&date=${date}&host=${host}`

解决(网址)

})

}

常量 IatRecorder u003d 类 {

构造函数({ 语言、口音、appId } u003d {}){

让自我 u003d 这个

this.status u003d 'null'

this.language u003d 语言 || 'zh_cn'

this.accent u003d 重音 || '普通话'

this.appId u003d appId || APPID

// 录制音频数据

this.audioData u003d []

// 记录听写结果

this.resultText u003d ''

// wpgs下的听写结果需要记录在中间状态

this.resultTextTemp u003d ''

transWorker.onmessage u003d 函数(事件){

// console.log("在构造方法中", self.audioData)

self.audioData.push(...event.data)

}

}

// 修改录音听写状态

设置状态(状态){

this.onWillStatusChange && this.status !u003du003d 状态 && this.onWillStatusChange(this.status, status)

this.status u003d 状态

}

setResultText({ resultText, resultTextTemp } u003d {}) {

this.onTextChange && this.onTextChange(resultTextTemp || resultText || '')

resultText !u003du003d 未定义 && (this.resultText u003d resultText)

resultTextTemp !u003du003d 未定义 && (this.resultTextTemp u003d resultTextTemp)

}

// 修改听写参数

setParams({ 语言,口音 } u003d {}) {

语言 && (this.language u003d 语言)

重音 && (this.accent u003d 重音)

}

// 连接到 websocket

连接WebSocket() {

返回 getWebSocketUrl().then(url u003d> {

让 iatWS

if ('WebSocket' in window) {

iatWS u003d 新的 WebSocket(网址)

} else if ('MozWebSocket' in window) {

iatWS u003d 新 MozWebSocket(url)

} 其他 {

alert('浏览器不支持 WebSocket')

返回

}

this.webSocket u003d iatWS

this.setStatus('init')

so.onetime u003d h u003d> {

this.setStatus('ing')

// 重新开始录制

setTimeout(() u003d> {

this.webSocketSend()

}, 500)

}

iatWS.onmessage u003d e u003d> {

this.result(e.data)

}

iatWS.onerror u003d e u003d> {

this.recorderStop()

}

iaTOS.onclose u003d h u003d> {

endTime u003d Date.parse(新日期())

console.log("持续时间",endTime-startTime)

this.recorderStop()

}

})

}

// 初始化浏览器录制

记录器初始化() {

navigator.getUserMedia u003d

navigator.getUserMedia ||

navigator.webkitGetUserMedia ||

navigator.mozGetUserMedia ||

navigator.msGetUserMedia

// 创建音频环境

试试 {

this.audioContext u003d new (window.AudioContext || window.webkitAudioContext)()

this.audioContext.resume()

if (!this.audioContext) {

alert('浏览器不支持 webAudioApi 相关接口')

返回

}

} 捕捉 (e) {

if (!this.audioContext) {

alert('浏览器不支持 webAudioApi 相关接口')

返回

}

}

// 获取浏览器录制权限

if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {

navigator.mediaDevices

.getUserMedia({

音频:真实,

视频:错误,

})

.then(流 u003d> {

获取媒体成功(流)

})

.catch(e u003d> {

getMediaFail(e)

})

} else if (navigator.getUserMedia) {

navigator.getUserMedia(

{

音频:真实,

视频:错误,

},

流 u003d> {

获取媒体成功(流)

},

功能(e){

getMediaFail(e)

}

)

} 其他 {

if (navigator.userAgent.toLowerCase().match(/chrome/) && location.origin.indexOf('https://') < 0) {

alert('chrome要获取浏览器录音功能,因为安全问题,需要在localhost或者127.0.0.1或者https权限下才能获取')

} 其他 {

alert('无法获取浏览器的录音功能,请升级浏览器或使用chrome')

}

this.audioContext && this.audioContext.close()

返回

}

// 获取浏览器录制权限成功回调

让 getMediaSuccess u003d 流 u003d> {

// 创建一个直接通过 JavaScript 处理音频

this.scriptProcessor u003d this.audioContext.createScriptProcessor(0, 1, 1)

this.scriptProcessor.onaudioprocess u003d e u003d> {

// 处理音频数据

if (this.status u003du003du003d 'ing') {

transWorker.postMessage(e.inputBuffer.getChannelData(0))

// this.audioData.push(e.inputBuffer.getChannelData(0))

}

}

// 创建一个新的 mediastreamcaudiosourcenode 对象,以便可以播放和操作来自 MediaStream 的音频

this.mediaSource u003d this.audioContext.createMediaStreamSource(流)

// 连接

this.mediaSource.connect(this.scriptProcessor)

this.scriptProcessor.connect(this.audioContext.destination)

this.connectWebSocket()

}

让 getMediaFail u003d (e) u003d> {

this.audioContext && this.audioContext.close()

this.audioContext u003d 未定义

// 关闭 websocket

if (this.webSocket && this.webSocket.readyState u003du003du003d 1) {

this.webSocket.close()

}

}

}

记录器开始() {

if (!this.audioContext) {

this.recorderInit()

} 其他 {

this.audioContext.resume()

this.connectWebSocket()

}

}

// 暂停录制

记录器停止() {

// 在 safari 中挂起后再次恢复。录制内容将为空白。在 Safari 中设置不暂停

if (!(/Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgen))){

this.audioContext && this.audioContext.suspend()

}

this.setStatus('end')

}

// 处理音频数据

// transAudioData(audioData) {

// audioData u003d transAudioData.transaction(audioData)

// this.audioData.push(...audioData)

// }

// base64编码处理后的音频数据,

toBase64(缓冲区){

var 二进制 u003d ''

var bytes u003d new Uint8Array(buffer)

var len u003d bytes.byteLength

for (var i u003d 0; i < len; i++) {

二进制 +u003d String.fromCharCode(bytes[i])

}

返回 window.btoa(二进制)

}

// 发送数据到 webSocket

webSocketSend() {

if (this.webSocket.readyState !u003du003d 1) {

返回

}

让 audioData u003d this.audioData.splice(0, 1280)

变量参数 u003d {

常见:{

应用_id:this.appId,

},

业务:{

language: this.language, //控制台可以添加小语言-语音听写(流式)-方言/语言

域:'iat',

口音: this.accent, //可以在控制台添加汉语方言-语音听写(流式)-方言/语言

},

数据:{

状态:0,

格式:'audio/L16;rateu003d16000',

编码:'原始',

音频:this.toBase64(audioData),

},

}

console.log("参数语言:",this.language)

console.log("参数重音:",this.accent)

this.webSocket.send(JSON.stringify(params))

startTime u003d Date.parse(新日期())

this.handlerInterval u003d setInterval(() u003d> {

// websocket 未连接

if (this.webSocket.readyState !u003du003d 1) {

console.log("websocket 未连接")

this.audioData u003d []

clearInterval(this.handlerInterval)

返回

}

if (this.audioData.length u003du003du003d 0) {

console.log("自动关闭",this.status)

if (this.status u003du003du003d 'end') {

this.webSocket.send(

JSON.stringify({

数据:{

状态:2,

格式:'audio/L16;rateu003d16000',

编码:'原始',

音频:'',

},

})

)

this.audioData u003d []

clearInterval(this.handlerInterval)

}

返回假

}

audioData u003d this.audioData.splice(0, 1280)

// 中间帧

this.webSocket.send(

JSON.stringify({

数据:{

状态:1,

格式:'audio/L16;rateu003d16000',

编码:'原始',

音频:this.toBase64(audioData),

},

})

)

}, 40)

}

结果(结果数据){

// 识别结束

让 jsonData u003d JSON.parse(resultData)

if (jsonData.data && jsonData.data.result) {

让数据 u003d jsonData.data.result

让 str u003d ''

让 resultStr u003d ''

让 ws u003d data.ws

for (让 i u003d 0; i < ws.length; i++) {

str u003d str + ws[i].cw[0].w

}

console.log("识别结果为:",str)

//开启wpgs时该字段可用(前提:控制台开启动态修正功能)

// 当值为“apd”时,表示切片结果是追加到最前面的最终结果;当值为“rpl”时,表示替换之前的结果,替换范围为rg字段

如果(数据.pgs){

if (data.pgs u003du003du003d 'apd') {

// 将 resultTextTemp 同步到 resultText

this.setResultText({

结果文本:this.resultTextTemp,

})

}

// 将结果存储在 resultTextTemp 中

this.setResultText({

resultTextTemp:this.resultText + str,

})

} 其他 {

this.setResultText({

结果文本:this.resultText + str,

})

}

}

if (jsonData.code u003du003du003d 0 && jsonData.data.status u003du003du003d 2) {

this.webSocket.close()

}

if (jsonData.code !u003du003d 0) {

this.webSocket.close()

控制台.log(`${jsonData.code}:${jsonData.message}`)

}

}

开始() {

this.recorderStart()

this.setResultText({ resultText: '', resultTextTemp: '' })

}

停止() {

this.recorderStop()

}

}

导出默认 IatRecorder

第二步:配置你使用的页面:

<模板>

<div classu003d"conter">

<button @clicku003d"translationStart">开始</button>

<button @clicku003d"translationEnd">停止</button>

</div>

</模板>

<脚本>

从“@/assets/js/IatRecorder”导入 IatRecorder;

const iatRecorder u003d new IatRecorder('en_us','mandarin','9abbbfb0')//小语种-汉语方言-appId

导出默认 {

数据() {

返回{

};

},

方法:{

翻译开始() {

iatRecorder.start();

},

翻译结束() {

iatRecorder.onTextChange u003d (文本) u003d> {

让 inputText u003d 文本;

this.searchData u003d inputText.substring(0, inputText.length - 1); //文字处理,因为不知道为什么识别输出后面跟着'',这个方法去掉字符串的最后一位

控制台.log(this.searchData);

};

iatRecorder.stop();

},

}

};

</脚本>

引用的时候,问题来了,转码工。 JS文件

const transWorker u003d new Worker() 会报错因为原生new Worker不能直接在vue中使用

众所周知,JavaScript是单线程的,一些复杂耗时的操作会阻塞页面的渲染交互,造成页面卡顿,影响用户体验。 web worker 是 html5 的新特性之一。主要用于解决此类问题,为页面多开一个线程,在不影响主线程的情况下处理一些耗时的操作。

在实际vue项目的开发和使用过程中,遇到了很多问题

不同模块之间的通信主要是通过postMessage推送,通过onmessage接收,所以vue项目不能直接使用,必须配置。但是科大讯飞语音官网没有给出vue项目的例子,也没有特别说明,所以我也踩了个坑

第三步:解决new Worker()报错问题

首先,两个js文件都不需要更改

然后安装

npm install worker-loader -D

vue.config.js 添加以下配置:

configureWebpack: 配置 u003d> {

config.module.rules.push({

测试:/\.worker.js$/,

使用:{

装载机:“工人装载机”,

选项:{ 内联:true,名称:'workerName.[hash].js'}

}

})

},

运行的时候会发现控制台会报错,“window is undefined”。这是因为工作线程中没有window对象,所以不能直接使用。相反,在 Vue 配置中使用它。 JS

链Webpack:配置u003d> {

config.output.globalObject('this')

}

打包时添加:

平行:假

在一起是

模块.exports u003d {

configureWebpack: 配置 u003d> {

config.module.rules.push({

测试:/\.worker.js$/,

使用:{

装载机:“工人装载机”,

选项:{ 内联:true,名称:'workerName.[hash].js'}

}

})

},

平行:假,

链Webpack:配置u003d> {

config.output.globalObject('this')

}

}

配置完你会发现没有报错,然后就可以正常运行了!

到此结束。希望猿友可以一键连接三遍~~~

Logo

Vue社区为您提供最前沿的新闻资讯和知识内容

更多推荐