音频可视化:原生音频API为前端带来的全新可能!

音频API是一组提供给网页开发者的接口,允许他们直接在浏览器中处理音频内容。这些API使得在不依赖任何外部插件的情况下操作和控制音频成为可能。
Web Audio API 可以进行音频的播放、处理、合成以及分析等操作。借助于这些工具,开发者可以实现自定义的音效处理,创建互动的音乐体验,甚至开发复杂的音频应用程序,如实时音频频谱分析或音频可视化效果。

在这里插入图片描述

本文就通过Web Audio API来实现对音乐可视化的案例

基础结构

整个界面结构比较简单,需要一个播放音频的audio和用于可视化的canvas。

<canvas id="canvas"></canvas>
<audiosrc="https://resource.dengzhanyong.com/audio/海底.mp3"controls
></audio>

初始化工作

对 audio 注册播放事件,在首次播放时做一些音频处理相关的初始化工作

const audio = document.querySelector("audio");
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
// 事件初始化状态
let isInit = false;
// 绑定播放事件
audio.onplay = () => {// 初始化内容只需要做一次,每次暂停后再播放都会调用此事件,因此这里做个判断if (isInit) return;/* 处理内容 */isInit = true;
};

音频处理流程

要想把音频可视化,必须要拿到播放的音频数据,这就需要使用到AudioContext API,可以理解为是一个音频上下文,音频所有的事情都在上下文中发生,整个流程见下图。
在这里插入图片描述

源节点:可以通过AudioContext来创建源节点,本案例中源节点就是audio标签
处理节点:在这里对音频进行处理,比如:处理音色、音调、音频等
输出节点:一般为当前使用的扬声器,可以在AudioContext中获取到
每个节点之间通过连接的方式串联起来,形成一个完整的链路,在处理节点可以加入多个处理节点,也可以有多个源节点。

在这里插入图片描述

对于本案例来说,需要一个分析器节点,从分析器节点中获取到音频波形数据,然后处理数据,最后交给canvas绘制。
在这里插入图片描述

audio.onplay = () => {if (isInit) return;// 创建音频上下文const audioCtx = new AudioContext();// 创建音频源const source = audioCtx.createMediaElementSource(audio);// 连接到输出设备source.connect(audioCtx.destination);isInit = true;
};

audioCtx.destination为当前的输出设备

获取处理音频数据

使用audioCtx.createAnalyser 创建一个分析器节点,然后将源节点连接到分析其节点。

分析器节点获取到的是时域图的数据,需要通过快速傅立叶变换把时域图转为频域图数据,转换过程不需要我们自己去做,AudioContext 提供了相关的API,只需要简单设置一些参数即可。

// 设置初始化状态
let isInit = false;
let analyser, data;
// 绑定播放事件
audio.onplay = () => {// console.log("开始播放");if (isInit) return;// 创建音频上下文const audioCtx = new AudioContext();// 创建音频源const source = audioCtx.createMediaElementSource(audio);// 创建分析器节点analyser = audioCtx.createAnalyser();// 设置窗口大小,窗口越大,分析结果越详细analyser.fftSize = 512;data = new Uint8Array(analyser.frequencyBinCount);// 将源连接到分析器节点source.connect(analyser);// 将分析器节点连接到输出设备analyser.connect(audioCtx.destination);isInit = true;
};
  • fftSize:设置傅立叶变换的窗口大小,窗口越大,分析的结果越详细。数值必须是2的n次幂
  • 分析结果放到数组中,数组的每一项都是一个8位无符号的整数,因此这里创建的不是一个普通数组Array,而是Uint8Array
  • frequencyBinCount:这个属性的值为fftSize的一半,因为傅立叶变换后的频域图是对称的结构,所以这里只需要拿到一半的数据即可
    最后将分析器节点连接到输出设备,否则无法听到音频声音

绘制数据

随着音频的不断播放,需要把分析器的数据不断的更新到data数组中。
绘制过程就是一些简单的计算逻辑:
每个矩形的宽度 = 画布宽度/数组长度
每个条形的总宽度 = 数据/255 * 画布高度

// 绘制内容
function draw() {requestAnimationFrame(draw);
// 清空画布
const { width, height } = canvas;ctx.clearRect(0, 0, width, height);if (!isInit) return;// 把分析器节点的数据更新到data中analyser.getByteFrequencyData(data);const len = data.length;const barWidth = width / len;// 每一个方块的高度const blockHeight = 8;for (let index = 0; index < data.length; index++) {// 拿到本列的数值const _data = data[index];const barHeight = (_data / 255) * height;// 每列的横坐标const x = index * barWidth;// 每列的方块数量const blockCount = Math.round(barHeight / 10);// 循环绘制每列的小方块for (let number = 0; number < blockCount; number++) {// 设置颜色ctx.fillStyle = gradient[number];// 每个小方块的纵坐标const y = height - blockHeight * number;// 绘制圆角矩形drawRoundedRect(x, y, barWidth - 1,  blockHeight - 1, 2);}}   
}

绘制圆角矩形

canvas没有直接绘制圆角矩形的方法,我们通过lineTo方法来设置四边,再通过quadraticCurveTo(二次贝塞尔曲线路径)方法来设置圆角的路径,最后再进行填充。

function drawRoundedRect(x, y, width, height, radius) {
if (height === 0) return;ctx.beginPath();ctx.moveTo(x + radius, y);ctx.lineTo(x + width - radius, y);ctx.quadraticCurveTo(x + width, y, x + width, y + radius);ctx.lineTo(x + width, y + height - radius);ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);ctx.lineTo(x + radius, y + height);ctx.quadraticCurveTo(x, y + height, x, y + height - radius);ctx.lineTo(x, y + radius);ctx.quadraticCurveTo(x, y, x + radius, y);ctx.fill();
}

设置渐变色

HSLA表示一种颜色模式,它是由四个部分组成:色相(Hue)、饱和度(Saturation)、亮度(Lightness)和透明度(Alpha)

  • hue(色相):0到360之间的整数,表示颜色的基本属性,如红色、绿色或蓝色。
  • saturation(饱和度):0%到100%之间的百分比,表示颜色的纯度。0%表示灰色,100%表示最鲜艳的颜色。
  • lightness(亮度):0%到100%之间的百分比,表示颜色的明暗程度。0%表示黑色,50%表示原始颜色,100%表示白色。
  • alpha(透明度):0到1之间的小数,表示颜色的透明度。0表示完全透明,1表示完全不透明。
    在这里插入图片描述

封装一个获取渐变色的方法 generateGradient,接收两个参数:baseColor(起始颜色)、count(渐变色的数量)。

function generateGradient(baseColor, count) {let hsl = baseColor.match(/hsla?\((\d+),\s*(\d+%),\s*(\d+%),\s*([\d.]+)\)/);let h = parseInt(hsl[1], 10); // Huelet s = parseInt(hsl[2], 10); // Saturationlet l = parseInt(hsl[3], 10); // Lightness// 在色盘上按照数量均分,获取每个均分点的颜色let stepH = 360 / count;// 提高每个等级的亮度let stepL = 100 / (count + 1);let gradientColors = [];for (let i = 0; i < count; i++) {gradientColors.push(`hsl(${h + i * stepH}, ${s}%, ${l + i * stepL}%)`);}return gradientColors;
}let baseColor = "hsla(240, 100%, 50%, 1)"; // 蓝色
let gradient = generateGradient(baseColor, 200); // 200种颜色

到这里就已经完成了本次案例的全部内容,对于音频的处理这还只是冰山一角,发挥你的想象力可以做出更多可玩性较强的内容。

最后,可以访问 https://resource.dengzhanyong.com/audio/音频可视化.html 查看本次案例的效果。回复 “音频可视化” 获取本案例的全部源码。

往期推荐

10分钟掌握HTML拖放API!让你的网页元素瞬间拥有拖拽功能,轻松提升用户体验!

不要只会用conosle.log了,这几个console命令,让你的调试效率翻倍

前端手写Promise.all,你不知道的多个知识点,比想象中更精彩!

写在最后

欢迎访问我的个人网站:www.dengzhanyong.com
关注我的公众号【前端筱园】,不错过每一篇推送
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/7035.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IPD-开发流程

2024-5-6记录于PR办公室 在上一家公司做硬件产品经理的时候&#xff0c;Richard Li曾花费“巨资”请了华为前战略专家给我们培训&#xff0c;讲授IPD这门课的模式都很IPD&#xff0c;当时完全没重视&#xff0c;光想着不可能靠这个能把产品做好&#xff0c;这样做产品必定是一批…

wordpress外贸建站公司歪建站新版网站上线

wordpress外贸建站公司 歪猫建站 歪猫WordPress外贸建站&#xff0c;专业从事WordPress多语言外贸小语种网站建设与外贸网站海个推广、Google SEO搜索引擎优化等服务。 https://www.waimaoyes.com/dongguan

【driver2】设备读写,同步和互斥,ioctl,进程休眠,时间和延时,延缓

文章目录 1.实现设备读写&#xff1a;write函数中一个进程写没问题&#xff0c;两进程写&#xff1a;第一个进程运行到kzalloc时&#xff0c;第二个进程也执行了kzalloc&#xff0c;只第二个进程地址保存在c中&#xff0c;第一个进程分配内存空间地址丢失造成内存泄漏。第一个进…

题目:排序疑惑

问题描述&#xff1a; 解题思路&#xff1a; 做的时候没想到&#xff0c;其实这是以贪心题。我们可以每次排最大的区间&#xff08;小于n&#xff0c;即n-1大的区间&#xff09;&#xff0c;再判断是否有序 。因此只需要分别判断排&#xff08;1~n-1&#xff09;和&#xff08;…

我独自升级崛起下载教程 我独自升级崛起一键下载

动作RPG游戏基于广大喜爱的动画和在线漫画《我独自升级崛起》在5月8日&#xff0c;这款新的游戏首次在全球亮相&#xff0c;意在给那些对游戏情有独钟的玩家带来更加丰富和多种多样的游戏体验。这个网络武侠题材的游戏设计非常具有创意&#xff0c;其主要故事围绕着“独孤求败”…

数据分析——业务指标分析

业务指标分析 前言一、业务指标分析的定义二、业务问题构建问题构建的要求 三、业务问题的识别在识别问题的阶段对于企业内部收益者的补充 四、竞争者分析竞争者分析的内容竞争者分析目的案例 五、市场机会识别好的市场机会必须满足的条件市场机会案例 六、风险控制数据分析师常…

【字符串】Leetcode 二进制求和

题目讲解 67. 二进制求和 算法讲解 为了方便计算&#xff0c;我们将两个字符串的长度弄成一样的&#xff0c;在短的字符串前面添加字符0&#xff1b;我们从后往前计算&#xff0c;当遇到当前计算出来的字符是> 2’的&#xff0c;那么就需要往前面进位和求余 注意&#xf…

在企业中软件产品测试报告可以运用的场景

在企业应用场景中&#xff0c;测试报告的应用场景十分广泛且重要。以下是几个主要的应用场景&#xff1a; 产品质量评估与保证&#xff1a;测试报告是企业评估软件或产品质量的重要依据。通过测试报告&#xff0c;企业可以了解产品在不同场景下的性能表现、安全性、稳定性以及…

1.4 初探JdbcTemplate操作

实战目的 掌握Spring框架中JdbcTemplate的使用&#xff0c;实现对数据库的基本操作。理解数据库连接池的工作原理及其在实际开发中的重要性。通过实际操作&#xff0c;加深对Spring框架中ORM&#xff08;对象关系映射&#xff09;的理解。 关键技术点 JdbcTemplate操作&…

辐射类案例分析

辐射类案例分析 1.1 接地对辐射实验的影响 金属外壳接地已经成为了一种共识&#xff0c;很多人可能会认为金属外壳就该接地&#xff0c;接地可以改善EMC性能&#xff0c;对于抗干扰类实验&#xff0c;情况可能是这样&#xff0c;但是对于辐射类实验而言&#xff0c;有时候会有…

Java八股文系列之五(分布式事务)

什么是分布式事务 事务是一个程序执行单元&#xff0c;里面的所有操作要么全部执行成功&#xff0c;要么全部执行失败。在分布式系统中&#xff0c;这些操作可能是位于不同的服务中&#xff0c;那么如果也能保证这些操作要么全部执行成功要么全部执行失败呢&#xff1f;这便是…

直播预告|第一批 Vision Pro 开发者开始弃坑了吗? 本周六一起听听三位 XR 开发者的真实想法!

随着技术的进步&#xff0c;扩展现实&#xff08;XR&#xff09;行业正在迅速发展&#xff0c;成为连接现实与虚拟世界的桥梁。XR 技术&#xff0c;包括虚拟现实&#xff08;VR&#xff09;、增强现实&#xff08;AR&#xff09;和混合现实&#xff08;MR&#xff09;&#xff…

Web测试需要测试什么

Web测试可以涵盖以下方面的测试&#xff1a; 1.功能测试&#xff1a;确保Web应用的各项功能按照需求规格说明书的要求正常工作。测试包括用户注册、登录、搜索、数据提交、页面导航等功能。 2.用户界面测试&#xff1a;验证Web应用的用户界面是否符合设计和用户体验要求。测试…

【0day】湖南建研工程质量检测系统InstrumentUsageRecordExport接口处存在任意文件读取漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

2024-05-06 问AI: 介绍一下深度学习中的LSTM网络

文心一言 当谈到深度学习中的LSTM&#xff08;Long Short-Term Memory&#xff09;网络时&#xff0c;它是一种特殊的循环神经网络&#xff08;RNN&#xff09;架构&#xff0c;旨在解决传统RNN在处理长序列时遇到的梯度消失和梯度爆炸问题。LSTM网络因其能够捕捉序列数据中的…

Leetcode编程练习

面试题-消失的数字 . - 力扣&#xff08;LeetCode&#xff09; class Solution { public:void reverse(vector<int>& nums, int start, int end) {while (start < end) {swap(nums[start], nums[end]);start 1;end - 1;}}void rotate(vector<int>& …

Rust语言系统编程实战(小北学习笔记)

前言 进入大学以来&#xff08;计算机应用技术——大数据方向&#xff09;&#xff0c;就像很多程序猿&#x1f412;一样&#xff0c;小北开始每学期学习一种新的编程语言。通过学习另一个编程语言&#xff0c;可以了解很多规范和规则&#xff0c;并得到了一些想法&#xff0c;…

如何使用IntelliJ IDEA SSH连接本地Linux服务器远程开发

文章目录 1. 检查Linux SSH服务2. 本地连接测试3. Linux 安装Cpolar4. 创建远程连接公网地址5. 公网远程连接测试6. 固定连接公网地址7. 固定地址连接测试 本文主要介绍如何在IDEA中设置远程连接服务器开发环境&#xff0c;并结合Cpolar内网穿透工具实现无公网远程连接&#xf…

MES生产系统与数字孪生双重结合:智慧制造工厂的新引擎

随着数字化浪潮的推动&#xff0c;制造行业正在经历着前所未有的变革。在这个变革的浪潮中&#xff0c;MES生产制造系统与数字孪生技术的深度融合成为了制造工厂未来发展的核心驱动力。这种结合不仅提升了生产效率&#xff0c;优化了资源配置&#xff0c;降低了运营成本&#x…

德国韦纳WENAROLL滚压刀,液压缸,滚光刀,挤压刀,滚轧刀

德国韦纳WENAROLL滚压刀,液压缸&#xff0c;滚光刀,挤压刀&#xff0c;滚轧刀&#xff08;百度一下&#xff0c;西安尚融&#xff09; 德国韦纳&#xff08;WENAROLL&#xff09;的滚压刀、液压缸、滚光刀、挤压刀和滚轧刀在工业领域享有很高的声誉&#xff0c;这些产品因其高…