前端实现 web获取麦克风权限 录制音频 (需求:ai对话问答)

下载插件

javascript 复制代码
npm i recordrtc

文档:https://recordrtc.org/RecordRTC.html

相关方法整理

获取设备
javascript 复制代码
getvice() {
      if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
        var Mic = [];
        // 弹框获取麦克风
        navigator.mediaDevices.getUserMedia({ audio: true }).then((stream) => {
          navigator.mediaDevices.enumerateDevices().then((devices) => {
            devices.forEach((device) => {
              if (device.kind === "audioinput") {
                // 麦克风
                if (
                  device.deviceId != "default" &&
                  device.deviceId != "communications"
                ) {
                  this.Mic.push(device);//获取到的麦克风设备
                }
              }
            });
          });
          // 只是为了获取麦克风权限,获取以后立马关闭
          stream.getTracks().forEach((track) => track.stop());
          console.log(this.Mic, 22);
        });
      }
    },

开始录音

javascript 复制代码
 // 开始录音
    startRecord() {
      var that = this;
      // this.voiceStatus = true;
      // mediaDevices可提供对相机和麦克风等媒体输入设备的连接访问
      window.navigator.mediaDevices
        .getUserMedia({ audio: { deviceId: this.Mic[0].deviceId } })//设置{ audio: true}会选择电脑默认设置的麦克风设备
        .then((stream) => {
          this.stream = stream;
          this.getVoice();

          this.recorder = RecordRTC(stream, {
            type: "audio",//类型
            mimeType: "audio/wav",//音频格式
            recorderType: RecordRTC.StereoAudioRecorder,
            desiredSampRate: 16000,//频率
            numberOfAudioChannels: 2, // 单声道
            timeSlice: 1000,
            // bufferSize: 4096, // 缓存大小
            // ondataavailable: this.sendData,//有音频时的回调,一般及时传输websocket有用
            checkForInactiveTracks: true,
          });
          this.recorder.startRecording();
        })
        .catch(function (err) {
          console.log(err);
          console.log("当前浏览器不支持开启麦克风!");
          // that.voiceStatus = false;
        });
    },

停止录音

javascript 复制代码
  // 结束录音
    stopRecord() {
      // this.voiceStatus = false;
      if (this.recorder != null) {
        let recorder = this.recorder;
        // var internalRecorder = recorder.getInternalRecorder();
        // console.log("停止录音回调internalRecorder", internalRecorder);
        //停止录音
        recorder.stopRecording(() => {
          //   var BB = new Blob([recorder.getBlob()], {
          //   type: "audio/wav; codecs=opus",
          // });
          let blob = recorder.getBlob();//获取blob
          var audioURL = window.URL.createObjectURL(blob);

          // let a = document.createElement("a");
          // a.href = audioURL;
          // a.download = "测试";
          // a.click();
          // 将录音文件 以文件对象形式传给后端
          var form = new FormData();
          form.append("upfile", blob);
          console.log("form", form, blob);

          // 释放这个临时的对象url
          window.URL.revokeObjectURL(audioURL);
        });
        let stream = this.stream;
        clearInterval(this.timer1);
        RMSList = [//记录音频大小,用于音频波动样式绘制用
          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
          0, 0, 0, 0, 0, 0, 0,
        ];
        //结束媒体
        stream.getAudioTracks().forEach((track) => track.stop());
      }
    },

获取音量大小

javascript 复制代码
 // 获取音量值大小
    getVoice() {
      const audioContext = new (window.AudioContext ||
        window.webkitAudioContext)();
      // 将麦克风的声音输入这个对象
      const mediaStreamSource = audioContext.createMediaStreamSource(
        this.stream
      );
      // 创建分析节点
      const analyserNode = audioContext.createAnalyser();
      // 连接节点
      mediaStreamSource.connect(analyserNode);
      // 可以实时听到麦克风采集的声音
      // analyserNode.connect(audioContext.destination)

      // 获取音量数据
      const dataArray = new Uint8Array(analyserNode.frequencyBinCount);

      function getVolume() {
        analyserNode.getByteFrequencyData(dataArray);
        let sum = 0;
        for (let i = 0; i < dataArray.length; i++) {
          sum += dataArray[i];
        }
        // 计算平均音量
        const averageVolume = sum / dataArray.length;
        return averageVolume;
      }

      // 每隔一段时间获取一次音量
      this.timer1 = setInterval(() => {
        const volume = getVolume();
        console.log("音量:", Math.round(volume));
        RMSList.unshift(Math.round(volume));
        RMSList.pop();
        // 在这里可以根据需要进行相应的处理
      }, 100);
    },

以上用于记录,后续补充文章,整理AI对话搭建成果

相关推荐
天平1 小时前
油猴脚本创建webworker踩坑记录
前端·javascript·typescript
原则猫2 小时前
前端基础大厦
前端
陈随易4 小时前
编程语言级别的Skill市场,AI Agent 的未来形态
前端·后端·程序员
SoaringHeart4 小时前
Flutter进阶:基于 EasyRefresh 的下拉刷新封装 n_easy_refresh_mixin.dart
前端·flutter
IT_陈寒6 小时前
Vite的热更新突然不香了,排查三小时差点砸键盘
前端·人工智能·后端
子兮曰7 小时前
Agency-Agents 深度解析:400+ AI 专家的"梦之队"如何重塑开发工作流
前端·后端·vibecoding
竹林8187 小时前
用 The Graph 查询链上数据实战:从手搓 RPC 到 Subgraph,我的 NFT 项目数据加载快了 10 倍
前端·javascript
妙码生花8 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十九):点选验证码代码逐行目检
前端·后端·go
Awu12278 小时前
⚡从零开发 Agent CLI(五)实现一个可治理、可扩展的工具系统
前端·人工智能·claude
咪库咪库咪9 小时前
Vue3-生命周期
前端