AudioContext实现的音频波形动画在iPhone端无法运行如何解决
iOS Safari 上无法生效的核心原因是苹果系统的浏览器安全策略限制,需要针对以下几个点做适配:
- 必须在用户主动交互事件中触发 AudioContext 初始化与音频播放
iOS Safari 禁止页面自动初始化 AudioContext 或自动播放音频,所有和音频相关的初始化、播放逻辑必须放在click、touchstart这类用户主动触发的事件回调中执行,否则 AudioContext 会一直处于suspended挂起状态,音频流无法被分析器读取。 - 必须显式处理 AudioContext 的挂起状态
初始化之后需要调用resume()方法恢复上下文运行,部分iOS版本即使在交互事件中初始化也可能出现上下文挂起的问题。如果需要兼容静音开关开启的场景,可以在上下文初始化后先播放一段空白音频激活上下文。 - 跨域音频需要配置 CORS 属性
如果音频资源和当前站点不同源,需要给 audio 标签添加crossOrigin="anonymous"属性,iOS Safari 对跨域媒体资源的检查比其他浏览器更严格,没有该属性的情况下分析器无法读取音频流数据,最终波形不会动。 - audio 元素属性配置
需要给audio标签添加playsinline属性,避免iOS自动调用全屏播放器,全屏状态下音频流也可能无法被AudioContext捕获。
适配后的参考代码
// 提前定义全局变量 var audio, context, analyser, source, canvas, ctx, bufferLength, dataArray, WIDTH, HEIGHT, barWidth; // 绑定用户交互事件,示例为页面播放按钮的点击事件 document.querySelector('#playBtn').addEventListener('click', function() { // AudioContext 初始化必须放在交互回调内 context = new(window.AudioContext || window.webkitAudioContext)(); // 主动恢复挂起的上下文 if (context.state === 'suspended') { context.resume(); } audio = new Audio(); // 配置iOS必要的音频属性 audio.crossOrigin = "anonymous"; audio.playsInline = true; source = context.createMediaElementSource(audio); analyser = context.createAnalyser(); canvas = document.getElementById("canvas"); ctx = canvas.getContext("2d"); source.connect(analyser); analyser.connect(context.destination); analyser.fftSize = 256; bufferLength = analyser.frequencyBinCount; dataArray = new Uint8Array(bufferLength); WIDTH = canvas.width; HEIGHT = canvas.height + (canvas.height * 0.7); barWidth = (WIDTH / bufferLength) * 2.5; renderFrame(); audio.src = jQuery("source").attr("src"); audio.play(); }) function renderFrame() { var x = 0; ctx.fillStyle = "#000"; ctx.fillRect(0, 0, WIDTH, HEIGHT); analyser.getByteFrequencyData(dataArray); for (var i = 0; i < bufferLength; i++) { var barHeight = dataArray[i]; var r = barHeight + (25 * (i / bufferLength)); var g = 250 * (i / bufferLength); var b = 50; ctx.fillStyle = "rgb(" + r + "," + g + "," + b + ")"; ctx.fillRect(x, HEIGHT - barHeight, barWidth, barHeight); x += barWidth + 1; } requestAnimationFrame(renderFrame); }
内容的提问来源于stack exchange,提问作者Miro Barsocchi
相关产品推荐
相关产品推荐

