前端音频可视化Web Audio如何实现

免费教程   2024年05月11日 2:29  

这篇文章主要介绍“前端音频可视化WebAudio如何实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“前端音频可视化WebAudio如何实现”文章能帮助大家解决问题。

实现思路

首先画肯定是用canvas去画,关于音频的相关数据(如频率、波形)如何去获取,需要去获取相关audio的DOM 或通过请求处理去拿到相关的音频数据,然后通过Web API 提供相关的方法来实现。(当然还要考虑要音频请求跨域的问题,留在最后。)

一个简单而典型的 audio 流程如下(取自MDN):

创建音频上下文

在音频上下文里创建源 &mdash; 例如<audio>, 振荡器,流

创建效果节点,例如混响、双二阶滤波器、平移、压缩

为音频选择一个目的地,例如你的系统扬声器

连接源到效果器,对目的地进行效果输出

实现一、频率图

实现第一种类型,首先我们需要通过fetch或xhr来获取一个线上音频的数据,这里以fetch为例;

//创建一个音频上下文、考虑兼容性问题letaudioCtx=new(window.AudioContext||window.webkitAudioContext)();//添加一个音频源节点letsource=audioCtx.createBufferSource();//res.arrayBuffer是将数据转换为arrayBuffer格式fetch(url).then((res)=>res.arrayBuffer()).then((res)=>{//decodeAudioData是将arrayBuffer格式数据转换为audioBufferaudioCtx.decodeAudioData(res).then((buffer)=>{//decodeAudioData解码完成后,返回一个AudioBuffer对象//绘制音频波形图draw(buffer);//连接音频源source.buffer=buffer;source.connect(audioCtx.destination);//音频数据处理完毕});});

需要明白的是,source.connect(audioCtx.destination)是将音频源节点链接到输出设备,否则会没声音哦。那么现在有了数据、我们只需要通过canvas将数据画出来即可。

functiondraw(buffer){//buffer.numberOfChannels返回音频的通道数量,1即为单声道,2代表双声道。这里我们只取一条通道的数据letdata=[];letoriginData=buffer.getChannelData(0);//存储所有的正数据letpositives=[];//存储所有的负数据letnegatives=[];//先每隔50条数据取1条for(leti=0;i<originData.length;i+=50){data.push(originData[i]);}//再从data中每10条取一个最大值一个最小值for(letj=0,len=data.length/10;j<len;j++){lettemp=data.slice(j*10,(j+1)*10);positives.push(Math.max(...temp));negatives.push(Math.min(...temp));}if(canvas.getContext){letctx=canvas.getContext("2d");canvas.width=positives.length;letx=0;lety=75;letoffset=0;vargrd=ctx.createLinearGradient(0,0,canvas.width,0);//为渐变添加颜色,参数1表示渐变开始和结束之间的位置(用0至1的占比表示),参数2位颜色grd.addColorStop(0,"yellow");grd.addColorStop(0.5,"red");grd.addColorStop(1,"blue");ctx.fillStyle=grd;ctx.beginPath();ctx.moveTo(x,y);//横坐标上方绘制正数据,下方绘制负数据//先从左往右绘制正数据//x+0.5是为了解决canvas1像素线条模糊的问题for(letk=0;k<positives.length;k++){ctx.lineTo(x+k+0.5,y-50*positives[k]);}//再从右往左绘制负数据for(letl=negatives.length-1;l>=0;l--){ctx.lineTo(x+l+0.5,y+50*Math.abs(negatives[l]));}//填充图形ctx.fill();}}

[参考文章](Web Audio - 绘制音频图谱

二、实时频率图

实现第二种类型,获取实时频率,用到的API与第一种有区别,但流程一直,都是通过一个音频源节点通过连接达到效果。只不过在连接的中间加入了一个分析器analyser,在将分析器连接到输出设备。

constaudio=document.querySelector('audio')//解决音频跨域问题audio.crossOrigin='anonymous'constcanvas=document.querySelector('canvas')constctx=canvas.getContext("2d")functioninitCanvas(){//初始化canvascanvas.width=window.innerWidth*devicePixelRatiocanvas.height=(window.innerHeight/2)*devicePixelRatio}initCanvas()//将数据提出来letdataArray,analyser;//播放事件audio.onplay=function(){//创建一个音频上下文实例constaudioCtx=new(window.AudioContext||window.webkitAudioContext)();//添加一个音频源节点constsource=audioCtx.createMediaElementSource(audio);//分析器节点analyser=audioCtx.createAnalyser();//fft分析器越大分析越细analyser.fftSize=512//创建一个无符号字节的数组dataArray=newUint8Array(analyser.frequencyBinCount);//音频源节点链接分析器source.connect(analyser)//分析器链接输出设备analyser.connect(audioCtx.destination,)}

那么接下来至于怎么把数据画出来,就凭大家的想法了。

requestAnimationFrame(draw)//const{width,height}=canvas;ctx.clearRect(0,0,width,height)//分析器节点分析出的数据到数组中ctx.fillStyle='#78C5F7'ctx.lineWidth=2;ctx.beginPath();//getByteFrequencyData,分析当前音频源的数据装到dataArray数组中去//获取实时数据analyser.getByteFrequencyData(dataArray)//console.log(dataArray);constlen=dataArray.length;constbarWidth=width/len;letx=0;for(leti=0;i<len;i++){constdata=dataArray[i];constbarHeight=data/255*height;//ctx.fillRect(x,y,barWidth,height)letv=dataArray[i]/128.0;lety=v*height/2;if(i===0){ctx.moveTo(x,y);}else{ctx.lineTo(x,y);}x+=barWidth;}//ctx.lineTo(canvas.width,canvas.height/2);ctx.stroke();}draw();关于请求音频跨域问题解决方案

给获取的audio DOM添加一条属性即可

audio.crossOrigin='anonymous'

或者直接在 aduio标签中 加入 crossorigin="anonymous"

关于“前端音频可视化WebAudio如何实现”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注行业资讯频道,小编每天都会为大家更新不同的知识点。

域名注册
购买VPS主机

您或许对下面这些文章有兴趣:                    本月吐槽辛苦排行榜

看贴要回贴有N种理由!看帖不回贴的后果你懂得的!


评论内容 (*必填):
(Ctrl + Enter提交)   

部落快速搜索栏

各类专题梳理

网站导航栏

X
返回顶部