【wavesurfer.js实战范例】多区域音频标注(含区域实时切换显示)

简介: 【wavesurfer.js实战范例】多区域音频标注(含区域实时切换显示)

通过多选框,实现多区域显示的实时切换,实现原理:

  1. 每次切换时先清除所有区域
  2. 对选中区域进行重绘
<template>
  <div style="padding: 30px">
    <el-row type="flex" justify="center">
      <el-checkbox-group v-model="showList" @change="showListChange">
        <el-checkbox
          v-for="(regionInfo, regionKey) in regionDic"
          :label="regionKey"
          :key="'region' + regionKey"
        >
          <div class="colorTag" :style="{ background: regionInfo.color }"></div>
          {{ regionInfo.label }}</el-checkbox
        >
      </el-checkbox-group>
    </el-row>
    <div class="waveBox" ref="wave_Ref"></div>
  </div>
</template>

<script>
import WaveSurfer from "wavesurfer.js";
// 导入插件--区域
import RegionsPlugin from "wavesurfer.js/dist/plugin/wavesurfer.regions.min.js";
// 导入插件--指针轴
import CursorPlugin from "wavesurfer.js/dist/plugin/wavesurfer.cursor.js";

export default {
  data() {
    return {
      showList: ["1", "2", "3", "4", "5"],
      wavesurfer: null,
      regionDic: {
        1: {
          label: "前奏",
          color: "rgba(255, 255, 0, 0.5)",
          dataMark: "preludeList",
        },
        2: {
          label: "男声",
          color: "rgba(0, 0, 255, 0.5)",
          dataMark: "boyVoiceList",
        },
        3: {
          label: "女声",
          color: "rgba(255, 0, 0, 0.5)",
          dataMark: "girlVoiceList",
        },
        4: {
          label: "男/女合唱",
          color: "rgba(0, 255, 255, 0.5)",
          dataMark: "chorusList",
        },
        5: {
          label: "间奏",
          color: "rgba(255, 0, 255, 0.5)",
          dataMark: "interludeList",
        },
      },

      boyVoiceList: [
        {
          start: 14,
          end: 26,
        },
        {
          start: 59,
          end: 64,
        },
        {
          start: 109,
          end: 134,
        },
        {
          start: 148,
          end: 160,
        },
      ],

      girlVoiceList: [
        {
          start: 27,
          end: 39,
        },
        {
          start: 52,
          end: 58,
        },
      ],

      preludeList: [
        {
          start: 0,
          end: 14,
        },
      ],

      // 男女合唱
      chorusList: [
        {
          start: 40,
          end: 52,
        },
        {
          start: 65,
          end: 71,
        },
        {
          start: 97,
          end: 109,
        },
        {
          start: 135,
          end: 147,
        },
        {
          start: 161,
          end: 173,
        },
      ],
      // 间奏
      interludeList: [
        {
          start: 72,
          end: 96,
        },
      ],
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.wavesurfer = WaveSurfer.create({
        container: this.$refs.wave_Ref,
        plugins: [
          // 插件--区域的配置
          RegionsPlugin.create({}),

          // 插件--指针轴的配置
          CursorPlugin.create({
            showTime: true,
            opacity: 1,
            customShowTimeStyle: {
              "background-color": "#000",
              color: "#fff",
              padding: "2px",
              "font-size": "10px",
            },
          }),
        ],
      });
      this.wavesurfer.load(require("./《祝福你》群星_粤语.mp3"));
      // 自动播放
      let that = this;
      this.wavesurfer.on("ready", function () {
        that.wavesurfer.play();
      });
      this.drawRegion();
    });
  },
  methods: {
    showListChange() {
      this.wavesurfer.clearRegions();
      this.drawRegion();
    },
    wavesurferAddRegion(start, end, color) {
      this.wavesurfer.addRegion({
        start: start, // 区域开始时间
        end: end, // 区域结束时间
        color: color, // 区域颜色
        drag: false, // 是否可拖拽
        resize: false, // 是否可改变大小
      });
    },
    drawRegion() {
      this.showList.forEach((regionType) => {
        let regionInfo = this.regionDic[regionType];
        this[regionInfo.dataMark].forEach((item) => {
          this.wavesurferAddRegion(item.start, item.end, regionInfo.color);
        });
      });
    },
  },
};
</script>
<style scoped>
.colorTag {
  display: inline-block;
  height: 10px;
  width: 30px;
}
.waveBox {
  border: 1px solid gray;
  margin-top: 15px;
}
</style>
目录
相关文章
|
5月前
|
人工智能 自然语言处理 JavaScript
通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
通义灵码基于自然语言需求,快速生成完整Vue组件。例如,用Vue 2和JavaScript实现贪吃蛇游戏:包含键盘控制、得分系统、游戏结束判定与Canvas动态渲染。AI生成的代码符合规范,支持响应式数据与事件监听,还能进阶优化(如增加启停按钮、速度随分数提升)。传统需1小时的工作量,使用通义灵码仅10分钟完成,大幅提升开发效率。操作简单:安装插件、输入需求、运行项目即可实现功能。
259 4
 通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
|
19天前
|
JavaScript 前端开发 安全
【逆向】Python 调用 JS 代码实战:使用 pyexecjs 与 Node.js 无缝衔接
本文介绍了如何使用 Python 的轻量级库 `pyexecjs` 调用 JavaScript 代码,并结合 Node.js 实现完整的执行流程。内容涵盖环境搭建、基本使用、常见问题解决方案及爬虫逆向分析中的实战技巧,帮助开发者在 Python 中高效处理 JS 逻辑。
|
3月前
|
JavaScript 前端开发 算法
流量分发代码实战|学会用JS控制用户访问路径
流量分发工具(Traffic Distributor),又称跳转器或负载均衡器,可通过JavaScript按预设规则将用户随机引导至不同网站,适用于SEO优化、广告投放、A/B测试等场景。本文分享一段不到百行的JS代码,实现智能、隐蔽的流量控制,并附完整示例与算法解析。
95 1
|
7月前
|
监控 JavaScript 前端开发
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
MutationObserver 是一个非常强大的 API,提供了一种高效、灵活的方式来监听和响应 DOM 变化。它解决了传统 DOM 事件监听器的诸多局限性,通过异步、批量的方式处理 DOM 变化,大大提高了性能和效率。在实际开发中,合理使用 MutationObserver 可以帮助我们更好地控制 DOM 操作,提高代码的健壮性和可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
|
监控 安全 中间件
Next.js 实战 (十):中间件的魅力,打造更快更安全的应用
这篇文章介绍了什么是Next.js中的中间件以及其应用场景。中间件可以用于处理每个传入请求,比如实现日志记录、身份验证、重定向、CORS配置等功能。文章还提供了一个身份验证中间件的示例代码,以及如何使用限流中间件来限制同一IP地址的请求次数。中间件相当于一个构建模块,能够简化HTTP请求的预处理和后处理,提高代码的可维护性,有助于创建快速、安全和用户友好的Web体验。
204 0
Next.js 实战 (十):中间件的魅力,打造更快更安全的应用
|
中间件 API
Next.js 实战 (八):使用 Lodash 打包构建产生的“坑”?
这篇文章介绍了作者在使用Nextjs15进行项目开发时遇到的部署问题。在部署过程中,作者遇到了打包构建时的一系列报错,报错内容涉及动态代码评估在Edge运行时不被允许等问题。经过一天的尝试和调整,作者最终删除了lodash-es库,并将radash的部分源码复制到本地,解决了打包报错的问题。文章最后提供了项目的线上预览地址,并欢迎读者留言讨论更好的解决方案。
231 0
Next.js 实战 (八):使用 Lodash 打包构建产生的“坑”?
|
设计模式 数据安全/隐私保护
Next.js 实战 (七):浅谈 Layout 布局的嵌套设计模式
这篇文章介绍了在Next.js框架下,如何处理中后台管理系统中特殊页面(如登录页)不包裹根布局(RootLayout)的问题。作者指出Next.js的设计理念是通过布局的嵌套来创建复杂的页面结构,这虽然保持了代码的整洁和可维护性,但对于特殊页面来说,却造成了不必要的布局包裹。文章提出了一个解决方案,即通过判断页面的skipGlobalLayout属性来决定是否包含RootLayout,从而实现特殊页面不包裹根布局的目标。
301 0
Next.js 实战 (七):浅谈 Layout 布局的嵌套设计模式
|
JavaScript 前端开发 API
Next.js 实战 (六):如何实现文件本地上传
这篇文章介绍了在Next.js中如何实现文件上传到本地的方法。文章首先提到Next.js官方文档中没有提供文件上传的实例代码,因此开发者需要自行实现,通常有两种思路:使用Node.js原生上传或使用第三方插件如multer。接着,文章选择了使用Node.js原生上传的方式来讲解实现过程,包括如何通过哈希值命名文件、上传到指定目录以及如何分类文件夹。然后,文章展示了具体的实现步骤,包括编写代码来处理文件上传,并给出了代码示例。最后,文章通过一个效果演示说明了如何通过postman模拟上传文件,并展示了上传后的文件夹结构。
224 0
Next.js 实战 (六):如何实现文件本地上传
|
前端开发 API 开发者
Next.js 实战 (五):添加路由 Transition 过渡效果和 Loading 动画
这篇文章介绍了Framer Motion,一个为React设计的动画库,提供了声明式API处理动画和页面转换,适合创建响应式用户界面。文章包括首屏加载动画、路由加载Loading、路由进场和退场动画等主题,并提供了使用Framer Motion和next.js实现这些动画的示例代码。最后,文章总结了这些效果,并邀请读者探讨更好的实现方案。
291 0
Next.js 实战 (五):添加路由 Transition 过渡效果和 Loading 动画
|
存储 网络架构
Next.js 实战 (四):i18n 国际化的最优方案实践
这篇文章介绍了Next.js国际化方案,作者对比了网上常见的方案并提出了自己的需求:不破坏应用程序的目录结构和路由。文章推荐使用next-intl库来实现国际化,并提供了详细的安装步骤和代码示例。作者实现了国际化切换时不改变路由,并把当前语言的key存储到浏览器cookie中,使得刷新浏览器后语言不会失效。最后,文章总结了这种国际化方案的优势,并提供Github仓库链接供读者参考。
569 0
Next.js 实战 (四):i18n 国际化的最优方案实践

热门文章

最新文章