使用 waversurfer 开发波普图音频录制组件

284 阅读1分钟

开发需求:实现音频波谱展示音频录制过程。

需求分析:

  1. 音频录制获取录制权限,判断是否有麦克风可用,可选择麦克风
  2. 音频录制按钮控制
  3. 录制时长显示
  4. 波谱展示
  5. 导出录制音频

波普图设计搞.png

实现:使用 waversurfer.js 以及插件 RecordPlugin

安装 waversurfer.js

npm install --save wavesurfer.js

导入 waversuefer.jsRecordPlugin

import WaveSurfer from 'wavesurfer.js'
import RecordPlugin from 'wavesurfer.js/dist/plugins/record.esm.js';

模版示例

image.png

<template>
  <div class="recorder">
    <div ref="mic"></div>  //展示录制时波普图
    <div class="buttonWrapper">  // 按钮组
      <div class="flex items-center">
        <button id="record" @click="recButton">{{ recButtontext }}</button>
        //如有需要可加入暂停按钮
        <!-- <button id="pause" @click="onPause">{{ pauseButtonText }}</button> --> 
        <p id="progress" class="text-[0.715rem]">{{ progressText }}</p>
      </div>
      <select id="mic-select" v-model="currentDevice">
        <option :value="device.value" v-for="device of options">{{ device.text }}</option>
      </select>
    </div>
  </div>
</template>

获取麦克风设备列表

const currentDevice = ref('');
const options = ref([]);
RecordPlugin.getAvailableAudioDevices().then((devices) => {
  devices.forEach((device) => {
    let option = {};
    option.value = device.deviceId;
    option.text = device.label || device.deviceId;
    options.value.push(option);
  });
  currentDevice.value = options.value[0].value; // 默认选择第一支麦克风
});

录制时更新时间进度

const progressText = ref('00:00');
const updateProgress = (time) => {
  // time will be in milliseconds, convert it to mm:ss format
  const formattedTime = [
    Math.floor((time % 3600000) / 60000), // minutes
    Math.floor((time % 60000) / 1000), // seconds
  ]
    .map((v) => (v < 10 ? '0' + v : v))
    .join(':');
  progressText.value = formattedTime;
};

录制方法

//开始录制后,按钮变更为结束按钮
const recButton = () => {
  if (record.isRecording() || record.isPaused()) {
    record.stopRecording()
    recButtontext.value = `⏺${t('录制')}`;
    // pauseButtonText.value = `⏸${t('暂停')}`;
    return;
  }

  // 通过已选择的设备录制
  const deviceId = currentDevice.value;
  record.startRecording({ deviceId }).then(() => {
    recButtontext.value = `🛑${t('结束')}`;
  });
};

创建 waversurfer 实例

const createWaveSurfer = () => {
  recButtontext.value = `⏺${t('录制')}`;
  if (wavesurfer) {
    wavesurfer.destroy();
  }
  wavesurfer = WaveSurfer.create({
    container: mic.value,
    waveColor: '#003ff6',
    progressColor: 'rgb(100, 0, 100)',
  });

  // 初始化音频录制插件
  record = wavesurfer.registerPlugin(
    RecordPlugin.create({
      scrollingWaveform: false,
      renderRecordedAudio: false,
      // mimeType: 'audio/wav' // 设置录音格式为 WAV
    })
  );
  // 录制结束将 blob emit出去
  record.on('record-end', (blob) => {
    emit('handle-audio-blob', blob);
  });
  
  //录制过程中更新进度
  record.on('record-progress', (time) => {
    updateProgress(time);
  });
};

注意点:音频录制需要 HTTPS 环境,开发测试时使用 localhost:端口号,测试环境可配置浏览器设置edge://flags/#unsafely-treat-insecure-origin-as-securechrome://flags/#unsafely-treat-insecure-origin-as-secure 启用

image.png