使用vue3封装一个hooks实时获取麦克风音量

之前是在做一个electron项目中需要去检测音量,检测音量不是为了证明音量本身,而是去看看麦克风是否正常响应。

如图所示:这是一个模仿腾讯会议的音量检测的UI


在浏览器中是无法获取真实设备的电平输入的,所以此方法是通过后去音频数据来计算出音量,并非系统实际音量

使用场景
  • 在web端对麦克风进行检测,看看麦克风是否有效
  • 在electron、Capacitor等以web交互为主开发的应用都可以支持(比如:electron应用)
ts 复制代码
// useVolume.ts

import { ref } from 'vue'

/**
 * 实时获取麦克风音量
 * 此方法是通过后去音频数据来计算出音量,并非系统实际音量
 * @param _audioContext 如果传入AudioContext,则使用它,否则新建一个音频来获取音量大小
 * @returns
 */
export const useVolume = () => {
  const audioContext = ref<AudioContext | null>()
  const analyser = ref<AnalyserNode | null>(null)
  const isStart = ref<boolean>(false)
  // 音量[0, 100]
  const volume = ref<number>(0)

  /**
   * 开启音量检测
   * @param _source 数据源
   * @param _audioContext audio上下文 (用于在录音的过程中同时去检测,这样就不需要再次创建多一个audio上下文)
   * @param deviceId 麦克风设备ID,用于指定检测那个麦克风的音量
   */
  const startVolumeCheck = async (
    _source?: MediaStreamAudioSourceNode | null,
    _audioContext?: AudioContext | null,
    deviceId?: string | null,
  ) => {
    if (!audioContext.value) {
      if (_audioContext) {
        audioContext.value = _audioContext
      } else {
        audioContext.value = new AudioContext()
      }
    }

    isStart.value = true
    const mediaOptions = deviceId
      ? { audio: { deviceId: deviceId } }
      : { audio: true }
    let source = _source
    if (!source) {
      const stream = await navigator.mediaDevices.getUserMedia(mediaOptions)
      source = audioContext.value.createMediaStreamSource(stream)
    }

    analyser.value = audioContext.value.createAnalyser()
    analyser.value!.fftSize = 32
    source.connect(analyser.value!)

    // 创建数据缓冲区
    const bufferLength = analyser.value!.frequencyBinCount
    const dataArray = new Uint8Array(bufferLength)

    // 定义更新音量的函数
    function updateVolume() {
      analyser.value!.getByteFrequencyData(dataArray)

      let sum = 0
      for (let i = 0; i < bufferLength; i++) {
        sum += dataArray[i]
      }
      volume.value = Math.floor((sum / bufferLength / 255) * 100)

      if (isStart.value) {
        requestAnimationFrame(updateVolume)
      } else {
        volume.value = 0
      }
    }

    // 开始更新音量
    updateVolume()
  }
  
  // 暂停检测
  const stopVolumeCheck = () => {
    isStart.value = false
    analyser.value?.disconnect()
  }

  return {
    startVolumeCheck,
    stopVolumeCheck,
    volume,
    isStart,
  }
}

提示:在检测麦克风之前,需要获取麦克风权限,并且获取到你正在使用的麦克风

相关推荐
祈澈菇凉12 分钟前
如何结合使用thread-loader和cache-loader以获得最佳效果?
前端
垣宇15 分钟前
Vite 和 Webpack 的区别和选择
前端·webpack·node.js
java1234_小锋18 分钟前
一周学会Flask3 Python Web开发-客户端状态信息Cookie以及加密
前端·python·flask·flask3
化作繁星21 分钟前
如何在 React 中测试高阶组件?
前端·javascript·react.js
初遇你时动了情24 分钟前
react module.scss 避免全局冲突类似vue中scoped
vue.js·react.js·scss
Au_ust28 分钟前
千峰React:函数组件使用(2)
前端·javascript·react.js
爱吃南瓜的北瓜39 分钟前
npm install 卡在“sill idealTree buildDeps“
前端·npm·node.js
TTc_42 分钟前
记录首次安装远古时代所需的运行环境成功npm install --save-dev node-sass
前端·npm·sass
翻滚吧键盘1 小时前
npm使用了代理,但是代理软件已经关闭导致创建失败
前端·npm·node.js
烂蜻蜓1 小时前
Uniapp 设计思路全分享
前端·css·vue.js·uni-app·html