Safari ведет себя очень странно с аудио-тегом HTML5 - PullRequest
0 голосов
/ 13 февраля 2019

Я создаю сайт, где у меня есть аудиоэлемент HTML5, где я использую javascript для динамического обновления источника в зависимости от того, на какую дорожку нажимают пользователи.Это оборачивается веб-аудио API, который выполняет fft и использует его для управления сценой в три js.

Сайт работает правильно в Chrome и Firefox, однако в Safari аудио крайне проблематично.

Первая проблема заключалась в том, что safari не будет принимать источник в качестве дочернего узла аудио, если вы обновляете его динамически, вы должны указать src в теге audio.Я проверяю Safari / IOS в моем js и либо устанавливаю источник звука opus или mp3 в зависимости от результата.Я пытался использовать m4a в качестве формата файла, но он не воспроизводился, несмотря на то, что браузер поддерживает m4a?

Сохраняются следующие проблемы:

Метод .pause() не работает с аудиоэлементом, он просто воспроизводится с начала дорожки снова, когда пользователь возобновляет воспроизведение.

Попытка установить .currentTime, чтобы позволить пользователю пропустить дорожку, ничего не делает в сафари.Однако он читает currentTime в качестве установки позиции игровой головки.

Когда функция animate () (которая вызывается рекурсивно с помощью requestAnimationFrame) работает очень медленно, прежде чем начать что-либо воспроизводить, в течение минутызадержка, то же самое на ios, но не так сильно, и ios не страдает от других проблем.

Число поли на сцене составляет приблизительно 250 тыс., что довольно много, однако было бы странно, если бы поли-счет на холстепроигрывал звук медленно, несмотря на другие проблемы со звуком, в то время как requestAnimationFrame не работает.

Извините за неаккуратный код, у меня не было много времени, чтобы написать это:

const playTrack = (trackNumber) => {
    audio.src = `assets/audio/${trackNumber}.${fileType}`;
    audio.load();
    audio.play();
};

audio.ontimeupdate = () => {
    const left = audio.currentTime * segment;
    playHead.style.width = `${left}px`;
};

playbar.addEventListener("click", (e) => {
    const pos = e.x - container.left;
    audio.currentTime =  pos / segment;
}, false);

    tracks.forEach(track => {
    track.addEventListener("click", (e) => {
        e.preventDefault();

        //pause or load
        if (!audio.paused && nowPlaying === track) {
            //pause track
            audio.pause();
            track.children[0].classList.remove('fa-pause');
            track.children[0].classList.add('fa-play');
        } else if (audio.paused && nowPlaying === track) {
            //play track
            audio.play();
            track.children[0].classList.remove('fa-play');
            track.children[0].classList.add('fa-pause');
        } else {
            //load and play track
            instructions.style.display = "none";
            trackNumber = parseInt(track.getAttribute('data-value'), 10);
            playTrack(trackNumber);
            nowPlaying = track;

            iconFlick(track);
        }

        trackDuration = duration[trackNumber];
        segment = width / trackDuration;

        if (clickFirst === 0) {
            clickFirst = 10;
            setupNodes(audio)
        }

        trackGlobal = track;
    });

const setupNodes = (audio) => {
    const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
    const source = audioCtx.createMediaElementSource(audio);

    analyser = audioCtx.createAnalyser();
    source.connect(analyser);

    analyser.fftSize = 256;
    bufferLength = analyser.frequencyBinCount;
    dataArray = new Uint8Array(bufferLength);

    audioBegin = 1;

    analyser.connect(audioCtx.destination);
};

Веб-сайт, который я создаю, находится здесь, содержит полный исходный код: https://www.missed.flights/

пожалуйста, дайте мне знать, если вы заметите что-нибудь, это поставило меня в тупик.

1 Ответ

0 голосов
/ 06 марта 2019

У вас может быть больше удачи и больше контроля, если вы не используете тег <audio>.Вам нужно будет сделать свою собственную кнопку воспроизведения и ползунок, если вы хотите эти элементы управления.И используйте Web Audio API для загрузки, декодирования и воспроизведения трека.

var url = "whatever.mp3";
var source = audioCtx.createBufferSource();
var buffers = {};

var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';

request.onload = function () {
    audioCtx.decodeAudioData(request.response, function (buffer) {
        source.buffer = buffer;
        source.connect(audioCtx.destination);
        source.start(audioCtx.currentTime);

        // save this for later, so you can replay it without downloading
        buffers[url] = buffer; 

    }, function () {
        console.warn("error loading sound url: " + url);
    });
}
request.send();
...