Как установить currentTime в аудиообъекте HTML5, когда аудиофайл находится в сети? - PullRequest
0 голосов
/ 02 сентября 2018

У меня есть аудиоплеер JavaScript с кнопками пропуска вперед / назад 10 секунд. Я делаю это, устанавливая currentTime моего аудиоэлемента:

function Player(skipTime)
{
    this.skipTime = skipTime;
    this.waitLoad = false;

    // initialise main narration audio
    this.narration = new Audio(getFileName(dynamicNarration));
    this.narration.preload = "auto";
    this.narration.addEventListener('canplaythrough', () => { this.loaded();       });
    this.narration.addEventListener('timeupdate',     () => { this.seek();         });
    this.narration.addEventListener('ended',          () => { this.ended();        });
    this.narration.addEventListener('waiting',        () => { this.audioWaiting(); });
    this.narration.addEventListener('playing',        () => { this.loaded();       });
}

Player.prototype = {
    rew: function rew()
    {
        if (!this.waitLoad) {
            this.skip(-this.skipTime);
        }
    },

    ffw: function ffw()
    {
        if (!this.waitLoad) {
            this.skip(this.skipTime);
        }
    },

    skip: function skip(amount)
    {
        const curTime = this.narration.currentTime;
        const newTime = curTime + amount;
        console.log(`Changing currentTime (${curTime}) to ${newTime}`);
        this.narration.currentTime = newTime;
        console.log(`Result: currentTime = ${this.narration.currentTime}`);
    },

    loaded: function loaded()
    {
        if (this.waitLoad) {
            this.waitLoad = false;
            playButton.removeClass('loading');
        }
    },

    audioWaiting: function audioWaiting()
    {
        if (!this.waitLoad) {
            this.waitLoad = true;
            playButton.addClass('loading');
        }
    },
}

(я включаю сюда некоторых слушателей событий, которые я присоединяю, потому что ранее я отлаживал подобную проблему, связанную с конфликтами в слушателях событий. Хотя на этот раз я тщательно отладил прослушиватели событий, я не думаю в этом корень проблемы.)

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

  • Chrome: сбрасывает игровое положение до 0. Конечная строка консоли гласит: currentTime = 0.
  • Safari: вообще не меняет игровую позицию. Последняя строка console.log дает значение для currentTime, равное newTime (даже при том, что позиция игры фактически не меняется).
  • Firefox: пропуск вперед работ; Пропуск в обратном направлении прерывает звук на несколько секунд, затем он начинает воспроизводиться снова за пару секунд до того места, где была точка воспроизведения. В обоих случаях последняя строка console.log дает значение для currentTime, равное newTime

Проблема должна иметь отношение к способу загрузки звука. Я попытался добавить еще одну строку журнала консоли, чтобы показать начальное и конечное значения для buffered.

В Chrome до 2 секунд после текущей позиции воспроизведения. В Safari он идет до ~170 секунд, а в Firefox, похоже, буферизует всю длину звука.

Однако в каждом случае начало объекта buffered составляет 0.

Кто-нибудь знает, что может быть не так?

Ответы [ 3 ]

0 голосов
/ 27 октября 2018

Я нашел решение своей проблемы, если не совсем объяснение.

Мой хостинг-провайдер использует CDN, для которого он должен заменить URL-адреса ресурсов ресурсами другого домена. URL-адреса моих аудио-ресурсов динамически создаются JS, потому что в них есть случайный элемент; как таковой, процесс развертывания, который заменяет URL, не ловил те для моих аудио файлов. Чтобы обойти это, я вручную исключил аудиофайлы из CDN, то есть мог бы ссылаться на них, используя относительные пути к файлам.

Так было, когда у меня возникла эта проблема.

Затем, из-за отдельной проблемы, я выбрал другой подход: я вернул аудиофайлы в CDN и написал функцию для извлечения доменного имени, которое мне нужно было использовать для извлечения файлов. Когда я это сделал, вдруг обнаружил, что все мои проблемы с настройкой currentTime исчезли. Почему-то отсутствие файлов в CDN сильно мешало браузеру загружать их упорядоченным образом.

Если бы кто-нибудь мог добровольно объяснить, почему это могло быть, мне было бы очень любопытно услышать это ...

0 голосов
/ 13 мая 2019

Это решило мою проблему ...

    private refreshSrc() {
      const src = this.media.src;
      this.media.src = '';
      this.media.src = src;
    }
0 голосов
/ 07 сентября 2018

Если ваш браузер не загрузил аудио, то звук не может быть воспроизведен. Браузер не знает ваш аудиофайл, и из-за этого он пытается воспроизвести ваш аудио с самого начала. Может быть, ваш звук может быть только 1 секунда или даже короче.

Решение

Вам нужно дождаться события loadedmetadata, а после него вы можете сыграть свою аудиторию с любой временной позиции. После этого события ваш браузер знает всю необходимую информацию о вашем аудиофайле.

Пожалуйста, измените ваш код следующим образом:

function Player(skipTime)
{
    this.skipTime = skipTime;

    // initialise main narration audio
    this.narration = new Audio(getFileName(dynamicNarration));
    this.narration.preload = "auto";
    this.narration.addEventListener('canplaythrough', () => { this.loaded();       });
    this.narration.addEventListener('timeupdate',     () => { this.seek();         });
    this.narration.addEventListener('ended',          () => { this.ended();        });
    this.narration.addEventListener('waiting',        () => { this.audioWaiting(); });
    this.narration.addEventListener('playing',        () => { this.loaded();       });

    this.narration.addEventListener('loadedmetadata', () => {playButton.removeClass('loading');});

    playButton.addClass('loading');
}

Player.prototype =
{
    rew: function()
    {
        this.skip(-this.skipTime);
    },

    ffw: function()
    {
        this.skip(this.skipTime);
    },

    skip: function(amount)
    {
        var curTime = this.narration.currentTime;
        var newTime = curTime + amount;
        console.log(`Changing currentTime (${curTime}) to ${newTime}`);
        this.narration.currentTime = newTime;
        console.log(`Result: currentTime = ${this.narration.currentTime}`);
    }
};

Но если вы не хотите долго ждать загрузки звука, у вас есть только один вариант: преобразовать все ваши аудиофайлы в формат dataURL, который выглядит следующим образом:

var data = "data:audio/mp3;base64,...

Но в этом случае вам придется ждать загрузки вашей страницы даже больше, чем загрузки одного аудиофайла. А при загрузке аудиофайла это только метаданные и они быстрее.

...