javascript - iOS 13+ 设备的网络音频音量衰减

标签 javascript ios progressive-web-apps web-audio-api

我希望 Stack Overflow 社区中的某个人能够为此提供解决方法。很长一段时间以来,它一直是我身边的一根刺。
我的要求很简单:淡入音量以在页面上播放音频。
使用 javascript 有几种方法可以做到这一点:

  • 更新 HTMLAudioElement 上的“volume”属性. 这对于 iOS 设备根本不起作用,因为该属性对于操作系统是只读的。
  • 使用网络音频 API AudioContext.createMediaElementSource()GainNode . 这目前有效,但声音输出通常会失真 - 裂纹和爆裂声会破坏任何流式音频的体验。这不是由 AudioContext 使用不同的采样率引起的。
  • 使用网络音频 API AudioBuffer通过 XMLHttpRequest 下载的文件与 arraybuffer响应类型。 这似乎根本没有音量。它适用于模拟器,但不适用于物理设备。

  • 这三种方法几乎适用于任何设备上的任何浏览器,但现代 iOS 设备除外。 13 之前的 iOS 版本适用于方法 2 或 3。我并不是说所有的阴谋论者,但苹果是否会故意破坏 PWA 支持以将更多收入输送到他们的应用商店?

    最佳答案

    TL;DR 你所需要的就在这个片段中(希望如此)
    我有这个片段,你可以试试,告诉我它是否适合你:

    // input
    const FADE_IN_DURATION = 10
    const url = '/path/to/audio.mp3'
    
    // setup
    const context = /** @type {AudioContext} */(new (window.AudioContext || window.webkitAudioContext)())
    const gainNode = context.createGain()
    gainNode.connect(context.destination)
    gainNode.gain.value = 0
    
    // fetch
    const response = await fetch(url)
    const audioData = await response.arrayBuffer()
    const buffer = await new Promise((resolve, reject) => {
        context.decodeAudioData(audioData, resolve, reject)
    })
    
    // connect
    const source = context.createBufferSource()
    source.buffer = buffer
    source.connect(gainNode)
    
    // play
    const startTime = context.currentTime
    gainNode.gain.linearRampToValueAtTime(1, startTime + FADE_IN_DURATION)
    source.start(startTime)
    
    关键点
  • GainNodecontext.createGain() 返回让您访问“增益”AudioParam .和AudioParam有一个名为 linearRampToValueAtTime 的方法这完全符合您的要求
  • 高于 1 的增益值会产生一些“失真”,因为“音量峰值”开始超过最大可能值。因此,如果您只想要平滑的淡入,请保持在 0 之间。和 1 .
  • 我正在做的“接线”是非常基本的AudioBufferSourceNode --> GainNode --> AudioContext

  • 实际工作脚本
    上面的代码片段并不能真正开箱即用,因为您需要
  • 处理异步/等待的函数,
  • 以及开始播放音频上下文的用户输入)。
    所以这里有所有正确的包装:

  • // input
    const FADE_IN_DURATION = 10
    const url = 'https://upload.wikimedia.org/wikipedia/commons/d/de/Lorem_ipsum.ogg'
    
    // setup
    const context = /** @type {AudioContext} */ (new(window.AudioContext || window.webkitAudioContext)())
    const gainNode = context.createGain()
    gainNode.connect(context.destination)
    gainNode.gain.value = 0
    
    // fetch
    ;(async function() {
      const response = await fetch(url)
      const audioData = await response.arrayBuffer()
      const buffer = await new Promise((resolve, reject) => {
        context.decodeAudioData(audioData, resolve, reject)
      })
    
      // user input necessary
      document.getElementById('text').textContent = "Ready. Click anywhere to start audio."
      document.addEventListener('click', () => {
        document.getElementById('text').textContent = "Now playing..."
    
        // connect
        const source = context.createBufferSource()
        source.buffer = buffer
        source.connect(gainNode)
    
        // play
        const startTime = context.currentTime
        gainNode.gain.linearRampToValueAtTime(1, startTime + FADE_IN_DURATION)
        source.start(startTime)
      }, {
        once: true
      })
    })()
    <div id="text">Loading file...</div>

    关于javascript - iOS 13+ 设备的网络音频音量衰减,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68054650/

    相关文章:

    ios - 未调用子类覆盖方法

    ios - Swift 错误无法转换类型 '(AFHTTPRequestOperation?, AnyObject?) 的值 -> ()

    progressive-web-apps - 渐进式 Web 应用程序 "Manifest does not contain a suitable icon"

    javascript - 如何在 Web 应用程序上获取键盘高度

    javascript - 替换字符串(url)中的一些字符

    javascript - Node Express 处理来自外部 api 的身份验证 token

    ios - 将核心数据捆绑到 tableviewcontroller (他自己在导航 Controller 中(他自己在 tabbarcontroller 中))

    javascript - PWA : check if pwa is installed, navigator.getInstalledRelatedApps() 返回空数组

    javascript - message.content 在 Discord.js v14 中没有任何值(value)

    javascript - Marquee 在 IE 中拖动我的 css <ul> 内容在 chrome 中完美工作