You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 23:36:01