前端在线客服-实现发送语音

981 阅读2分钟
  1. 业务流程
  2. 创建频道 - 返回群组id
  3. 创建消息队列 - 根据群组id 发送类型消息
  4. 消息类型 文本 图片 语音消息 多媒体 文件 位置
  5. 通过轮询调取消息接口及时更新数据

本期使用的插件版本

"js-audio-recorder": "1.0.7", //主要用于Web端录制短音频
"lamejs": "1.2.0", //1.2.1的会报错,已经有人踩过坑
//将pcm(wav)音频文件转化为mp3格式,注意:需使用16采样位数
"vue-baidu-map": "^0.21.22",  //地图组件map

示例 web端录制音频demo

创建频道

  • 获取当前机构的用户
  • 选择同一频道内用户
  • 存放进user_code_list
  • 频道类型:两名用户为私聊,以上为群聊
  • 发送请求,返回群组id

创建消息队列

根据群组id来发送对应类型的数据

image.png

消息类型

  • 这里主要是音频部分 上代码!
  • 先引入js-audio-recorder,lamejs
import Recorder from "js-audio-recorder";
var lamejs = require("lamejs");
export default {
        data(){
            return{
            recorder:null
           }
       }
       methods:{
         // 初始化录音配置
        initRecorder() {
            this.recorder = new Recorder({
                sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
                sampleRate: 48000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
                numChannels: 1, // 声道,支持 1 或 2, 默认是1
                // compiling: false,(0.x版本中生效,1.x增加中) // 是否边录边转换,默认是false
            });
        },
         // 开始录音
        startRecorder() {
            this.initRecorder();
            this.recorder.start().then(
                () => {},
                (error) => {
                    // 出错了
                    console.log(`${error.name} : ${error.message}`);
                }
            );
        },
        // 结束录音
        stopRecorder() {
            this.recorder.stop();
        },
         // 销毁录音
        destroyRecorder() {
            let that = this;
            this.recorder.destroy().then(function () {
                that.recorder = null;
            });
        },
        // 获取录音文件
        getRecorder() {
            let toltime = this.recorder.duration; //录音总时长
            let fileSize = this.recorder.fileSize; //录音总大小
            //录音结束,获取取录音数据
            let PCMBlob = this.recorder.getPCMBlob(); //获取 PCM 数据
            let wav = this.recorder.getWAVBlob(); //获取 WAV 数据
            let channel = this.recorder.getChannelData(); //获取左声道和右声道音频数据
            this.getMp3Data(); //转成mp3
            this.isVoice = false;
            // 销毁音频实例
            this.destroyRecorder();
        },
        /**
         * 文件格式转换 wav-map3
         * */
         //发送Blob
        async getMp3Data() {
            const mp3Blob = this.convertToMp3(this.recorder.getWAV());
            console.log("mp3Blob", mp3Blob);
            let audioFile = new File([mp3Blob], Date.now() + ".mp3", {
                type: mp3Blob.type,
            });
            let fd = new FormData();
            fd.append("filename", audioFile);
            // 请求上传接口
            let result = await apiUpload(fd);
            // 创建消息队列
            this.apiInserMessage("voice", result.data.path);
            // 下载本地MP3文件
            // this.recorder.download(mp3Blob, "recorder", "mp3");
        },
        convertToMp3(wavDataView) {
            // 获取wav头信息
            console.log(lamejs);
            const wav = lamejs.WavHeader.readHeader(wavDataView); // 此处其实可以不用去读wav头信息,毕竟有对应的config配置
            const { channels, sampleRate } = wav;
            const mp3enc = new lamejs.Mp3Encoder(channels, sampleRate, 128);
            // 获取左右通道数据
            const result = this.recorder.getChannelData();
            const buffer = [];
            const leftData =
                result.left &&
                new Int16Array(
                    result.left.buffer,
                    0,
                    result.left.byteLength / 2
                );
            const rightData =
                result.right &&
                new Int16Array(
                    result.right.buffer,
                    0,
                    result.right.byteLength / 2
                );
            const remaining =
                leftData.length + (rightData ? rightData.length : 0);
            const maxSamples = 1152;
            for (let i = 0; i < remaining; i += maxSamples) {
                const left = leftData.subarray(i, i + maxSamples);
                let right = null;
                let mp3buf = null;
                if (channels === 2) {
                    right = rightData.subarray(i, i + maxSamples);
                    mp3buf = mp3enc.encodeBuffer(left, right);
                } else {
                    mp3buf = mp3enc.encodeBuffer(left);
                }
                if (mp3buf.length > 0) {
                    buffer.push(mp3buf);
                }
            }
            const enc = mp3enc.flush();
            if (enc.length > 0) {
                buffer.push(enc);
            }
            return new Blob(buffer, { type: "audio/mp3" }); //返回Blob
        },
        //获取录音权限
        microphoneHandel() {
            this.isVoice = !this.isVoice;
            Recorder.getPermission().then(
                () => {
                    this.$message.success("获取录音权限成功");
                },
                (error) => {
                    console.log(`${error.name} : ${error.message}`);
                }
            );
        },
    }
}