AudioContext 创建后默认处于 suspended 状态,必须通过用户真实交互触发 resume() 才能进入 running 状态;需兼容前缀、监听 state 变化、区分 suspend/resume 与节点播放控制。

AudioContext 不是“创建即可用”,它一出生就处于 suspended 状态,必须经用户真实交互(比如点击、触摸)触发 resume() 才能进入 running,否则所有音频操作都会静默失败或直接报错。
创建时就得考虑兼容与时机
现代浏览器要求 AudioContext 必须用标准方式创建,并兼顾旧版 Safari/Chrome 的前缀兼容:
- 统一写法:
const audioCtx = new (window.AudioContext || window.webkitAudioContext)(); - 不要在页面加载完成(
DOMContentLoaded)或定时器里创建后立刻调用start()或decodeAudioData()—— 此时上下文大概率仍是 suspended,操作无效 - 可以提前创建实例(比如初始化阶段),但所有依赖音频图的操作(建 Oscillator、连 Analyser、解码 buffer)必须等 resume 完成后再执行
resume() 是唯一合规的“启动钥匙”
它不是可选优化,而是浏览器强制策略下的必要步骤。不调用 resume,你就无法调度播放、更新 currentTime,甚至 analyser.getByteFrequencyData() 也会返回全 0:
- 必须绑定在用户手势事件中:click、touchstart、keydown(非自动触发的 keyup 或 input)
- 推荐入口:
button.addEventListener('click', () => audioCtx.resume());移动端注意加e.preventDefault()防止误触滚动 -
resume()返回 Promise,建议 await 处理,成功后再进行后续音频操作 - 失败时会 reject,应 catch 并提示用户“请点一下屏幕启用声音”
state 变化需要主动监听和响应
AudioContext 的状态可能动态变化,尤其在移动端切后台、系统休眠后常被浏览器自动 suspend:
立即学习“前端免费学习笔记(深入)”;
- 用
audioCtx.onstatechange = () => { console.log(audioCtx.state); }监听状态切换 - 监听到
'suspended'时,可显示轻量提示(如浮动图标+文字),引导用户再次交互唤醒 - 监听到
'running'后,可立即恢复可视化渲染、重播提示音、或继续未完成的 decode 流程 - 避免假设 state 一劳永逸 —— 它不是只设一次的静态属性
别混淆 suspend/resume 和播放控制
这两个方法管理的是整个音频上下文的执行资格,不是某段音频的暂停/继续:
-
audioCtx.suspend()会让所有节点停止调度、currentTime 冻结,适合省电或临时冻结整个音频图 - 想控制单个音源(比如 oscillator 或 buffer source)的启停,该用
node.start()/stop()或gainNode.gain.setValueAtTime() - 误把 resume 当作“播放按钮”会导致逻辑混乱 —— 它解决的是“能不能干活”,不是“干不干活”



















