前端录入音频并上传

2023-09-18 16:59:00

纯 js 实现(有问题)

上传音频文件时 blob 数据中 size 一直是0,导致上传之后音频不可播放(本地录制后本地是可以播放的)在这里插入图片描述

<template>
  <div>
    <button v-if="!isRecording" @click="startRecording">开始录音</button>
    <button v-else @click="stopRecording">停止录音</button>
    <audio v-show="recordedAudio" ref="audioPlayer" controls></audio>
    <!-- <audio src="./法老-百变酒精.mp3" controls></audio> -->
  </div>
</template>

<script>
import { UploadOssFiles } from '@/api/service'

export default {
  data() {
    return {
      isRecording: false,
      recordedAudio: null,
      mediaRecorder: null,
      chunks: []
    }
  },
  methods: {
    startRecording() {
      navigator.mediaDevices
        .getUserMedia({ audio: true })
        .then((stream) => {
          this.isRecording = true
          this.mediaRecorder = new MediaRecorder(stream)
          this.mediaRecorder.addEventListener('dataavailable', this.handleDataAvailable)
          this.mediaRecorder.start()
        })
        .catch((error) => {
          console.error('无法访问麦克风:', error)
        })
    },
    stopRecording() {
      this.isRecording = false
      this.mediaRecorder.stop()
      // this.mediaRecorder.state = 'inactive'

      const blob = new Blob(this.chunks, { type: 'audio/webm' })
      // const blob = new Blob(this.chunks, { type: 'audio/mp3' })
      console.log('blob----', blob)
      const formData = new FormData()
      // formData.append('audio', blob, 'recording.webm')
      formData.append('files', blob, 'recording.webm')
      // formData.append('files', blob, 'recording.mp3')
      // 发送音频数据到后端的API接口
      UploadOssFiles(formData)
        .then((response) => {
          // 处理后端返回的响应
        })
        .catch((error) => {
          // 处理请求错误
        })
    },
    handleDataAvailable(event) {
      this.chunks.push(event.data)
      if (this.mediaRecorder.state === 'inactive') {
        this.processRecordedAudio()
      }
    },
    processRecordedAudio() {
      const blob = new Blob(this.chunks, { type: 'audio/webm' })
      // const blob = new Blob(this.chunks, { type: 'audio/mp3' })
      this.recordedAudio = URL.createObjectURL(blob)
      console.log('this.recordedAudio----', this.recordedAudio)
      this.$refs.audioPlayer.src = this.recordedAudio
    }
  }
}
</script>

代码来源

使用插件 recorder-core (没问题)

在这里插入图片描述

<template>
  <div>
    <!-- 按钮 -->
    <button @click="recOpen">打开录音,请求权限</button>
    | <button @click="recStart">开始录音</button> | <button @click="recStop">结束录音</button> |
    <button @click="recPlay">本地试听</button>
    <div style="padding-top: 5px">
      <!-- 波形绘制区域 -->
      <div style="border: 1px solid #ccc; display: inline-block; vertical-align: bottom">
        <div ref="recwave" style="height: 100px; width: 300px" />
      </div>
    </div>
  </div>
</template>

<script>
import { UploadOssFiles } from '@/api/service'

// 必须引入的核心
import Recorder from 'recorder-core'

// 引入mp3格式支持文件;如果需要多个格式支持,把这些格式的编码引擎js文件放到后面统统引入进来即可
import 'recorder-core/src/engine/mp3'
import 'recorder-core/src/engine/mp3-engine'
// 录制wav格式的用这一句就行
// import 'recorder-core/src/engine/wav'

// 可选的插件支持项,这个是波形可视化插件
import 'recorder-core/src/extensions/waveview'

// ts import 提示:npm包内已自带了.d.ts声明文件(不过是any类型)

export default {
  name: '',
  components: {},

  data() {
    return {
      rec: null,
      recBlob: null,
      wave: null
    }
  },

  methods: {
    // 申请录音权限
    recOpen() {
      // 创建录音对象
      this.rec = Recorder({
        type: 'mp3', // 录音格式,可以换成wav等其他格式
        sampleRate: 16000, // 录音的采样率,越大细节越丰富越细腻
        bitRate: 16, // 录音的比特率,越大音质越好
        onProcess: (
          buffers,
          powerLevel,
          bufferDuration,
          bufferSampleRate,
          newBufferIdx,
          asyncEnd
        ) => {
          // 录音实时回调,大约1秒调用12次本回调
          // 可实时绘制波形,实时上传(发送)数据
          if (this.wave) this.wave.input(buffers[buffers.length - 1], powerLevel, bufferSampleRate)
        }
      })

      // 打开录音,获得权限
      this.rec.open(
        () => {
          console.log('录音已打开')
          if (this.$refs.recwave) {
            // 创建音频可视化图形绘制对象
            this.wave = Recorder.WaveView({ elem: this.$refs.recwave })
          }
        },
        (msg, isUserNotAllow) => {
          // 用户拒绝了录音权限,或者浏览器不支持录音
          console.log((isUserNotAllow ? 'UserNotAllow,' : '') + '无法录音:' + msg)
        }
      )
    },
    // 开始录音
    recStart() {
      if (!this.rec) {
        console.error('未打开录音')
        return
      }
      this.rec.start()
      console.log('已开始录音')
    },
    // 结束录音
    recStop() {
      if (!this.rec) {
        console.error('未打开录音')
        return
      }
      this.rec.stop(
        (blob, duration) => {
          // blob就是我们要的录音文件对象,可以上传,或者本地播放
          this.recBlob = blob
          // 简单利用URL生成本地文件地址,此地址只能本地使用,比如赋值给audio.src进行播放,赋值给a.href然后a.click()进行下载(a需提供download="xxx.mp3"属性)
          var localUrl = (window.URL || webkitURL).createObjectURL(blob)
          console.log('录音成功', blob, localUrl, '时长:' + duration + 'ms')

          this.upload(blob) // 把blob文件上传到服务器

          this.rec.close() // 关闭录音,释放录音资源,当然可以不释放,后面可以连续调用start
          this.rec = null
        },
        (err) => {
          console.error('结束录音出错:' + err)
          this.rec.close() // 关闭录音,释放录音资源,当然可以不释放,后面可以连续调用start
          this.rec = null
        }
      )
    },
    // 上传录音
    upload(blob) {
      console.log('blob----', blob)
      // 使用FormData用multipart/form-data表单上传文件
      // 或者将blob文件用FileReader转成base64纯文本编码,使用普通application/x-www-form-urlencoded表单上传
      var form = new FormData()
      form.append('files', blob, 'recorder.mp3') // 和普通form表单并无二致,后端接收到upfile参数的文件,文件名为recorder.mp3

      UploadOssFiles(form)
        .then((response) => {
          // 处理后端返回的响应
        })
        .catch((error) => {
          // 处理请求错误
        })
    },
    // 本地播放录音
    recPlay() {
      // 本地播放录音试听,可以直接用URL把blob转换成本地播放地址,用audio进行播放
      var localUrl = URL.createObjectURL(this.recBlob)
      var audio = document.createElement('audio')
      audio.controls = true
      document.body.appendChild(audio)
      audio.src = localUrl
      audio.play() // 这样就能播放了

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

<style lang='scss' scoped>
</style>

代码来源

更多推荐

道可云元宇宙每日资讯|首届报业传媒元宇宙应用大会在青岛开幕

道可云元宇宙每日简报(2023年9月22日)讯,今日元宇宙新鲜事有:元宇宙与人工智能时代的出版与阅读研讨会举行由中国新闻出版研究院元宇宙出版与阅读实验室、北京印刷学院数字出版前沿技术应用创新联合实验室主办的元宇宙与人工智能时代的出版与阅读研讨会今天在敦煌举行。与会嘉宾围绕通用人工智能在出版行业应用现状与发展方向、元宇宙

思腾云计算

思腾合力(SITONHOLY)是AI服务器与HPC基础架构解决方案商,作为NVIDIA精英级别的合作伙伴,一直专注于人工智能领域。思腾合力拥有自主品牌GPU服务器及通用X86服务器,适用于深度学习训练及推理等场景,覆盖服务器、静音工作站等多种产品形态。在人工智能硬件领域深耕的同时,也在软件领域不断探索发展,独立开发的S

Java日志

加油,新时代打工人!一、日志分级最开始的日志分级是由Syslog的开发者EricAllman在1981年提出的。之后,这个级别分级系统被广泛应用于各种领域的日志记录和信息处理中。下面我们就来介绍下常用的日志等级TRACE;是最低级别的日志记录,用于输出最详细的调试信息,通常用于开发调试目的。在生产环境中,应该关闭TRA

SG-Former实战:使用SG-Former实现图像分类任务(一)

摘要SG-Former是一种新型的Transformer模型,它被提出以降低视觉Transformer的计算成本,同时保持其优秀的性能表现。计算成本的降低使得SG-Former能够更有效地处理大规模的特征映射,从而提高了模型的效率和全局感知能力。SG-Former的核心思想是利用显著性图来引导Transformer模型

leetcode 236.二叉树的最近公共祖先

⭐️题目描述🌟leetcode链接:二叉树的最近公共祖先思路1:依次遍历每一个结点,遍历到当前根结点,再继续递归找p是否存在左子树q是否存在右子树,若p在左子树q在右子树或者q在左子树p在右子树,说明当前root就是qp的公共祖先,若当前结点找不到这种情况,则当前root转换为子问题root->leftroot->r

343. 整数拆分

题目:343.整数拆分给定一个正整数n,将其拆分为k个正整数的和(k>=2),并使这些整数的乘积最大化。返回你可以获得的最大乘积。示例1:输入:n=2输出:1解释:2=1+1,1×1=1。示例2:输入:n=10输出:36解释:10=3+3+4,3×3×4=36。提示:2<=n<=58思考历程与知识点:看到这道题目,都会

信息化发展44

智能运维1、中国电子工业标准化技术协会发布的团体标准I/CESA1172《信息技术服务智能运维通用要求》,给出了智能运维能力框架,包括组织治理、智能特征、智能运维场景实现、能力域和能力要素,其中能力要素是构建智能运维能力的基础。2、组织通过场景分析、场景构建、场景交付和效果评估四个过程,基于数据管理能力域提供的高质量数

关于mysql已有主从环境得主从重配置

恢复主从环境1:Situation(背景)2:Task(任务)3:Action(行动)主库(备份)1:锁表2:效验是否锁表3:查看主库状态并记录4:备份数据库全部5:解锁表6:把备份放到从库从库1:备份从库(可选)2:恢复从库3:清除旧设置4:添加新设置4:Result(结果)1:Situation(背景)测试环境下得

片内互联中常用的拓扑结构

主要的拓扑结构有星型(Star)、交叉(Crossbar)、总线(Bus)、环型(Ring)和网格(Mesh)等。星型(Star)结构,主控处理器放在中心位置,其他各个模块均与其连接,而模块彼此之间并不直接交互,必须通过主控中转,结构如图1所示。这种结构简单高效,在早期片内模块数量较少、结构单一时经常被使用。但随着多核

9.21数电(加法器&状态机&独热编码)

加法半加器一位,分为两部分,一个是进位,一个是单位上的和进位采取与门,单位上的和用异或门全加器进位数就是三个数进行加和,通过与门,就是两两过与门描述每位的和项就是,只去描述那个1的情况,即三中有一个,或者三个都为1分解全加器行波进位加法器快速加法器是说下一位的进位=此位的两个加数再加上来自上位的进数当此位的两个加数均为

如何恢复U盘里面的已经损坏的数据?

弹出使用驱动器之前,先将U盘格式化的信息框,是Windows系统针对某些特定类型的U盘或移动硬盘的一种常见处理方式。一般来说,如果U盘或移动硬盘出现某些故障或问题,Windows系统会建议用户将其格式化。格式化是一种常规的操作,它能使U盘或移动硬盘恢复到初始状态,但需要注意的是,格式化操作将会清除所有存储在U盘或移动硬

热文推荐