基于Web Audio API与Canvas的音频可视化在Safari浏览器不生效问题
问题诱因
- 老版本Safari的Web Audio Context(包括带webkit前缀的实现)在用户手势触发创建后,默认处于suspended 挂起状态。Chrome、Opera等浏览器会自动将用户交互回调中创建的Context切换为running状态,但Safari需要手动调用
resume()方法激活,否则整个音频处理链路不会实际运行,Analyser节点无法获取音频流数据,getByteTimeDomainData只能返回默认填充的128值。 - 部分Safari版本要求音频处理节点的连接操作必须在Context处于running状态后执行,否则连接的Analyzer节点不会接收到音频数据流。
修复方案
修改createAudio函数,在创建Context后手动触发恢复,等恢复完成后再执行节点连接逻辑即可:
function createAudio() { if (MyNamespace.firstUserGesture) { if ('webkitAudioContext' in window) { MyNamespace.ctx = new webkitAudioContext() console.log('webkitAudioContext() is available.') } else if ('AudioContext' in window) { MyNamespace.ctx = new AudioContext() console.log('AudioContext() is available.') } else { console.log('Web Audio API is not available.') return } // 新增Safari兼容:手动恢复Context到运行状态 MyNamespace.ctx.resume().then(() => { MyNamespace.audio.source = MyNamespace.ctx.createMediaElementSource(MyNamespace.audio.el) MyNamespace.audio.analyzer = MyNamespace.ctx.createAnalyser() // 可选:显式设置fftSize避免不同浏览器默认值差异 MyNamespace.audio.analyzer.fftSize = 2048 MyNamespace.audio.source.connect(MyNamespace.audio.analyzer) MyNamespace.audio.source.connect(MyNamespace.ctx.destination) console.log('Web Audio API is all set') setupCanvas() }) } MyNamespace.firstUserGesture = false }
可选优化:如果存在用户播放时Context再次被挂起的场景,可以在handleClick播放逻辑前增加Context状态判断:
function handleClick() { createAudio() // 新增:播放前确保Context处于运行状态 if (MyNamespace.ctx && MyNamespace.ctx.state === 'suspended') { MyNamespace.ctx.resume() } if (MyNamespace.audio.el.paused) { MyNamespace.audio.el.play() } else { MyNamespace.audio.el.pause() } }
内容的提问来源于stack exchange,提问作者Megidd
相关产品推荐
相关产品推荐

