vue 音频可视化

这篇具有很好参考价值的文章主要介绍了vue 音频可视化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

书接上文 vue实现歌词滚动效果,既然有了歌词滚动那么今天给大家来个绝活——音频可视化。伴随着各种新技术的更新迭代,往后大家或多或少都会接触到这个技能,因为在未来前端可视化必定会占有极其重要的地位,可视化应用场景应用模式也是千变万化,我将以最直观最简单的例子作为切入点,来带大家了解探究音频可视化到底是怎么实现的。


一、音频可视化是什么?

​音频可视化,是指一种以视觉为核心,以音乐为载体,以大众为诉求对象,借助多种新媒体技术等传播媒介,通过画面、影像来诠释音乐内容的、视听结合的大众化传播方式。  它能为理解、分析和比较音乐艺术作品形态的表现力和内外部结构提供的一种直观视觉呈现的技术。

二、实现思路

1,创建音频上下文,音频源节点

2,创建分析器节点对音频进行分析,连接音频源节点和分析器,随着音乐进度变化,分析器不断的分析出结果

3,连接分析器反馈分析结果到输出设备,由输出设备渲染到canvas标签

至于分析器简单来说就是可以把音频时域图通过频谱分析转换为频谱图,这个转换的过程叫做频谱分析,频谱分析的方式有很多,最常见的是快速傅里叶变换,有兴趣的可以研究一下频谱分析(之前写的一些小dome),内部逻辑大家就没必要深究啦 !

三、实现代码

1.初始化canvas

代码如下(示例)

<audio :src="music" @timeupdate="audioTime" controls  id="myAudio"></audio> 
<canvas id="myCanvas" style="border:1px solid #000;width:600px;height:200px">
 </canvas>

    initCancas() { 
      let canvas = document.getElementById("myCanvas");
      let ctx = canvas.getContext("2d"); 
      ctx.fillRect(10, 10, 280, 130);
    },

2,当音频播放时 初始化分析器

根据MDN的文档,AudioContext是一个专门用于音频处理的接口,并且工作原理是将AudioContext创建出来的各种节点(AudioNode)相互连接,音频数据流经这些节点并作出相应处理。

AudioContext() 构造方法创建了一个新的 AudioContext 对象 它代表了一个由音频模块链接而成的音频处理图,每一个模块由 AudioNode 表示。

AudioContext的createAnalyser()方法能创建一个AnalyserNode,可以用来获取音频时间和频率数据,以及实现数据可视化。

 onPlay() {
      if (this.isInit) {
        return;
      }
      let audioEle = document.getElementById("myAudio");
      //初始化
      var audCtx = new AudioContext(); //创建音频上下文
      this.analyser = audCtx.createAnalyser();
      const source = audCtx.createMediaElementSource(audioEle); //创建音频源节点
      this.analyser.fftSize = 512; //一个无符号长整形 (unsigned long) 的值,代表了快速傅里叶变换(分析器)的窗口大小
      //创建数组,用于接受节点分析器分析的数据
      this.dataArry = new Uint8Array(this.analyser.frequencyBinCount); //这里并不是声明一个普通数组,而是需要声明一个无符号的八位整数,刚好是一个字节。并且数组长度需要刚好等于频谱图横坐标长度
      source.connect(this.analyser);
      this.analyser.connect(audCtx.destination);

      this.isInit = true;
    },

vue 音频可视化

vue 音频可视化  

 vue 音频可视化

3.绘制分析器分析的结果数据

代码如下(示例):

    //把分析器分析的数据不断绘制到canvas
    draw() {
      let cvs = document.getElementById("myCanvas");
      let ctx = cvs.getContext("2d");
      requestAnimationFrame(this.draw);
      //清空画布
      const { width, height } = cvs;
      ctx.clearRect(0, 0, width, height);
      //判断分析器是否初始化
      if (!this.isInit) {
        return;
      }
      //分析器节点分析出数据到数组中
      this.analyser.getByteFrequencyData(this.dataArry); //让分析器节点分析当前音频源数据,把分析结果添加到数组
      const len = this.dataArry.length;
      const barWidth = width / len / 2;
      ctx.fillStyle = "#41b883";
      for (let i = 0; i < len; i++) {
        const data = this.dataArry[i]; //<256
        const barHeight = (data / 255) * height;
        const x1 = i * barWidth + width / 2;
        const x2 = width / 2 - (i + 1) * barWidth;
        const y = height - barHeight;
        ctx.fillRect(x1, y, barWidth, barHeight);
        ctx.fillRect(x2, y, barWidth, barHeight);
      }
    },

window.requestAnimationFrame() 告诉浏览器,你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行

备注: 若你想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用 window.requestAnimationFrame(callback)

兼容说明

由于是用的是实验API,此功能某些浏览器尚在开发中,请参考浏览器兼容性表格以得到在不同浏览器中适合使用的前缀。由于该功能对应的标准文档可能被重新修订,所以在未来版本的浏览器中该功能的语法和行为可能随之改变。

vue 音频可视化


 歌词滚动+音频可视化全部代码

<template>
  <div class="hello">
    <audio
      :src="music"
      @timeupdate="audioTime"
      controls
      @play="onPlay"
      id="myAudio"
    ></audio>
    <div
      :class="className"
      :style="{ 'animation-duration': `${lrcTime}000ms` }"
    >
      {{ dataWords }}
    </div>
    <canvas
      id="myCanvas"
      style="width: 600px; height: 100px"
    >
    </canvas>
  </div>
</template>

<script>
import music from "../assets/music.mp3";
export default {
  data() {
    return {
      isInit: false,
      className: "text load",
      lrcTime: "",
      music,
      currenttime: "",
      LRC: `[00:00.000] 作词 : 周耀辉/李焯雄
[00:01.000] 作曲 : 林健华
[00:02.000] 编曲 : 林健华
[00:15.000]忽然之间
[00:18.000]天昏地暗
[00:21.000]世界可以忽然什么都没有
[00:28.000]我想起了你
[00:32.000]再想到自己
[00:35.000]我为什么总在非常脆弱的时候
[00:40.000]怀念你
[00:43.000]''
[00:44.000]我明白太放不开你的爱
[00:49.000]太熟悉你的关怀分不开
[00:54.000]想你算是安慰还是悲哀
[00:58.000]而现在就算时针都停摆
[01:03.000]就算生命像尘埃分不开
[01:08.000]我们也许反而更相信爱
[01:24.000]''
[01:25.000]如果这天地
[01:29.000]最终会消失
[01:32.000]不想一路走来珍惜的回忆
[01:38.000]没有你
[01:40.000]''
[01:41.000]我明白太放不开你的爱
[01:46.000]太熟悉你的关怀分不开
[01:51.000]想你算是安慰还是悲哀
[01:55.000]而现在就算时针都停摆
[02:00.000]就算生命像尘埃分不开
[02:05.000]我们也许反而更相信爱
[02:34.000]''
[02:35.000]我明白太放不开你的爱
[02:40.000]太熟悉你的关怀分不开
[02:45.000]想你算是安慰还是悲哀
[02:49.000]而现在就算时针都停摆
[02:54.000]就算生命像尘埃分不开
[03:00.000]我们也许反而更相信爱`,
      lrcData: "",
      dataWords: "",

      analyser: {},
      dataArry: [],
    };
  },
  name: "HelloWorld",
  methods: {
    // 当音频播放
    onPlay() {
      if (this.isInit) {
        return;
      }
      let audioEle = document.getElementById("myAudio");
      //初始化
      var audCtx = new AudioContext(); //创建音频上下文
      this.analyser = audCtx.createAnalyser();
      const source = audCtx.createMediaElementSource(audioEle); //创建音频源节点
      this.analyser.fftSize = 512; //一个无符号长整形 (unsigned long) 的值,代表了快速傅里叶变换(分析器)的窗口大小
      //创建数组,用于接受节点分析器分析的数据
      this.dataArry = new Uint8Array(this.analyser.frequencyBinCount); //这里并不是声明一个普通数组,而是需要声明一个无符号的八位整数,刚好是一个字节。并且数组长度需要刚好等于频谱图横坐标长度
      source.connect(this.analyser);
      this.analyser.connect(audCtx.destination);

      this.isInit = true;
    },
    //把分析器分析的数据不断绘制到canvas
    draw() {
      let cvs = document.getElementById("myCanvas");
      let ctx = cvs.getContext("2d");
      requestAnimationFrame(this.draw);
      //清空画布
      const { width, height } = cvs;
      ctx.clearRect(0, 0, width, height);
      //判断分析器是否初始化
      if (!this.isInit) {
        return;
      }
      //分析器节点分析出数据到数组中
      this.analyser.getByteFrequencyData(this.dataArry); //让分析器节点分析当前音频源数据,把分析结果添加到数组
      const len = this.dataArry.length;
      const barWidth = width / len / 2;
      ctx.fillStyle = "#41b883";
      for (let i = 0; i < len; i++) {
        const data = this.dataArry[i]; //<256
        const barHeight = (data / 255) * height;
        const x1 = i * barWidth + width / 2;
        const x2 = width / 2 - (i + 1) * barWidth;
        const y = height - barHeight;
        ctx.fillRect(x1, y, barWidth, barHeight);
        ctx.fillRect(x2, y, barWidth, barHeight);
      }
    },
    initCancas() {
      let canvas = document.getElementById("myCanvas");
      let ctx = canvas.getContext("2d");
      // ctx.fillStyle = "#000";
      ctx.fillRect(10, 10, 280, 100);
    },
    //歌词数据转化为数组
    formatLrc() {
      var strLrc = this.LRC.split("\n");
      let arr = [];
      for (var i = 0; i < strLrc.length; i++) {
        var str = strLrc[i];
        var parts = str.split("]");
        var timeStr = parts[0].substring(1);
        var obj = {
          time: this.formatTime(timeStr),
          words: parts[1],
        };
        arr.push(obj);
      }
      this.lrcData = arr;
    },
    //时间转换(秒)
    formatTime(time) {
      var parts = time.split(":"); //[03:00.000]==>[03,00.00]
      return +parts[0] * 60 + +parts[1]; //计算秒
    },
    audioTime(e) {
      var time = e.target.currentTime; //当前播放器时间
      for (var i = 0; i < this.lrcData.length; i++) {
        if (time < this.lrcData[i].time) {
          //循环歌词数组,当播放器当前时间第一次小于歌词时间时当前数组下标减一即为当前时间数组所对应歌词下标
          this.lrcTime = this.lrcData[i].time - this.lrcData[i - 1].time;
          this.dataWords = this.lrcData[i - 1].words;
          return i - 1;
        }
      }
    },
  },
  watch: {
    dataWords() {
      this.className = "text";
      setTimeout(() => {
        this.className = "text load";
      }, 40);
    },
  },
  mounted() {
    this.formatLrc();
    this.initCancas();
    this.draw();
  },
};
</script> 
<style scoped>
@keyframes scan {
  0% {
    background-size: 0 100%;
  }
  100% {
    background-size: 100% 100%;
  }
}
.text {
  background: #7e7e7e -webkit-linear-gradient(left, #76ca16, #0fa046) no-repeat 0
    0;
  -webkit-text-fill-color: transparent;
  -webkit-background-clip: text;
  background-size: 0 100%;
}
.load {
  background-size: 100% 100%;
  animation: scan linear;
}
</style>

总结

以上就是今天要讲的内容,本文仅仅简单介绍了音频可视化的实现,而MDN为我们提供了大量新的API,能实现的东西远不局限于音频可视化,大家可以发挥想象力和创造力,去实现更华丽的功能。文章来源地址https://www.toymoban.com/news/detail-435737.html

到了这里,关于vue 音频可视化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【html本地工具】html+css+js本地音乐播放器,实现可视化音频频谱

    html+css+js本地音乐播放器,实现可视化音频频谱 之前用swing写了个本地音乐播放器(如下图),但是效果一言难尽,界面丑,功能bug也多,唉 所以后面又重新用html写了个,界面样式和功能方面,比swing写的好看、完善多了。 导入音乐(已完成) 展示列表(已完成) 列表双击

    2024年02月14日
    浏览(42)
  • python对wav音频可视化

    本文主要是使用代码实现音频文件(wav)的多种可视化。 1.信号 2.傅里叶变换 3.Mel(梅尔)谱图 4.log_Mel谱图 提示:以下是本篇文章正文内容,下面案例可供参考 为了便于展示,我将信号和傅里叶变换使用plt组合在一起进行展示。 结果展示: 为了便于展示,我将信号和傅里

    2023年04月08日
    浏览(82)
  • vue3 | 数据可视化实现数字滚动特效

    vue3不支持vue-count-to插件,无法使用vue-count-to实现数字动效,数字自动分割,vue-count-to主要针对vue2使用,vue3按照会报错: TypeError: Cannot read properties of undefined (reading \\\'_c\\\') 的错误信息。这个时候我们只能自己封装一个CountTo组件实现数字动效。先来看效果图: 使用Vue.component定义公

    2024年02月02日
    浏览(43)
  • Vue3实现可视化拖拽标签小程序

    实现功能:可视化标签拖拽,双击标签可修改标签内容 一个大DIV包含里面存放两个DIV一个input header为头部标签名称 内容区域绑定双击鼠标事件,触发开始修改事件(startEditing),使用v-if进行标签的显示和隐藏操作 input标签,事件绑定为修改内容,绑定获取焦点事件(@blue=“

    2024年02月09日
    浏览(51)
  • vue基于threejs实现的3D可视化编辑器

    随着5G网络的渐渐普及,物联网在人们的生活中渐渐广泛使用,社会向着越来越智能化的方向发展。当康科技经过不懈努力,研发属于自己的一款3D可视化编辑器,助力企业应用实现3D可视化服务。 编辑器界面如下: 操作视频演示: 3D可视化编辑器v1.0版本完成 主要功能点如下

    2024年02月13日
    浏览(43)
  • Springboot + Vue ElementUI 实现MySQL&&Postgresql可视化

    PostgreSQL教程--实现类似于MySQL的show create table功能实现见末尾 效果如图: DB连接配置维护: Schema功能:集成Screw生成文档,导出库的表结构,导出表结构和数据  表对象操作:翻页查询,查看创建SQL,生成代码 可以单个代码文件下载,也可以全部下载(打成zip包下载返回)

    2024年02月12日
    浏览(41)
  • 记录--关于前端的音频可视化-Web Audio

    最近听音乐的时候,看到各种动效,突然好奇这些音频数据是如何获取并展示出来的,于是花了几天功夫去研究相关的内容,这里只是给大家一些代码实例,具体要看懂、看明白,还是建议大家大家结合相关API文档来阅读这篇文章。 参考资料地址:Web Audio API - Web API 接口参考

    2024年02月16日
    浏览(53)
  • Android 音频可视化:频谱特效的探索与实践

    音频可视化,一言以蔽之,就是声音到图像的转换。 随着视觉工业时代的到来,用户逐渐重视产品的极致体验,在市场上诸多优秀的音乐类APP中, 频谱动效 是一个经典的应用场景: 图片来源:咪咕音乐 本文以 Android 端为例,从音频信号 数据的获取 、 数据的处理 、 常见问

    2024年02月15日
    浏览(48)
  • HTML5+CSS3+JS小实例:音频可视化

    实例:音频可视化 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 【CSS】

    2024年01月18日
    浏览(46)
  • Qt数据可视化示例01-显示实时音频数据的简单应用程序

    audiolevels 示例显示实时音频数据的简单应用程序。示例从麦克风读取音频电平, 并在条形图中显示这些电平。为了增加用于演示目的的负载,并使图形更漂亮, 使用稍作修改的数据来填充多行。 作为Qt 数据可视化的第一个示例,我们忽略数据源的获取,主要关注数据的呈现

    2024年01月18日
    浏览(68)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包