关于Audio API简单介绍
阅读时间:约2 - 3分钟
一切源于一个简单的需求,音乐播放器,一开始就只是写个UI,调用媒体 API,然后加上了通过进度条映射到seek音频进度到功能,再往上加需求的时候,就是音频可视化了。
记得十多年前的电脑上,Windows Media Player、千千静听等音频软件都会有音频可视化的界面,都是各种各样随着音频的变化,绘制不同规律的图案。可是在浏览器中,做音频分析,对于我来说真的有点不可思议,直到我看到了AudioContext,它给音频处理打开了一扇门。
什么是AudioContext
AudioContext 是 Audio API 中的音频上下文,一切对于音频的操作,都发生在 AudioContext。用大家熟悉的东西来说的话 AudioContext 和 Canvas 的上下文是类似的概念。
Audio API 在 W3C 标准中还是草案状态(Web Audio API),但是不少PC现代主流浏览器已经实现了一部分的功能,所以我们还是可以先用Chrome来尝试一番。
创建AudioContext 并且连接音频
// 创建音频上下文,这是一种兼容的写法
let actx = new (window.AudioContext || webkitAudioContext)();
// 我们从网页的audio元素来连接音频
let audio = document.getElementById("didit");
let source = actx.createMediaElementSource(audio);
AudioContext 提供三种方式来提供音频内容
-
AudioContext.createBufferSource()
通过AudioContext.createBuffer创建或AudioContext.decodeAudioData解码音轨来创建内容
-
AudioContext.createMediaElementSource()
通过媒体元素来获取
-
AudioContext.createMediaStreamSource()
通过流媒体获取(如麦克风)
利用Analyzer分析音频内容
// 创建analyzer
let analyzer = actx.createAnalyser();
// 创建用来获取音频数据的缓冲buffer
let bufferLength = analyzer.fftSize;
let dataArray = new Uint8Array(bufferLength);
// 连接analyzer和音频元
source.connect(analyzer)
analyzer.connect(actx.destination)
在使用Analyser的时候,我遇到了一个问题,analyzer没有办法获取到当前播放的内容。但是我注意到了在其他示例中,音频上下文和他的工具集之间建立了连接。
这就引出了Audio API的工作方式,他的工具集和音频上下文的目的地直接,是通过connect耦合的,在使用工具的时候,需要两方互相连接。
我们在这里使用analyzer.connect(actx.destination)
连接音频上下文目的地的原因是,音频的播放信息在AudioContext连接音频元素的时候,就被AudioContext接管了,是它在传输现在播放音频的数据,所以需要如此连接。
一个简单的例子
function getNowText(some) {
analyzer.getByteTimeDomainData(dataArray);
let one = (findMax(dataArray) / 128);
let delta = some - one;
one = delta * 0.618 + one;
c.rotate(0.5,0.5,0);
c.scale(one , one , one );
c.update();
requestAnimationFrame(getNowText.bind(this,one))
}
使用一个我之前写的css3d库(HakeCSS3D)来进行简单的视觉效果,这里我们取音频最大值来作为控制变量,并实时更新。(请忽略我这个充满副作用的写法)
analyzer.getByteTimeDomainData(dataArray);
是用来获取当前时间的音频分析信息,它返回的信息是128为基准值的整数。
实际效果参考:mcube.hustfe.com/ (请在PC现代浏览器下打开)