当前位置: 首页 > news >正文

vue2使用WaveSurfer实现简易的音频播放

背景

最近在维护一个 Vue2 的后台管理系统,需要在 PC 端播放移动端上传的录音文件MP3,一开始我尝试使用原生的 标签来实现,但在拖动进度条时,音频总时长会异常变化,播放体验很差。

于是就想看看有没有更专业的库来处理波形和播放控制,最后发现了 wavesurfer.js
一个专门做音频可视化和播放控制的轻量库,试了一下发现效果很不错,功能简洁,扩展性强。

需求

  1. 在后台页面播放移动端录音
  2. 可视化波形,支持点击进度跳转
  3. 显示 播放进度/总时长
  4. 支持 播放速度调节
  5. 支持 播放 / 暂停 / 停止

实现效果

实现效果

wavesurfer 安装与引入

npm install wavesurfer
# 或者
yarn add wavesurfer
# 在 Vue2 组件中引入:
import WaveSurfer from "wavesurfer";

完整代码

<template><div class="app-container"><divclass="audio-container"style="display: flex; align-items: center; gap: 12px; width: 100%;"v-show="showAudio"><!-- 波形图 --><div ref="waveform" style="flex: 1; height: 80px;"></div><!-- 播放时间 --><span style="white-space: nowrap;">{{ formatTime(currentTime) }} / {{ formatTime(duration) }}</span><!-- 播放速度 --><div style="display: flex; align-items: center; gap: 4px;"><label>播放速度:</label><el-select v-model="speed" @change="changeSpeed" style="width: 70px;"><el-option v-for="s in speeds" :key="s" :value="s">{{ s }}x</el-option></el-select></div><!-- 播放/暂停/关闭按钮 --><div style="display: flex; align-items: center; gap: 8px;"><el-button type="primary" @click="playAudio">播放</el-button><el-button type="warning" @click="pauseAudio">暂停</el-button><el-button type="default" @click="stopAudio">关闭</el-button></div></div></div>
</template><script>
import WaveSurfer from "wavesurfer";
export default {name: "soundRecording",data() {return {wavesurfer: null,showAudio: false,palyAudioUrl: "",currentTime: 0,duration: 0,speed: 1,speeds: [0.5, 0.75, 1, 1.25, 1.5, 2]};},methods: {// 格式化时间formatTime(seconds) {const m = Math.floor(seconds / 60).toString().padStart(2, "0");const s = Math.floor(seconds % 60).toString().padStart(2, "0");return `${m}:${s}`;},// 初始化 WaveSurferinitWaveform(url) {// 销毁已有实例if (this.wavesurfer) {this.wavesurfer.destroy();this.wavesurfer = null;}// 初始化 WaveSurferthis.wavesurfer = WaveSurfer.create({container: this.$refs.waveform,waveColor: "#A8DBA8",progressColor: "#3B8686",height: 80,responsive: true});// 监听加载完成this.wavesurfer.on("ready", () => {this.duration = this.wavesurfer.getDuration();this.wavesurfer.setPlaybackRate(this.speed);// 🔹 音频加载完成后再播放this.wavesurfer.play();});// 更新播放时间this.wavesurfer.on("audioprocess", () => {this.currentTime = this.wavesurfer.getCurrentTime();});// 播放结束this.wavesurfer.on("finish", () => {this.currentTime = 0;});// 监听用户点击波形图进度this.wavesurfer.on("seek", progress => {// progress 是 0~1 的比例,转换成秒this.currentTime = progress * this.wavesurfer.getDuration();});// 加载音频this.wavesurfer.load(url);this.playAudio();},// 初始化播放录音,传入录音数据playRecording(row) {this.showAudio = true;let url = row.blob ? URL.createObjectURL(row.blob) : row.url;this.audioUrl = url;this.initWaveform(url);},// 播放音频playAudio() {if (this.wavesurfer) this.wavesurfer.play();},// 暂停音频pauseAudio() {if (this.wavesurfer) this.wavesurfer.pause();},// 关闭音频stopAudio() {if (this.wavesurfer) {this.wavesurfer.stop();this.currentTime = 0;}this.showAudio = false;},// 改变播放速度changeSpeed() {if (this.wavesurfer) this.wavesurfer.setPlaybackRate(this.speed);}},mounted() {//初始化音频链接,可以通过点击获取音频链接再进行赋值,只有一个音频的话,也可以这样初始化this.playRecording({url:'https://xxx.com/example.mp3',//更换真实的mp3音频链接});}
};
</script>
http://www.dtcms.com/a/349613.html

相关文章:

  • 波音787项目:AR技术重塑航空制造的数字化转型
  • 用MessageBus优化模块通信:实现订阅/发布模式
  • nmcli命令详解
  • 文吃透朴素贝叶斯:从原理到实战
  • 【python文件处理】使用 open() 函数打开文件、 File 操作文件、使用 OS 对象操作文件目录的知识,使用 open() 函数打开文件
  • DMP-Net:面向脑组织术中成像的深度语义先验压缩光谱重建方法|文献速递-深度学习人工智能医疗图像
  • Android进入Activity时闪黑生命周期销毁并重建
  • 集成电路学习:什么是Caffe深度学习框架
  • 强化学习核心概念与算法详解-马尔可夫决策过程(MDP)+贝尔曼方程(Bellman Equation)
  • 合同管理软件的主要功能有什么?
  • 朴素贝叶斯学习笔记:从原理到实战(J享)
  • (LeetCode 每日一题) 498. 对角线遍历 (矩阵、模拟)
  • SSM从入门到实战:3.2 SpringMVC请求处理与控制器
  • 《C++哈希表:高效数据存储与检索的核心技术》
  • 朴素贝叶斯算法学习总结
  • MySQL 磁盘和 Redis 内存
  • 无人机航拍数据集|第22期 无人机城市交通目标检测YOLO数据集8624张yolov11/yolov8/yolov5可训练
  • Coze用户账号设置修改用户头像-前端源码
  • 【ACP】2025-最新-疑难题解析-5
  • Python Day 33 JavaScript BOM 与 DOM 核心笔记整合
  • 【数学建模】如何总结数学建模中的层次分析法最好
  • 通过Fiddler肆意修改接口返回数据进行测试
  • EXCEL自动调整列宽适应A4 A3 A2
  • OpenCV计算机视觉实战(21)——模板匹配详解
  • 将盾CDN:高防CDN和游戏盾有什么区别?
  • 宋红康 JVM 笔记 Day07|本地方法接口、本地方法栈
  • More Effective C++ 条款08:理解各种不同意义的new和delete
  • Genymotion 虚拟机如何安装 APK?(ARM 插件安装教程)
  • (操作系统)死锁是什么 必要条件 解决方式
  • 5分钟发布技术博客:cpolar简化Docsify远程协作流程