Я работаю над (веб-) анимацией, которая двигает губами с воспроизводимой аудио речью. Я использую Javascript getByteFrequencyData () для определения низких и высоких частот и очень реалистичного c движения рта.
Код отлично работает во всех Windows браузерах, на android (chrome), но я сталкиваюсь с огромной проблемой на IOS с Safari, а также с Chrome: getByteFrequencyData всегда возвращает постоянное значение. Ошибки не регистрируются в консоли, поэтому все объекты создаются, звук воспроизводится (как запущено в контексте взаимодействия с пользователем).
ОБНОВЛЕНИЕ: Я тестировал Safari, Firefox, Edge и Chrome, все с тот же результат.
ОБНОВЛЕНИЕ2: все приложение работает не в Safari OSX, а в Chrome OSX. На Chrome OSX (Catalina) getByteFrequencyData также работает хорошо. Кажется, это проблема iOS.
Вот как я запускаю аудиосистему (один раз):
...
audio = document.getElementById("audio");
audio.addEventListener('ended', onAudioPlayed, false);
var AudioContext = window.AudioContext || window.webkitAudioContext;
ctx = new AudioContext();
audioSrc = ctx.createMediaElementSource(audio);
audioSrc.connect(ctx.destination);
analyser = ctx.createAnalyser();
frequencyData = new Uint8Array(analyser.frequencyBinCount);
...
И я использую метод requestAnimationFrame-Method для подачи анимации:
...
audio.src = "audio/" + audioQueue.shift();
console.log("play: "+audio.src);
audio.type = "audio/mp3";
analyser.fftSize = 64;
analyser.smoothingTimeConstant = 0.4;
analyser.minDecibels = -80;
analyser.maxDecibels = -20;
audioSrc.connect(analyser);
analyser.getByteFrequencyData(frequencyData);
function renderFrame() {
if (!audio.paused) requestAnimationFrame(renderFrame);
analyser.getByteFrequencyData(frequencyData);
avgHigh = 0;
avgLow = 0;
count = analyser.frequencyBinCount;
//console.log("rendermund " + frequencyData[0]);
for (i = 0; i < count; i++) {
if (i < count/4)
avgLow += frequencyData[i]
else
avgHigh += frequencyData[i];
}
console.log("rendermund " + avgHigh + "/" + avgLow);
avgLow = avgLow/2000;
avgHigh = avgHigh/2000;
if (avgLow > 1) avgLow = 1;
if (avgHigh > 1) avgHigh = 1;
mund(avgHigh,avgLow); // Here I draw the mouth...
}
audio.load();
audio.play();
renderFrame();
...
Есть ли альтернативный способ получения живой информации о сэмплах, которые воспроизводятся в данный момент?
Странно то, что я не получаю никаких сообщений об ошибках - getByteFrequencyData () возвращает массив ожидаемого размера, но с постоянными значениями (0) на iOS. Я протестировал последнюю версию IO на Ipad Air, IPad Air 2 и iPad 5-го и 6-го поколения с одинаковым результатом.