音频可视化
先看效果
音频上下文
// 创建音频上下文
const audCtx = new AudioContext()
// 创建音频源节点
const source = audCtx.createMediaElementSource(audioEl)
const analyser = audCtx.createAnalyser() // 创建分析器节点
analyser.fftSize = 512
// 创建数组,接受分析器数据
const dataArray = new Uint8Array(analyser.frequencyBinCount) //frequencyBinCount 的值固定为 AnalyserNode 接口中 fftSize 值的一半
source.connect(analyser) // 分析器连接音频源节点
analyser.connect(audCtx.destination) // 分析器连接输出设备
实践-音乐可视化
首先实现html页面
<canvas></canvas>
<audio src="./music.mp3" controls></audio>
初始化canvas
const cvs = document.querySelector('canvas')
const ctx = cvs.getContext('2d')
function initCvs() {
cvs.width = window.innerWidth
cvs.height = window.innerHeight / 2
}
initCvs()
初始化音视频上下文
let isInit = false
let dataArray, analyser
audioEl.onplay = function () {
console.log(666);
if (isInit) return
// 初始化
// 创建音频上下文
const audCtx = new AudioContext()
// 创建音频源节点
const source = audCtx.createMediaElementSource(audioEl)
analyser = audCtx.createAnalyser() // 创建分析器节点
analyser.fftSize = 512
// 创建数组,接受分析器数据
dataArray = new Uint8Array(analyser.frequencyBinCount)
source.connect(analyser) // 分析器连接音频源节点
analyser.connect(audCtx.destination) // 分析器连接输出设备
isInit = true
}
绘制
function draw() {
requestAnimationFrame(draw)
// 清空画布
const { width, height } = cvs
ctx.clearRect(0, 0, width, height)
if (!isInit) return
// 让分析器节点分析出数据到数组中
analyser.getByteFrequencyData(dataArray)
const len = dataArray.length
const barWidth = width / len
ctx.fillStyle = '#78c5f7'
for (let i = 0; i < len; i++) {
const data = dataArray[i]
const barHeight = data / 255 * height
const x = i * barWidth
const y = height - barHeight
ctx.fillRect(x, y, barWidth, barHeight)
}
}
draw()
略微优化一下
function draw() {
requestAnimationFrame(draw)
// 清空画布
const { width, height } = cvs
ctx.clearRect(0, 0, width, height)
if (!isInit) return
// 让分析器节点分析出数据到数组中
analyser.getByteFrequencyData(dataArray)
const len = dataArray.length / 2.5
const barWidth = width / len / 2
ctx.fillStyle = '#78c5f7'
for (let i = 0; i < len; i++) {
const data = dataArray[i]
const barHeight = data / 255 * height
const x1 = i * barWidth + width / 2
const x2 = width / 2 - i * barWidth
const y = height - barHeight
ctx.fillRect(x1, y, barWidth - 2, barHeight)
ctx.fillRect(x2, y, barWidth - 2, barHeight)
}
}
扩展-麦克风输入的音频进行可视化
<button onclick="startRecording()">开始录音</button>
function startRecording() {
navigator.mediaDevices.getUserMedia({
audio: true
})
.then(stream => {
const audCtx = new AudioContext()
// 创建音频源节点
const source = audCtx.createMediaStreamSource(stream)
analyser = audCtx.createAnalyser() // 创建分析器节点
analyser.fftSize = 512
// 创建数组,接受分析器数据
dataArray = new Uint8Array(analyser.frequencyBinCount)
source.connect(analyser) // 分析器连接音频源节点
isInit = true
})
.catch(err => {
console.log('访问麦克风失败:' + err.message);
});
}