前端音频可视化Web Audio如何实现(audio,web,开发技术)

时间:2024-05-03 19:26:30 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

实现思路

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

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

  • 创建音频上下文

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

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

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

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

前端音频可视化Web 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);//音频数据处理完毕});});

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

需要明白的是,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"

 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:前端音频可视化Web Audio如何实现的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:Go语言状态机如何实现下一篇:

5 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18