黑豹程序员-h5前端录音、播放

H5支持页面中调用录音机进行录音

H5加入录音组件,录音后可以进行播放,并形成录音文件,其采样率固化48000,传言是google浏览器的BUG,它无法改动采样率。

大BUG,目前主流的支持16000hz的采样率。

界面

录音组件

D:\workspace\vue\vzx-admin\src\components\Recorder\recorder.vue

cpp 复制代码
<template>
  <div>
    <button @click="startRecording" :disabled="isRecording">开始录音</button>&nbsp;
    <button @click="stopRecording" :disabled="!isRecording">停止录音</button>&nbsp;
    <el-checkbox size="small" checked="isplay">是否播放</el-checkbox>
  </div>
</template>

<script>
import axios from "axios";

export default {
  data() {
    return {
      mediaRecorder: null,
      isRecording: false,
      chunks: [],
      isplay: true
    };
  },
  methods: {
    async startRecording() {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      let track = stream.getAudioTracks()[0];

      //获取音频文件的信息
      console.log(track.getCapabilities());

      this.mediaRecorder = new MediaRecorder(stream);
      this.chunks = [];

      this.mediaRecorder.ondataavailable = (event) => {
        if (event.data.size > 0) {
          this.chunks.push(event.data);
        }
      };

      this.mediaRecorder.onstop = () => {
        const audioBlob = new Blob(this.chunks, { type: 'audio/wav' });
        const audioUrl = URL.createObjectURL(audioBlob);

        // ==在这里你可以处理录制完成的音频,比如播放或上传到服务器===========
        // 创建FormData对象
        let formData = new FormData();
        // 第一个参数是后台接收的文件参数名,第二个参数是blob数据,第三个参数是文件名
        formData.append('file', audioBlob, 'rd.wav');

        // 发送ajax请求
        axios.post('http://localhost:6070/basic/coursepic', formData, {
          headers: {
            'Content-Type': 'multipart/form-data'
          }
        }).then(response => {
          // 处理响应数据
          console.log(response)
        }).catch(error => {
          // 处理错误
          console.log(error)
        })

        //==播放=================
        if(this.isplay){
          var audio=document.createElement("audio");
          audio.controls=true;
          document.body.appendChild(audio);
          audio.src=audioUrl;
          audio.play(); //这样就能播放了
          audio.style.display = "none";

          //注意不用了时需要revokeObjectURL,否则霸占内存
          setTimeout(function(){ URL.revokeObjectURL(audio.src) },5000);
        }
      };

      this.mediaRecorder.start();
      this.isRecording = true;
    },
    stopRecording() {
      if (this.mediaRecorder && this.isRecording) {
        this.mediaRecorder.stop();
        this.isRecording = false;
      }
    },
  },
};
</script>

测试页面

cpp 复制代码
<template>
	<Recorder />
</template>

<script setup>
import Recorder from '../../components/Recorder/recorder.vue';

</script>

后台上传类 FileUploadController

H5会将用户的语音转成一个采样率48khz的wav文件(二进制流),配合SpringMVC的multipartFiles,就可以实现将音频文件上传保存。

注意目前H5的谷歌浏览器无法设置采样率,这是一个公开的bug,因为目前市场主流都使用16khz采样。如:科大讯飞语音识别只支持8k,16k,不支持48k。

下面是写好的一个图片上传的工具类,大家可以将就,我们的重点在h5录音,当然也可以稍加改造即可。

cpp 复制代码
package com.zx.basic.controller;

import com.zx.basic.service.FileUploadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

/**
 * @version v1.0 创建时间:16:22
 * @author: 作者:陈子枢
 * @web CSDN:https://blog.csdn.net/nutony
 * @description 描述:
 */
@RestController
@CrossOrigin
public class FileUploadController {
    @Autowired
    private FileUploadService fileUploadService;

    //上传课程图片
    @PostMapping("/basic/coursepic")
    public String coursePic(@RequestParam("file") MultipartFile[] multipartFiles) throws IOException {

        return fileUploadService.coursePic(multipartFiles);
    }
}
cpp 复制代码
package com.zx.basic.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.UUID;

/**
 * @version v1.0 创建时间:15:47
 * @author: 作者:陈子枢
 * @web CSDN:https://blog.csdn.net/nutony
 * @description 描述:文件上传的服务
 */
@Service
public class FileUploadService {
    @Value("${upload-web.dir}")
    private String dir;

    public String coursePic(MultipartFile[] multipartFile) throws IOException {
        /*
                上传图片文件:
                1. 不能覆盖之前的文件?           起新文件名:uuid,后缀?使用源文件的后缀
                2. 一个目录下不要太多的文件?      会按文件的年/月/日/时...来创建文件并存储
                C:\Users\nutony\Documents\WeChat Files\tony52399178\FileStorage\File\2023-09
         */
        String src = multipartFile[0].getOriginalFilename();
        String extName = src.substring(src.lastIndexOf("."));   //扩展名
        String newFilename = UUID.randomUUID() + extName;   //防止同名覆盖,防止多用户

        //相对路径
        String subDir = "/" + DateUtil.now().substring(0,10) + "/";

        //利于hutool工具类包产生当前时间,当前日期
        FileUtil.mkdir(dir + subDir);    //创建多级目录

        Files.write(Paths.get(dir + subDir + newFilename), multipartFile[0].getBytes());
        return subDir + newFilename;
    }
}
相关推荐
zengyuhan5035 小时前
Windows BLE 开发指南(Rust windows-rs)
前端·rust
醉方休5 小时前
Webpack loader 的执行机制
前端·webpack·rust
前端老宋Running5 小时前
一次从“卡顿地狱”到“丝般顺滑”的 React 搜索优化实战
前端·react.js·掘金日报
隔壁的大叔5 小时前
如何自己构建一个Markdown增量渲染器
前端·javascript
用户4445543654265 小时前
Android的自定义View
前端
WILLF5 小时前
HTML iframe 标签
前端·javascript
枫,为落叶6 小时前
Axios使用教程(一)
前端
小章鱼学前端6 小时前
2025 年最新 Fabric.js 实战:一个完整可上线的图片选区标注组件(含全部源码).
前端·vue.js
ohyeah6 小时前
JavaScript 词法作用域、作用域链与闭包:从代码看机制
前端·javascript
流星稍逝6 小时前
手搓一个简简单单进度条
前端