科大讯飞语音拼写 + 导出音频文件
重要 不支持的手机浏览器
-
小米手机自带浏览器 15 版本以上不支持录音
-
阿里系浏览器不支持浏览器录音
-
vivo 和 oppo 手机自带浏览不支持录音(待测试)
科大讯飞语音拼写 demo 下载
引入到自己的项目的时候需要注意的地方
index.js
import TransWorker from 'js/transcode.worker.js'
webpack.config.js
module.exports = function (env, argv) {
env = env || {}
return {
mode: 'development',
devtool: conf.devtool,
module: {
rules: [
{
test: /\.worker\.js$/,
use: { loader: 'worker-loader' }
},
]
},
}
}
-
看着就是一个正常引入 其实在 webpack.config.js 中做了设置
-
是用 worker-loader 引入的worker.js文件
-
我当时就上当了(引入到项目的时候怎么弄就是不好使)
// 我引入的时候就是这样的
import TransWorker from "worker-loader!./transcode.worker.js";
把输入的录音导出来
-
Recorder 发现这个非常好用的插件
-
和科大讯飞的录音权限有重复获取 体验上没什么,不过我认为完全没必要引入Recorder 我只要获取到音频文件就行了
接下来就是找音频文件了
-
科大讯飞的官网上有个base64的文件,每次请求的时候都会带着,我想着就把这个base64转换一下转成我想要的,我没成功我放弃了
-
找到 inputBuffer.getChannelData(0) 这个就是获取音频一帧的文件,把每一帧的文件保存起来,等结束的时候转成音频文件就行了
this.iatRecorder.stop(); // 音频结束录制的时候
// this.iatRecorder.audiobase64 这个是我的音频文件
this.audiobase64 = this.iatRecorder.audiobase64;
let alldata = this.mergeArray(this.iatRecorder.audiobase64);
let wavBuffer = this.createWavFile(alldata);
let audioblob = new Blob([new Uint8Array(wavBuffer)]);
let audiosrc = window.URL.createObjectURL(audioblob);
- 这个就是我的音频文件
mergeArray(list) {
const length = list.length * list[0].length
const data = new Float32Array(length)
let offset = 0
for (let i = 0; i < list.length; i++) {
data.set(list[i], offset)
offset += list[i].length
}
return data
},
createWavFile (audioData) {
const WAV_HEAD_SIZE = 44;
let buffer = new ArrayBuffer(audioData.length * 2 + WAV_HEAD_SIZE),
// 需要用一个view来操控buffer
view = new DataView(buffer);
// 写入wav头部信息
// RIFF chunk descriptor/identifier
this.writeUTFBytes(view, 0, 'RIFF');
// RIFF chunk length
view.setUint32(4, 44 + audioData.length * 2, true);
// RIFF type
this.writeUTFBytes(view, 8, 'WAVE');
// format chunk identifier
// FMT sub-chunk
this.writeUTFBytes(view, 12, 'fmt ');
// format chunk length
view.setUint32(16, 16, true);
// sample format (raw)
view.setUint16(20, 1, true);
// stereo (2 channels)
view.setUint16(22, 2, true);
// sample rate
view.setUint32(24, 44100, true);
// byte rate (sample rate * block align)
view.setUint32(28, 44100 * 2, true);
// block align (channel count * bytes per sample)
view.setUint16(32, 2 * 2, true);
// bits per sample
view.setUint16(34, 16, true);
// data sub-chunk
// data chunk identifier
this.writeUTFBytes(view, 36, 'data');
// data chunk length
view.setUint32(40, audioData.length * 2, true);
let length = audioData.length;
let index = 44;
for (let i = 0; i < length; i++) {
// view.setInt16(index, audioData[i] * (0x7FFF * volume), true);
var s = Math.max(-1, Math.min(1, audioData[i]))
view.setInt16(index, s < 0 ? s * 0x8000 : s * 0x7fff, true)
index += 2;
}
return buffer;
},
writeUTFBytes (view, offset, string) {
var lng = string.length;
for (var i = 0; i < lng; i++) {
view.setUint8(offset + i, string.charCodeAt(i));
}
- 这块技术主要是借鉴了 xiangyuecn 大佬的文章