WebKit Audio distorts on iOS 6 (iPhone 5) first time after power cycling

前端 未结 3 830
再見小時候
再見小時候 2020-12-14 11:56

I\'ve been struggling with an elusive audio distortion bug using webkitAudioContext in HTML5 under iOS 6. It can happen in other circumstances, but the only way I can get 1

相关标签:
3条回答
  • 2020-12-14 12:03

    An npm package is online to fix this:

    https://github.com/Jam3/ios-safe-audio-context

    npm install ios-safe-audio-context
    
    0 讨论(0)
  • 2020-12-14 12:09

    I have been having similar problems, even on iOS 9.2.

    Even without a <video> tag, playback is distorted when first playing audio on the page after cold boot. After a reload, it works fine.

    The initial AudioContext seems to default to 48 kHz, which is where distortion is happening (even with our audio at 48 kHz sample rate). When playback is working properly, the AudioContext has a sample rate of 44.1 kHz.

    I did find a workaround: it is possible to re-create the AudioContext after playing an initial sound. The newly-created AudioContext seems to have the correct sample rate. To do this:

    // inside the click/touch handler
    var playInitSound = function playInitSound() {
        var source = context.createBufferSource();
        source.buffer = context.createBuffer(1, 1, 48000);
        source.connect(context.destination);
        if (source.start) {
            source.start(0);
        } else {
            source.noteOn(0);
        }
    };
    
    playInit();
    if (context.sampleRate === 48000) {
        context = new AudioContext();
        playInit();
    }
    
    0 讨论(0)
  • 2020-12-14 12:24

    I found a related bug with HTML5 video and think I discovered the root of the problem.
    I noticed that if you play a video using a <video> tag, it sets the context.sampleRate value to whatever the video's audio was encoded at. It seems as if iOS Safari has one global sampleRate that it uses for everything. To see this, try the following:

    // Play a video with audio encoded at 44100 Hz
    video.play();
    
    // This will console log 44100
    var ctx = new webkitAudioContext();
    console.log(ctx.sampleRate);
    
    // Play a video with audio encoded at 48000 Hz
    video2.play();
    
    // This will console log 48000
    var ctx = new webkitAudioContext();
    console.log(ctx.sampleRate);
    

    This global sample rate appears to persist across page loads and is shared between tabs and browser instances. So, playing a youtube video in another tab could break all your decoded audio.

    The audio becomes distorted when it is decoded at one sample rate and played at another one.

    1. Decode audio and store the buffer
    2. Do something to change the sample rate, such as playing a video or audio file
    3. Play buffer (distorted)

    I don't know why it's happening after a cold start. If I had to guess, it's that Safari doesn't initialize this global sample rate until you try to use it.

    The problem is still there on iOS 7, so I don't think a fix is coming anytime soon. We're stuck with hacks in the mean time like checking for a changed sample rate.

    0 讨论(0)
提交回复
热议问题