webkitAudioContext on iOS (15.4.1) pitch fluctuations with MediaElementSource

300 views Asked by At

I am making a website that plays mp3 audio and then fades out after X seconds. I had this working using a regular audio tag implementation by manipulating the volume at an interval, but this solution doesn't work on iOS because volume is a readonly property. I discovered that this could be achieved using the AudioContext api, but that I would need to use webkitAudioContext for Safari/iOS.

I have implemented a solution using context.createMediaElementSource but the audio pitch is all over the place. When the audio first starts playing it's pitched up for a few seconds, and also when you minimize the app and reopen it will pitch up again. I'm guessing it's something to do with the internal clock becoming misaligned so playback is being sped up to accommodate - but either way the app just isn't really usable with this problem.

I have found discussions about other distortion/buzzing issues surrounding this API on iOS but no mention of pitch issues. I found an answer submission here which links to a jsfiddle that exhibits the exact same audio pitch issues.

I have tried an implementation using createBufferSource instead of createMediaElementSource which actually resolves the issue, but managing the audio using that api (checking/setting the current position, checking/setting the pause/playing/stopped state e.t.c) seems impossible.

I've created a CodeSandbox demo and also uploaded a video to demonstrate and you can hear that the pitch shift is extremely obvious. Does anyone know how consistent this will reproduce across iOS devices (I imagine, very consistent) and can anyone suggest a fix/workaround?

2

There are 2 answers

0
JohnLoyd On

Same here. Pitchy for the first few seconds, then back to normal. The simplest implementation just does not work.

<div>    
<div id="playbutton">Play</div>
<audio  id="player" controls src="myaudio.wav"></audio> 
</div>

<script>
   var player = document.getElementById('player');
   var playbutton = document.getElementById('playbutton');
   var playStatus = 'paused';
   var audioSource = audioContext.createMediaElementSource(player);
   
   audioSource.connect(audioContext.destination); 

   playbutton.addEventListener('click',function(ev){

      if( playStatus1 == 'paused'){
      
         audioContext.resume();
         player.play();
         playbutton.innerHTML = "Pause";
         playStatus = 'isPlaying';

      } else {

         player.pause();
         playbutton.innerHTML = "Play";
         playStatus = 'paused';
      }
   });
</script>
0
chrisguttandin On

I guess this was tracked as Bug 239696 on WebKit's issue tracker. It should be fixed by now.