使用MediaElementSource将audio元素接入Web Audio API,再通过多个BiquadFilterNode(如lowshelf、peaking、highshelf)分别调节不同频段增益,实现可交互网页均衡器。

使用 AudioContext 的 MediaElementSource 实现网页均衡器,核心在于:**把 <audio></audio> 元素接入 Web Audio API,再通过 BiquadFilterNode 对不同频段分别调节增益**。它不修改原始音频文件,而是实时处理播放流,适合做可交互的图形化均衡器(如滑块控制低/中/高音)。
1. 创建 AudioContext 并连接 audio 元素
先获取 <audio></audio> 元素,用 AudioContext.createMediaElementSource() 将其转为音频源节点。注意:必须在用户手势(如点击)后初始化 AudioContext,否则现代浏览器会静音或报错。
const audio = document.querySelector('audio');
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
// 用户点击后才创建 source,避免自动播放限制
document.querySelector('#playBtn').addEventListener('click', () => {
const source = audioCtx.createMediaElementSource(audio);
// 后续接滤波器和目的地
source.connect(analyser); // 可选:加分析节点
analyser.connect(gainNode);
gainNode.connect(audioCtx.destination);
});
2. 添加多个 BiquadFilterNode 控制频段
均衡器本质是多个二阶滤波器并联或串联。常用做法是:用 3–5 个 BiquadFilterNode 分别覆盖低频(~100Hz)、中低频(~500Hz)、中频(~1.5kHz)、中高频(~4kHz)、高频(~10kHz),每个设为 "peaking" 类型,通过 gain 属性动态调节增益(单位:dB)。
-
低频滤波器:
type = "lowshelf"或"peaking",frequency = 100,Q = 1 -
中频滤波器:
type = "peaking",frequency = 1500,Q = 1.5 -
高频滤波器:
type = "highshelf"或"peaking",frequency = 8000,Q = 1 - 所有滤波器
gain.value初始为0(无增强/衰减)
3. 构建滤波链并支持动态调节
推荐将滤波器串联(一个接一个),保证相位一致性;也可用 ChannelSplitter + 多路并行处理(更专业但复杂)。关键是要把每个滤波器的 gain 绑定到 UI 滑块(<input type="range">):
立即学习“前端免费学习笔记(深入)”;
const lowFilter = audioCtx.createBiquadFilter();
lowFilter.type = 'peaking';
lowFilter.frequency.value = 100;
lowFilter.Q.value = 1;
document.querySelector('#low-slider').addEventListener('input', e => {
lowFilter.gain.value = parseFloat(e.target.value); // -12 ~ +12 dB
});
// 接入链路:source → lowFilter → midFilter → highFilter → destination
source.connect(lowFilter);
lowFilter.connect(midFilter);
midFilter.connect(highFilter);
highFilter.connect(audioCtx.destination);
4. 注意事项与优化建议
-
避免削波:多个正增益叠加可能导致输出溢出,可在最后加一个
GainNode做总音量微调,或启用clip提示 -
兼容性:Safari 需用
webkitAudioContext;iOS Safari 对自动播放限制更严,务必由用户手势触发 -
性能:滤波器不宜过多(>7 个可能增加 CPU 负担),
Q值过高(>3)易引发振铃,建议 0.7–2.0 区间 -
重置逻辑:提供“归零”按钮,遍历所有滤波器执行
filter.gain.value = 0



















