首页 > 其他分享 >vue前端获取/切换麦克风、播放采集音频和采集音量大小完整代码

vue前端获取/切换麦克风、播放采集音频和采集音量大小完整代码

时间:2024-03-11 14:58:48浏览次数:28  
标签:mediaDevices vue const 麦克风 stream 采集 window audio

1、创建Vue项目在终端运行

npm install element-ui
npm install recordrtc

2、案例图示

 

3、代码

1、获取麦克风列表

if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
  var Mic = []
  // 弹框获取麦克风
  navigator.mediaDevices.getUserMedia({audio: true}).then((stream) => {
    navigator.mediaDevices.enumerateDevices().then(function (devices) {
      devices.forEach(function (device) {
        if(device.kind === 'audioinput'){ // 麦克风
          if(device.deviceId != 'default' && device.deviceId != 'communications'){
            that.Mic.push(device)
          }
        }
      });
    })
  // 只是为了获取麦克风权限,获取以后立马关闭
  stream.getTracks().forEach(track => track.stop());
  })
}

2、用户在麦克风列表里面选择一个麦克风

<el-form
  style="padding: 0 80px"
  ref="mainFormRef"
  :model="main_form"
  label-width="100px"
  :rules="rules"
>
  <el-form-item label="声纹采集:" prop="file">
    <el-select :disabled="voiceStatus" style="width: 200px;" v-model="main_form.chooseMicDeviceId" placeholder="请选择麦克风">
      <el-option
        v-for="item in Mic"
        :key="item.deviceId"
        :label="item.label"
        :value="item.deviceId">
      </el-option>
    </el-select>
    <div class="voiceGather" v-if="main_form.chooseMicDeviceId != ''">
      <el-button style="margin-top: 20px;" @click="voiceInput">{{ voiceStatus ? '取消录音' : '开始录音' }}</el-button>
     
    </div>
  </el-form-item>
</el-form>

 

3、选取了麦克风以后使用当前麦克风录音

重要代码:audio: { deviceId: this.form.chooseMicDeviceId },将上面选的麦克风放到getUserMedia中,即可启用用户自己选择的麦克风

// 开始录音
startRecord(){
  var that = this
  this.voiceStatus = true
  // mediaDevices可提供对相机和麦克风等媒体输入设备的连接访问
  window.navigator.mediaDevices.getUserMedia(
    { audio: { deviceId: this.main_form.chooseMicDeviceId }}
    ).then((stream) => {
    this.stream = stream;
    this.getVoice()
    
    this.recorder = RecordRTC(stream, {
      type: 'audio',
      mimeType: 'audio/wav',
      recorderType: RecordRTC.StereoAudioRecorder,
      desiredSampRate: 16000,
      numberOfAudioChannels: 1, // 单声道
      timeSlice: 30000,
      // bufferSize: 4096, // 缓存大小
      ondataavailable: this.sendData,
    });
    this.recorder.startRecording();
  }).catch(function(err) {
    console.log(err);
    console.log('当前浏览器不支持开启麦克风!');
    that.voiceStatus = false
  });
},

在sendData中可以把数据流传给后端,可以播放/下载采集到的数据流,也可以将数据流转换成file传给后端

sendData(blob) {
  var BB =new Blob([blob], {'type': 'audio/wav; codecs=opus'})
  // var audioURL = window.URL.createObjectURL(BB)

  // 播放
  // const audio = document.createElement('audio')
  // audio.controls = true // 音频是否显示控件
  // audio.src = audioURL
  // audio.play()

  // 下载
  // let a = document.createElement("a");
  // a.href = audioURL;
  // a.download = '测试';
  // a.click();
  // // 释放这个临时的对象url
  // window.URL.revokeObjectURL(audioURL);

  let file = new window.File([BB], '测试.wav')
  console.log(file);
},

4、获取采集的音频音量大小

// 获取音量值大小
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 ));
// 在这里可以根据需要进行相应的处理
}, 100);
},

 

四、全部代码

<template>
    <div class="Page">
      <el-form
        style="padding: 0 80px"
        ref="mainFormRef"
        :model="main_form"
        label-width="100px"
        :rules="rules"
      >
        <el-form-item label="声纹采集:" prop="file">
          <el-select :disabled="voiceStatus" style="width: 200px;" v-model="main_form.chooseMicDeviceId" placeholder="请选择麦克风">
            <el-option
              v-for="item in Mic"
              :key="item.deviceId"
              :label="item.label"
              :value="item.deviceId">
            </el-option>
          </el-select>
          <div class="voiceGather" v-if="main_form.chooseMicDeviceId != ''">
            <el-button style="margin-top: 20px;" @click="voiceInput">{{ voiceStatus ? '取消录音' : '开始录音' }}</el-button>
            <!-- 正在录制 -->
            <!-- <template v-if="voiceStatus">
              <div class="bo">
                <div v-for="(item, index) in RMSList" :key="index" :style="{height: item / 100 * 40 + 'px'}" class="RMS"></div>
              </div>
            </template> -->
          </div>
        </el-form-item>
      </el-form>
    </div>
  </template>
  
  <script>
  import RecordRTC from 'recordrtc'

  import Vue from 'vue'
 
 //放到1和2这俩中间
 import ElementUI from 'element-ui';
 import 'element-ui/lib/theme-chalk/index.css';
 Vue.use(ElementUI);
 
  export default {
    name:"Voice",
    data() {
      return {
        recorder: '',
        voiceStatus: false, // 是否正在录音
        main_form: {
          chooseMicDeviceId: '', // 选择的麦克风id
        },
        Mic: [], // 可选择的麦克风
        rules: {
          file: [
            { required: true, message: "不能为空", trigger: "blur" },
          ],
        },
      };
    },
    created() {},
    mounted() {
      console.log("1111")
      this.getMic()
    },
    methods: {
      // 获取当前页面可以选择的麦克风
      getMic(){
        console.log(1111)
        let that = this;
        if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
          // 弹框获取麦克风
          navigator.mediaDevices.getUserMedia({audio: true}).then((stream) => {
            navigator.mediaDevices.enumerateDevices().then(function (devices) {
              devices.forEach(function (device) {
                console.log(device);
                if(device.kind === 'audioinput'){ // 麦克风
                  if(device.deviceId != 'default' && device.deviceId != 'communications'){
                    that.Mic.push(device)
                  }
                }
                
              });
            })
            stream.getTracks().forEach(track => track.stop());
          })
        }
        
      },
  
      // 语音输入
      voiceInput(){
        // 正在语音输入
        if(this.voiceStatus) {
          this.stopRecord() // 停止输入
        } else { // 开启语音输入
          this.startRecord()
        }
      },
  
      // 开始录音
      startRecord(){
        var that = this
        this.voiceStatus = true
        // mediaDevices可提供对相机和麦克风等媒体输入设备的连接访问
        window.navigator.mediaDevices.getUserMedia(
          { audio: { deviceId: this.main_form.chooseMicDeviceId }}
          ).then((stream) => {
          this.stream = stream;
          this.getVoice()
          
          this.recorder = RecordRTC(stream, {
            type: 'audio',
            mimeType: 'audio/wav',
            recorderType: RecordRTC.StereoAudioRecorder,
            desiredSampRate: 16000,
            numberOfAudioChannels: 1, // 单声道
            timeSlice: 1000,
            // bufferSize: 4096, // 缓存大小
            ondataavailable: this.sendData,
          });
          this.recorder.startRecording();
        }).catch(function(err) {
          console.log(err);
          console.log('当前浏览器不支持开启麦克风!');
          that.voiceStatus = false
        });
      },
  
      // 结束录音
      stopRecord(){
        this.voiceStatus = false
        if (this.recorder != null) {
          let recorder = this.recorder
          recorder.stopRecording();
          let stream = this.stream;
          clearInterval(this.timer1);
          stream.getAudioTracks().forEach(track => track.stop());
        }
      },
  
      // 获取音量值大小
      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 ));
          // 在这里可以根据需要进行相应的处理
        }, 100);
      },
  
      // 每timeSlice执行一次
      sendData(blob) {
        var BB = new Blob([blob], {'type': 'audio/wav; codecs=opus'})
        var audioURL = window.URL.createObjectURL(BB)
  
        //播放
        const audio = document.createElement('audio')
        audio.controls = true // 音频是否显示控件
        audio.src = audioURL
        audio.play()
  
        // //下载
        // let a = document.createElement("a");
        // a.href = audioURL;
        // a.download = '测试';
        // a.click();
        // // 释放这个临时的对象url
        // window.URL.revokeObjectURL(audioURL);
  
        let file = new window.File([BB], '测试.wav')
        console.log(file);
      },
    },
  };
  </script>
  
  <style scoped>
  
  .Page{
    padding: 20px;
  }
  </style>
View Code

 

标签:mediaDevices,vue,const,麦克风,stream,采集,window,audio
From: https://www.cnblogs.com/handsomeziff/p/18066058

相关文章

  • Vue — v-model详解
    一、v-model原理原理:v-model本质上是一个语法糖。例如在inpu中,就是value属性和input事件的合写作用:提供数据的双向绑定双向绑定:数据变,视图跟着变;视图变,数据跟着变二、表单类组件封装&v-model简化代码1.表单组件封装的核心思路:(1)父传子:数据从父组件使用prop传递给子组件渲染......
  • JeecgBoot Vue3前端项目性能优化&按需加载方案
    JeecgBootvue3前端项目在3.5.5版本之前,的确存在很严重的性能问题,大家可以参考以下文档进行升级。按需加载改造方法1、全局注册地方去掉2、组件改成异步注册3、用不到的大组件可以删掉【精简项目方案】大组件1、富文本tinyme2、Markdown3、CodeMirror4、地图数据......
  • Vue-手动清空Form表单的验证及验证提示(红字提示)
    问题:form表单清空校验,使用系统方法clearValidate和resetFields这两个方法清空校验的时候,无法清除。解决办法:在this.$nextTick这个方法里边调用clearValidate/resetFields这两个方法。this.$nextTick(function(){this.$refs.formRefs.clearValidate();})由于DOM......
  • Vue — 组件通信
    一、父传子<!--1.父组件:给子组件用添加属性的方式来传值--><Son:msg="msg":arr="arr"></Son>//2.子组件:子组件通过props来接收props:['msg','arr']关于prop1.什么是prop(1)定义:组件上定义的一些自定义属性(2)作用:向子组件传递数据(3)特点:可以传任意......
  • vue父子组件传参后,子组件重新初始化
    首先回顾一下父子组件生命周期的执行顺序:加载渲染过程:父beforeCreate ---> 父created ---> 父beforeMount ---> 子beforeCreate ---> 子created ---> 子beforeMount ---> 子mounted ---> 父mounted 子组件更新过程:父beforeUpdate ---> 子beforeUpdate--->......
  • vue3 监听鼠标点击拖动事件,移动端滑动事件,页面指针坐标事件
    PointerEventsAPI是Hmtl5的事件规范之一,它主要目的是用来将鼠标(Mouse)、触摸(touch)和触控笔(pen)三种事件整合为统一的API。Pointer指可以在屏幕上反馈一个指定坐标的输入设备。PointerEvent事件和TouchEventAPI对应的触摸事件类似,它继承扩展了TouchEvent,因此拥有TouchEven......
  • 基于vue+springboot高校宿舍管理系统
    本项目是一款基于springBoot的高校宿舍管理系统。本系统主要功能包含:(1)基本信息管理基本信息分为学生信息和宿舍信息两部分,其功能是负责维护这些信息,对它们进行增删查改等操作。宿舍分配管理(2)根据给定的宿舍信息与学生信息,按照一定的规则自动地给还未分配宿舍的学生分配宿舍,......
  • Vue学习笔记42--ref
    Vue==>refref属性被用来给元素或子组件注册引用信息(id的替代者)应用在html标签上获取的是真实的DOM元素,应用在组件标签上是组件实例对象(vc)使用方式:声明标识:<h1ref="xxx">。。。。。。</h1>或<Schoolref="xxx"></School>——School为组件获取方式:this.$refs.xxx......
  • vue项目实现PC端各分辨率适配
    最近做项目刚好用到pc端分辨率适配,在这里分享一下我的做法。1.先下载需要的插件包px2rem-loader、postcss-pxtoremnpminstallpx2rem-loadernpminstallpostcss-pxtorem@5.1.12.配置rem.js文件(名称自己随意取就可以),一般放置在utils文件夹里,没有就新建一个utils文件......
  • 在Chrome添加vue插件
    1.首先打开Chrome的开发者模式:(1)点击浏览器的"设置",再点击"扩展程序”:(2)或者直接点击浏览器右上角的扩展程序:打开右上角的“开发者模式”:2.在github下载vue插件,点击进入下载地址:https://github.com/vuejs/devtools3.依次点击下载:按需要浏览器(Chrome)下载:4.点击添加到......