zl程序教程

您现在的位置是:首页 >  Java

当前栏目

音量检测

2023-02-18 16:41:21 时间

写作背景:

在一些在线会议软件、通讯软件中尤其是头一次使用麦克风设备,当电脑中存在多个麦克风设备的时候,往往初始的设备有可能并不是我们想使用的,或者有时候设备故障的时候也需要通过音量的检测来进行判断。我们可以通过音量条的显示来反馈当前设备是否正常工作。

在 HTML5 中提供的 AudioContext 对象用来专门处理音频,通过上下文创建的各种 AudioNode 相互链接。

模板定义:

提供一个启动麦克风的按钮事件和一个用来显示音量的 div 元素,通过动态改变元素的宽度来实时显示。

<template>
  <h2>音量检测</h2>
  <a-divider />
  <a-button @click="openMicrophone">打开麦克风</a-button>
  <div
    :style="{
      width: `${audioLevel}px`,
      height: '10px',
      background: '#8dc63f',
      marginTop: '20px',
    }"
  ></div>
</template>

启动麦克风和检测:

实例化 SoundMeter ,并注册监听来回调音量数据:

soundMeter.value = new SoundMeter(
    new window.AudioContext(),
    (instant: number) => {
      audioLevel.value = Number(instant.toFixed(2)) * 348 + 1;
    }
);

通过 getUserMedia 设置允许音频的约束来启动麦克风,并对接检测工具:

const constraints: MediaStreamConstraints = { audio: true, video: false };
  navigator.mediaDevices
    .getUserMedia(constraints)
    .then((stream: MediaStream) => {
      soundMeter.value?.connectToSource(stream);
    })
  .catch(handleError);

当组件卸载后我们需要停掉检测音量的工具类:

onUnmounted(() => {
  soundMeter.value?.stop();
});

检测音量工具类:

在工具类中通过 onaudioprocess 来实时回调音量的数据,通过计算来得到一个适用于显示的数值。

export default class SoundMeter {
  mic: MediaStreamAudioSourceNode | undefined;
  script: ScriptProcessorNode;
  context: AudioContext;
  constructor(context: AudioContext, onAudioProcess: Function) {
    this.context = context;
    this.script = context.createScriptProcessor(2048, 1, 1);
    this.script.onaudioprocess = function (event) {
      let input = event.inputBuffer.getChannelData(0) || 0;
      let sum = 0.0;
      for (let i = 0; i < input.length; ++i) {
        sum += input[i] * input[i];
      }
      onAudioProcess &amp;&amp; onAudioProcess(Math.sqrt(sum / input.length));
    };
  }

  connectToSource(stream: MediaStream) {
    this.mic = this.context.createMediaStreamSource(stream);
    this.mic.connect(this.script);
    // necessary to make sample run, but should not be.
    this.script.connect(this.context.destination);
  }

  stop() {
    this.mic &amp;&amp; this.mic.disconnect();
    this.script &amp;&amp; this.script.disconnect();
  }
}

结语:

这一篇通过一个案例完成了音量的显示和检测音量的变化,明天继续学~