其实从事前端开发以来没有碰到过这样到需求,只是在前段时间看到一些音乐播放器的界面很漂亮,就想 web 端能否实现这样的效果呢,网上找了一下,发现已经有了很多案例了,这里只是自己实践一下.
目标效果
基本原理
我们知道一般可视化都是基于数据实现的,那么音频可视化可以分为两个部分来实现:
将音频转换为数据(流);
用 canvas、svg 或者其他方式将拿到的数据进行可视化;
第二步不用多说,有一定的 canvas 或者 svg 基础问题不大,那问题是第一步怎么将音频转换为数据(流)呢,幸运的是 html 5 提供流相关 api,就是 Web Audio.
Web Audio API 使用户可以在音频上下文(AudioContext)中进行音频操作,具有模块化路由的特点。在音频节点上操作进行基础的音频, 它们连接在一起构成音频路由图。
代码实现
既然了解流基本原理,就开始实践吧.这里我没有使用第三方框架/库,没必要搞得很复杂.
AudioItem
AudioItem, 这个类应该有开始、暂停、停止、播放完成以及让外部获取一些状态,如:获取音频时长、当前播放时长、当前播放状态和当前需要绘制的音频图像等方法.具体看代码
1 | class AudioItem { |
这里我们使用了 H5 的 AudioContext,具体资料可以到 MDN 上去了解,需要注意到有一下几个地方:
1、AudioBufferSourceNode 对象只能使用一次,所以每次暂停/停止后都要重新创建,之前都是在解码音频都回调中实现,发现音频解码耗时严重,会产生严重卡顿,所以后面将解码后的 buffer 缓存
2、已播放时长的问题,这个 MDN 上说的也不清除,后来在 stock overflow 上才找到解决方案.具体见代码注释.猜测实际播放时间(特别是暂停/停止后)为从播放开始的时间减去总暂停的时间,这个地方比较绕
3、音频 Uint8Array 的操作,因为 Uint8Array 也只能使用一次,所以每次都是使用当前 Uint8Array 的副本,相关 api 可以查看Uint8Array - JavaScript | MDN
CanvasItem
canvas 绘制图像,这里只暴露了两个方法,初始化和绘制,毕竟一进来什么都没有就比较奇怪,具体代码如下:
1 | class CanvasItem { |
canvas 画图没什么好说都,这里只有一个很重要都点,canvas 旋转绘图,每次旋转绘图完成后要将中心点移动回之前都位置,否则图像会越来越乱.
项目地址
项目地址: https://github.com/qiangqiang93/audio-visualization
在线 demo: 音频可视化播放器 demo
参考文章:
javascript - Web Audio API resume from pause - Stack Overflow
web-audio-api 可视化音乐播放器,实现暂停切换歌曲功能,粉色系专场~ - 简书
[越努力,越幸运!]