前端调用浏览器录音功能且生成文件(vue)

如果可以实现记得点赞分享,谢谢老铁~

首先在页面中给两个按钮,分别是"开始录音","结束录音"。以及录音成功后生成一个下载语音的链接。

1. 先看页面展示
html 复制代码
<template>
  <div>
    <button @click="startRecording" :disabled="isRecording">Start Recording</button>
    <button @click="stopRecording" :disabled="!isRecording">Stop Recording</button>
    <a v-if="downloadLink" :href="downloadLink" download="recording.pcm">Download Recording</a>
  </div>
</template>
2. 看vue3.0的代码实现
js 复制代码
<script setup>
import { ref, onBeforeUnmount } from 'vue';

const isRecording = ref(false);
const downloadLink = ref('');
let audioContext = null;
let processor = null;
let socket = null;
let mediaStream = null;
let audioChunks = [];
let silenceTimeout = null;
const silenceDelay = 2000; // 停止录音的延迟时间(毫秒)
const desiredSampleRate = 16000; // 期望的采样率为16kHz

const startRecording = async () => {
  try {
    mediaStream = await navigator.mediaDevices.getUserMedia({ audio: {
        sampleRate: desiredSampleRate,
        sampleSize: 16,
        channelCount: 1,
    } });
    audioContext = new (window.AudioContext || window.webkitAudioContext)({
        sampleRate: desiredSampleRate
    });
    const source = audioContext.createMediaStreamSource(mediaStream);
    processor = audioContext.createScriptProcessor(4096, 1, 1);

    source.connect(processor);
    processor.connect(audioContext.destination);
    socket = new WebSocket('ws://yourserver.com');
    socket.binaryType = 'arraybuffer';
    // 接收 WebSocket 消息
    socket.onmessage = (event) => {
      const receivedData = event.data;
      console.log('Received data from server:', receivedData);
      // 这里可以处理接收到的数据,例如显示在 UI 上
    };

    processor.onaudioprocess = processAudio;
    isRecording.value = true;
    audioChunks = []; // 清空之前的音频数据
  } catch (error) {
    console.error('Error accessing media devices.', error);
  }
};

const stopRecording = async () => {
  if (processor) {
    processor.disconnect();
  }
  if (mediaStream) {
    mediaStream.getTracks().forEach(track => track.stop());
  }
  if (audioContext && audioContext.state !== 'closed') {
    await audioContext.close();
    audioContext = null
  }
  if (socket) {
    socket.close();
  }
  isRecording.value = false;
  createDownloadLink();
};

const processAudio = (event) => {
  const inputBuffer = event.inputBuffer;
  const outputBuffer = new Float32Array(inputBuffer.length);
  inputBuffer.copyFromChannel(outputBuffer, 0);
  const pcmData = convertFloat32ToPCM(outputBuffer);

  // 检查音量是否为静音
  const isSilent = outputBuffer.every(sample => Math.abs(sample) < 0.01);
  if (!isSilent) {
    clearTimeout(silenceTimeout);
    silenceTimeout = setTimeout(() => stopRecording(), silenceDelay);
  }
  if (socket && socket.readyState === WebSocket.OPEN) {
    socket.send(pcmData);
  }

  audioChunks.push(pcmData);
};

const convertFloat32ToPCM = (input) => {
  const buffer = new ArrayBuffer(input.length * 2);
  const output = new DataView(buffer);
  for (let i = 0; i < input.length; i++) {
    const s = Math.max(-1, Math.min(1, input[i]));
    output.setInt16(i * 2, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
  }
  return buffer;
};

const createDownloadLink = () => {
  const blob = new Blob(audioChunks, { type: 'application/octet-stream' });
  downloadLink.value = URL.createObjectURL(blob);
};

onBeforeUnmount(() => {
  stopRecording();
});
</script>
解释

audioChunks 数组:

存储录音过程中的 PCM 数据块。

processAudio 方法:

将 PCM 数据块添加到 audioChunks 数组中。

stopRecording 方法:

停止录音,并调用 createDownloadLink 方法生成下载链接。

createDownloadLink 方法:

将存储的音频数据块创建为一个 Blob 对象,并生成一个下载链接。

downloadLink 变量:

存储生成的下载链接,供用户下载录音文件。

注意事项

确保WebSocket服务器可以处理PCM数据。

处理音频数据时,注意性能问题,避免阻塞主线程。

Web Audio API和WebSocket在不同浏览器上的实现可能会有所不同,确保在目标浏览器上测试。

OK,收工!如果可以实现记得点赞分享,谢谢老铁~

相关推荐
Мартин.3 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
一 乐4 小时前
学籍管理平台|在线学籍管理平台系统|基于Springboot+VUE的在线学籍管理平台系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·学习
昨天;明天。今天。4 小时前
案例-表白墙简单实现
前端·javascript·css
数云界4 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd4 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome
安冬的码畜日常4 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine
ChinaDragonDreamer4 小时前
Vite:为什么选 Vite
前端
小御姐@stella4 小时前
Vue 之组件插槽Slot用法(组件间通信一种方式)
前端·javascript·vue.js
GISer_Jing4 小时前
【React】增量传输与渲染
前端·javascript·面试
eHackyd4 小时前
前端知识汇总(持续更新)
前端