vue+springboot实现语音控制页面操作

本文介绍了使用vue和springboot实现语音控制页面操作的两种方案,包括页面录音和企业微信录音。核心是将音频发送至后台,通过第三方如百度AI转译为文字,匹配指令并反馈给前端执行。分享了关键代码、数据库设计及优化措施。
摘要由CSDN通过智能技术生成

目录

第一种方案:在页面上实现录音

1、实现原理图

2、主要的实现思路

3、实现代码:

4、数据库设计及数据结构

5、优化方案

第二种方案:企业微信录音

1、实现原理图

2、实现思路

3、实现代码


 

工作中遇到了一个需求:语音控制大屏。说的清楚一点就是,使用麦克风说话来控制页面的跳转等操作;如:打开xxx,页面响应对应的操作。

此功能提供两种实现方案参考,第一种是在页面上提供按钮,页面录音,转向后台解析语音,转成命令,再返回给前端实现相应的操作;第二种方案是使用企业微信创建应用,使用手机录音转向后台解析,再返回给前端实现相应的操作。这里两种方案只是录音的方式不同,后台的思想是相同的。

这里踩的坑分享出来,提供大家参考。会提供主要的实现代码,包括前端、后台,以及提高语音识别率的优化方案。

第一种方案:在页面上实现录音

1、实现原理图

2、主要的实现思路

客户端录音,将音频文件传给后台服务端,后台(服务端)将音频文件发送给第三方(第三方可以选择百度或者讯飞,这里我选择百度)解析成文字,后台(服务端)接收到返回的中文,去查库将中文转成对应的指令(自己设计的数据结构),将指令返回给前端页面执行。

说明:这里选择使用数据库来解析,没有写死在后台是考虑到后期扩展,将服务端设计成无状态,可以动态扩展指令,以后只有修改数据库及前端实现指令的代码即可。

3、实现代码:

前端代码

页面实现录音代码:参考链接:https://www.jianshu.com/p/f5637e838af0

说明:录音vue实现的代码参考了上面给连接,在此基础上做了修改,设置音量大小达到值时开始录音,当录音结束后再一定的时间内自动保存音频文件(recorder.js中有说明)并自动调用服务端接口。

//recorder.js
export default class Recorder {
  constructor(stream, config) {
    //兼容
    window.URL = window.URL || window.webkitURL;
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;

    config = config || {};
    config.sampleBits = config.sampleBits || 16;   //采样数位 8, 16
    config.sampleRate = config.sampleRate || 8000; //采样率(1/6 44100)

    this.context = new (window.webkitAudioContext || window.AudioContext)();
    this.audioInput = this.context.createMediaStreamSource(stream);
    this.createScript = this.context.createScriptProcessor || this.context.createJavaScriptNode;
    this.recorder = this.createScript.apply(this.context, [4096, 1, 1]);

    this.audioData = {
      size: 0,          //录音文件长度
      buffer: [],    //录音缓存
      inputSampleRate: this.context.sampleRate,   //输入采样率
      inputSampleBits: 16,     //输入采样数位 8, 16
      outputSampleRate: config.sampleRate,   //输出采样率
      oututSampleBits: config.sampleBits,       //输出采样数位 8, 16
      input: function (data) {
        this.buffer.push(new Float32Array(data));
        this.size += data.length;
      },
      compress: function () { //合并压缩
        //合并
        let data = new Float32Array(this.size);
        let offset = 0;
        for (let i = 0; i < this.buffer.length; i++) {
          data.set(this.buffer[i], offset);
          offset += this.buffer[i].length;
        }
        //压缩
        let compression = parseInt(this.inputSampleRate / this.outputSampleRate);
        let length = data.length / compression;
        let result = new Float32Array(length);
        let index = 0, j = 0;
        while (index < length) {
          result[index] = data[j];
          j += compression;
          index++;
        }
        return result;
      },
      encodeWAV: function () {
        let sampleRate = Math.min(this.inputSampleRate, this.outputSampleRate);
        let sampleBits = Math.min(this.inputSampleBits, this.oututSampleBits);
        let bytes = this.compress();
        let dataLength = bytes.length * (sampleBits / 8);
        let buffer = new ArrayBuffer(44 + dataLength);
        let data = new DataView(buffer);

        let channelCount = 1;//单声道
        let offset = 0;

        let writeString = function (str) {
          for (let i = 0; i < str.length; i++) {
            data.setUint8(offset + i, str.charCodeAt(i));
          }
        };

        // 资源交换文件标识符
        writeString('RIFF');
        offset += 4;
        // 下个地址开始到文件尾总字节数,即文件大小-8
        data.setUint32(offset, 36 + dataLength, true);
        offset += 4;
        // WAV文件标志
        writeString('WAVE');
        offset += 4;
        // 波形格式标志
        writeString('fmt ');
        offset += 4;
        // 过滤字节,一般为 0x10 = 16
        data.setUint32(offset, 16, true);
        offset += 4;
        // 格式类别 (PCM形式采样数据)
        data.setUint16(offset, 1, true);
        offset += 2;
        // 通道数
        data.setUint16(offset, channelCount, true);
        offset += 2;
        // 采样率,每秒样本数,表示每个通道的播放速度
        data.setUint32(offset, sampleRate, true);
        offset += 4;
        // 波形数据传输率 (每秒平均字节数) 单声道×每秒数据位数×每样本数据位/8
        data.setUint32(offset, channelCount * sampleRate * (sampleBits / 8), true);
        offset += 4;
 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值