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

背景

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

于是就想看看有没有更专业的库来处理波形和播放控制,最后发现了 wavesurfer.js

一个专门做音频可视化和播放控制的轻量库,试了一下发现效果很不错,功能简洁,扩展性强。

需求

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

实现效果

wavesurfer 安装与引入

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

完整代码

javascript 复制代码
<template>
  <div class="app-container">
    <div
      class="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}`;
    },
    // 初始化 WaveSurfer
    initWaveform(url) {
      // 销毁已有实例
      if (this.wavesurfer) {
        this.wavesurfer.destroy();
        this.wavesurfer = null;
      }

      // 初始化 WaveSurfer
      this.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>
相关推荐
蝉蜕日记9 小时前
视频压缩 v1.1.31:高效压缩,无损画质,释放存储空间
音视频·生活·视频编解码·视频·软件需求
lumengabc10 小时前
视频制作流程MP4旁白语音生成裁剪视频压缩python处理ppt转视频M4a格式
音视频
音视频牛哥13 小时前
AI浪潮下,实时音视频SDK正在经历怎样的价值重构?
人工智能·音视频·实时音视频·rtmp推流·低延迟rtsp播放器·低延迟rtmp播放器·rtsp转rtmp推流
乐橙开放平台13 小时前
明厨亮灶笔记:乐橙轻应用 H5 + 小程序插件,一套 BFF 出两张播放凭证
人工智能·笔记·物联网·小程序·音视频·notepad++
ofoxcoding14 小时前
Seedance 2.0 与 Wan 2026 视频生成 API 成本效率深度对比分析
网络·人工智能·ai·音视频
xingyuzhisuan14 小时前
星宇智算 AI 视频生成工具九维度全测评与行业对标分析
人工智能·音视频
豌豆学姐15 小时前
likeadmin-api 视频生成工作流实战:Seedance 2.0 接口从素材到任务查询
aigc·音视频·api·视频生成·likeadmin-api
乐橙开放平台15 小时前
养殖 SaaS 笔记:乐橙 IoT 物模型管环境,视频 OpenAPI 管回看
数据库·笔记·物联网·mysql·音视频
山顶夕景1 天前
【MAE】音频自监督训练Masked Autoencoders that Listen
音视频·ssl·多模态·自监督·mae
小码哥0681 天前
短视频后台系统架构设计与行业应用深度分析-源码-技术支持
系统架构·音视频·短视频后台·短剧后台·微剧后台