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

音频可视化:原生音频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
关注我的公众号【前端筱园】,不错过每一篇推送
在这里插入图片描述

相关文章:

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

音频API是一组提供给网页开发者的接口&#xff0c;允许他们直接在浏览器中处理音频内容。这些API使得在不依赖任何外部插件的情况下操作和控制音频成为可能。 Web Audio API 可以进行音频的播放、处理、合成以及分析等操作。借助于这些工具&#xff0c;开发者可以实现自定义的音…...

【中等】保研/考研408机试-动态规划1(01背包、完全背包、多重背包)

背包问题基本上都是模板题&#xff0c;重点&#xff1a;弄熟多重背包模板 dp[j]max(dp[j-v[i]]w[i],dp[j]) //核心思路代码&#xff08;一维数组版&#xff09; dp[i][j]max(dp[i-1][j], dp[i-1][j-v[i]]w[i])//二维数字版 一、 0-1背包 一般输入两个变量&#xff1a;体积&…...

[DEMO]给两个字符串取交集的词语

要求&#xff1a;2个英文字符串中&#xff0c;取相同的大于等于4个字母的词组 比如&#xff1a; 字符串1&#xff1a;" xingMeiLingabcdef WorldHello", 字符串2&#xff1a;"mnjqlup WorldLingLing xingMeiLingHello" 获取交接&#xff1a; [xingMeiLing…...

leetcode53-Maximum Subarray

题目 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组 是数组中的一个连续部分。 示例 1&#xff1a; 输入&#xff1a;nums [-2,1,-3,4,-1,2,1,-5,4] 输出&#xf…...

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之七 简单进行人脸检测并添加面具特效实现

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之七 简单进行人脸检测并添加面具特效实现 目录...

【go项目01_学习记录06】

学习记录 1 使用中间件1.1 测试一下1.2 push代码 2 URI 中的斜杆2.1 StrictSlash2.2 兼容 POST 请求 1 使用中间件 代码中存在重复率很高的代码 w.Header().Set("Content-Type", "text/html; charsetutf-8")统一对响应做处理的&#xff0c;我们可以使用中…...

Vue中Element的下载

打开vscode让项目在终端中打开 输入npm install element-ui2.15.3 然后进行下载 在node_modules中出现element-ui表示下载完成 然后在输入Vue.use(ElementUI); import Vue from vue import App from ./App.vue import router from ./router import ElementUI from element-ui…...

机器人项目相关

机器人项目相关 1. Nvidia 1.1 Jetson 1.1.1 初步安装Riva教程 llamaspeakJetson AGX Orin踩坑记录&#xff08;1&#xff09;安装Riva 参考知乎链接&#xff1a;https://zhuanlan.zhihu.com/p/670007305 1.1.2 NVIDIA Jetson AI Lab 借助 NVIDIA Jetson™ 将生成式 AI…...

Mac升级go版本某种错误情况处理

当看到 "go1.21 is keg-only, which means it was not symlinked into /opt/homebrew" 这样的信息时&#xff0c;意味着Homebrew没有自动为你创建指向新版本Go的符号链接&#xff08;symlink&#xff09;&#xff0c;因为这是一个旧版本Go的替代版本。 Homebrew中的…...

美团KV存储squirrel和Celler学习

文章目录 美团在KV存储squirrel优化和改进在水平方向1、对Gossip协议进行优化 在垂直扩展方面1、forkless RDB数据复制优化2、使用多线程&#xff0c;充分利用机器的多核能力 在高可用方面 美团持久化kv存储celler优化和改进水平扩展优化1、使用bulkload进行数据导入2、线程模型…...

Python学习笔记------处理数据和生成折线图

给定数据&#xff1a; jsonp_1629344292311_69436({"status":0,"msg":"success","data":[{"name":"美国","trend":{"updateDate":["2.22","2.23","2.24",&qu…...

知识图谱与大语言模型的协同(RAG)——MindMap

MindMap : Knowledge Graph Prompting Sparks Graph of Thoughts in Large Language Models 论文地址: https://arxiv.org/abs/2308.09729 代码:https://github.com/wylwilling/MindMap 1.概述 大型语言模型(LLMs)在处理新信息、防止生成幻觉内容、以及增强决策过程透明度…...

奶爸预备 |《P.E.T.父母效能训练:让亲子沟通如此高效而简单:21世纪版》 / 托马斯·戈登——读书笔记

目录 引出致中国读者译序前言第1章 父母总是被指责&#xff0c;而非受训练第2章 父母是人&#xff0c;不是神第3章 如何听&#xff0c;孩子才会说&#xff1a;接纳性语言第4章 让积极倾听发挥作用第5章 如何倾听不会说话的婴幼儿第6章 如何听&#xff0c;孩子才肯听第8章 通过改…...

【WebGIS实例】(13)MapboxGL 加载地形高程数据

前言 官网示例&#xff1a;Add 3D terrain to a map | Mapbox GL JS | Mapbox 大佬博客&#xff1a;Mapbox GL基础&#xff08;七&#xff09;&#xff1a;地形数据的处理与加载 (jl1mall.com) 加载Mapbox地形数据 map.once(style.load, () > {map.addSource(mapbox-dem,…...

Node.js -- MongoDB

文章目录 1. 相关介绍2. 核心概念3. 命令行交互3.1数据库命令3.2 集合命令3.3 文档命令 4. 数据库应用场景4.1 新增4.2 删除4.3 更新4.4 查询 5. 图形化工具Robo 3T 1. 相关介绍 一、简介 Mongodb是什么 MongoDB是一个基于分布式文件存储的数据库&#xff0c;官方地址https://…...

语音识别--单声道转换与降采样

⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计3077字&#xff0c;阅读大概需要3分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#xf…...

基于springboot+vue+Mysql的点餐平台网站

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…...

数据库优化

一、主从读写分离 主库:主要负责数据的写入。 从库:主要负责数据的查询。 引出问题: 可能会存在主从延迟,导致主从一致性问题。查询主库的量级需要控制。数据量庞大,索引也占据存储空间,磁盘空间不足,当主库宕机后会影响所有模块的写入,需要进行数据分片,因此引出分库…...

专业渗透测试 Phpsploit-Framework(PSF)框架软件小白入门教程(一)

本系列课程&#xff0c;将重点讲解Phpsploit-Framework框架软件的基础使用&#xff01; 本文章仅提供学习&#xff0c;切勿将其用于不法手段&#xff01; Phpsploit-Framework&#xff08;简称 PSF&#xff09;框架软件&#xff0c;是一款什么样的软件呢&#xff1f; Phpspl…...

Web安全研究(七)

NDSS 2023 开源地址&#xff1a;https://github.com/bfpmeasurementgithub/browser-fingeprint-measurement 霍普金斯大学 文章结构 introbackground threat model measurement methodology step1: traffic analysisstep2: fingerprint analysis dataset attack statisticsbro…...

矩池云jupyter运行opengait代码 未完成版

文章目录 前言——矩池云的使用技巧1.切换源 一、下载数据集二、下载模型三、环境配置1.查看python、torch、torchvision版本2.查看一些包版本是否过高3.下载包 四、开始训练1.设置环境变量2.遇到的问题&#xff08;1&#xff09;torch.cuda.is_available()返回false&#xff0…...

油烟净化器买家必看!商用油烟净化器功效及使用方法盘点

我最近分析了餐饮市场的油烟净化器等产品报告&#xff0c;解决了餐饮业厨房油腻的难题&#xff0c;更加方便了在餐饮业和商业场所有需求的小伙伴们。 在选择商用油烟净化器时&#xff0c;了解其功效和正确的使用方法至关重要。让我们一起来盘点一下。 高效净化油烟 商用油烟…...

gitee关联picgo设置自己的typora_图床

一&#xff1a;去gitee官网创建仓库&#xff1a;typora_图床 1.百度搜索关键字&#xff1a;gitee&#xff0c;进入官网 2.进入gitee登录或者注册自己的账号 3.进入主页后&#xff0c;点击右上方 4.点击新建仓库 5.设置仓库名&#xff1a;typora_图床 6.点击5的创建&#xff0…...

深入理解网络原理1

文章目录 前言一、网络初识1.1 IP地址1.2 端口号1.3 协议1.4 五元组1.5 协议分层 二、TCP/IP五层协议三、封装和分用四、客户端vs服务端4.1 交互模式4.2 常见的客户端服务端模型 前言 随着时代的发展&#xff0c;越来越需要计算机之间互相通信&#xff0c;共享软件和数据&…...

为什么感觉没有效果

以前在辅导小儿作业的时候&#xff0c;我会在常用的搜索引擎里去寻找答案&#xff0c;一般情况下都能解决问题。 但是最近一段时间&#xff0c;我发现&#xff0c;搜索引擎搜出来的结果还没有利用短视频搜出来的答案更全面&#xff0c;短视频软件不仅可以显示AI整理出来的答案…...

C++中的指针详解

C中的指针详解 在C编程中&#xff0c;指针是一个非常重要且基础的概念。它允许程序员直接访问和操作内存地址&#xff0c;为高级数据结构和算法的实现提供了基础。本文将详细讲解C中指针的概念、用法和注意事项&#xff0c;帮助读者深入理解并掌握指针的相关知识。 一、指针的…...

视频改字祝福 豪车装X系统源码uniapp前端小程序源码

视频改字祝福 豪车装X系统源码uniapp前端小程序源码&#xff0c;创意无限&#xff01;AI视频改字祝福&#xff0c;豪车装X系统源码开源&#xff0c;打造个性化祝 福视频不再难&#xff01; 想要为你的朋友或家人送上一份特别的祝福&#xff0c;让他们感受到你的真诚与关怀吗&am…...

google chromeDriver 地址

#chrome driver 下载地址 https://getwebdriver.com/chromedriver #chrome brower下载地址 https://googlechromelabs.github.io/chrome-for-testing/ centos 安装的dockerFile的部分命令&#xff1a; #安装browser wget https://dl.google.com/linux/chrome/rpm/stable/x86_…...

分布式与一致性协议之Raft算法(一)

Raft算法 概述 Raft算法属于Multi-Paxos算法&#xff0c;它在兰伯特Multi-Paxos思想的基础上做了一些简化和限制&#xff0c;比如日志必须是连续的&#xff0c;只支持领导者(Leader)、跟随者(Follwer)和候选人(Candidate)3种状态。在理解和算法实现上&#xff0c;Raft算法相对…...

从自定义一个作用域开始来了解SpringBean的作用域

你好&#xff0c;这里是codetrend专栏“Spring6全攻略”。 在 Spring 框架中&#xff0c;Bean 的作用域&#xff08;Scope&#xff09;定义了 Bean 实例在容器中如何创建、管理和销毁的策略。 Spring 提供了多种 Bean 作用域&#xff0c;每种作用域都有其特定的生命周期和适用…...

分享wordpress小程序源码/能够免费换友链的平台

比如一个商品表&#xff0c;一个关键词表1对多得关系那么可以用如下的sql取出结果集SELECT product_id,product_name,(SELECT GROUP_CONCAT(product_key_keyword)FROM b2b_product_key WHERE product_product_idproduct_id) as keyword FROM b2b_product WHERE 1 转载于:https…...

平台网站建设多少钱/上海广告推广

难得连续两天都有时间来更新&#xff0c;嘿嘿&#xff0c;我不是个勤劳的人&#xff0c;如果白天没时间&#xff0c;不要指望我晚上健完身会在家里奋笔疾书&#xff0c;哈哈哈&#xff0c;因为肥宅已经累趴下不想起来了……添加行在中继器中加入数据。我们事先已经在中继器左侧…...

安徽网站定制/营销推广外包

分享第一份Java基础-中级-高级面试集合 Java基础&#xff08;对象线程字符接口变量异常方法&#xff09; Java中级开发&#xff08;底层Spring相关Redis分布式设计模式MySQL高并发锁线程&#xff09; Java高级“程序猿”&#xff08;高并发Redis缓存分布式消息队列高可用微服务…...

企业网站管理系统的设计与实现/湖南关键词优化快速

2019独角兽企业重金招聘Python工程师标准>>> 2017派卧底去阿里、京东、美团、滴滴带回来的面试题及答案 javastack Java技术栈 2017-11-03 最近有很多朋友去目前主流的大型互联网公司面试&#xff08;阿里巴巴、京东、美团、滴滴&#xff09;&#xff0c;面试回来之…...

推广代理平台/移动优化课主讲:夫唯老师

点此下载 第一章 1&#xff0e;典型的编译程序在逻辑功能上由哪几部分组成&#xff1f; 答&#xff1a;编译程序主要由以下几个部分组成&#xff1a;词法分析、语法分析、语义分析、中间代码生成、中间代码优化、目标代码生成、错误处理、表格管理。 2. 实现编译程序的主要方…...

macbook air网站开发/优化关键词排名提升

前言 近日&#xff0c;看到Myabtis中组件中SqlSessionFactory由SqlSessionFactoryBuilder().build()生成时&#xff0c;且采用Builder模式&#xff0c;遂记录学习之。 SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream); 1、什么是Buil…...