Reputation: 3
I have an audio visualizer I made using the web audio API. It works on PC, and it did work on iOS until I updated to 13.3.
I don't know what is causing it not to work. All I know is that it only happens on the newer versions of iOS.
Here is my jsfiddle. https://jsfiddle.net/r1dobj07/
document.getElementById("btn").addEventListener("click", function() {
var canvas = document.getElementById('canvas');
var audio = new Audio();
audio.loop = true;
audio.autoplay = false;
audio.crossOrigin = "anonymous";
audio.addEventListener('error', function(e) {
console.log(e);
});
audio.src = "https://greggman.github.io/doodles/sounds/DOCTOR VOX - Level Up.mp3";
//audio.play();
audio.controls = true;
document.getElementById("wrapper").append(audio);
var player = document.getElementById('audio_player');
var context = new(window.AudioContext || window.webkitAudioContext)();
var src = context.createMediaElementSource(audio);
var analyser = context.createAnalyser();
src.connect(analyser);
analyser.fftSize = 32;
analyser.connect(context.destination);
var ctx = canvas.getContext("2d");
var bufferLength = analyser.frequencyBinCount;
var dataArray = new Uint8Array(bufferLength);
var WIDTH = canvas.width;
var HEIGHT = canvas.height;
var barWidth = (WIDTH / bufferLength) * 0.5;
var barHeight;
var x = 0;
function renderFrame() {
requestAnimationFrame(renderFrame);
x = 0;
analyser.getByteFrequencyData(dataArray);
ctx.fillStyle = "rgba(0,0,0,0)";
ctx.clearRect(0, 0, WIDTH, HEIGHT);
for (var i = 0; i < bufferLength; i++) {
barHeight = dataArray[i];
if (barHeight === 0) {
barHeight = 20;
}
var barHeightScaled = barHeight / 250;
var barHeightScaled2 = barHeightScaled * HEIGHT;
var newHeight = HEIGHT - barHeightScaled2;
var r = 111;
var g = 121;
var b = 180;
CanvasRenderingContext2D.prototype.roundRect = function(x, y, w, h, r) {
if (w < 2 * r) r = w / 2;
if (h < 2 * r) r = h / 2;
this.beginPath();
this.moveTo(x + r, y);
this.arcTo(x + w, y, x + w, y + h, r);
this.arcTo(x + w, y + h, x, y + h, r);
this.arcTo(x, y + h, x, y, r);
this.arcTo(x, y, x + w, y, r);
this.closePath();
return this;
}
ctx.fillStyle = "rgb(" + r + "," + g + "," + b + ")";
ctx.roundRect(x, newHeight / 2, barWidth, barHeightScaled2, 50).fill();
x += barWidth + 4;
}
}
renderFrame();
}
);
On PC it works fine. On my iPhone, it doesn't play the audio. I can see the bars are rendered on iOS, but they aren't moving, as no audio is being outputted.
Upvotes: 0
Views: 2952
Reputation: 31
I have the same problem, my test setup is on iOS 13.6.1. It is very bad! I am a WebAudio expert so here is what I found.
When our music app is set in background mode (user switches to another app or screen turned off), all the WebAudio AudioContexts inside the WkWebView freeze after exactly 27 seconds. At that moment, our app turns silent and the AudioContext.currentTime stops incrementing despite that the AudioContext.state is still "running". That's the only way to detect that broken WebAudio state I found.
And the worst part is that bringing back the app to the foreground don't resuscitate the frozen AudioContexts, they are dead forever, I tried. You can recreate new AudioContexts though but in our case we simply restart all the app, which means the user lost his progress. This is a quick fix waiting for the real iOS fix.
It is obviously a big bug introduced in iOS 13. Also I can see that this issue is almost one year old and it has not been fixed, that's not respectful for all HTML5 developer here, that's sad! Hoping someone competent will take this issue seriously.
Upvotes: 0
Reputation: 9066
Unfortunately there is currently a bug in iOS related to the MediaStreamAudioSourceNode. It causes a MediaElement to stop once you connect it to an AudioContext.
Upvotes: 1