Как последовательно воспроизводить медиа-файлы без видимых разрывов?

Как воспроизводить медиафайлы последовательно без видимого перерыва?

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


Во-первых, большая картина:

Я посылаю аудио нескольким клиентам P2P, которые будут подключаться и отключаться через произвольные интервалы. Аудио, которое я посылаю, является потоком, но каждому клиенту нужна только часть потока, откуда он подключен. Вот как я это решил:

  • Каждое {время ожидания} (например, 1000 мс) создайте новый звуковой объект
    • Blob будет полным аудиофайлом, со всеми метаданными, которые он должен воспроизводить
  • Как только создается BLOB-объект, преобразуйте его в буфер массива (улучшенную поддержку браузера) и загрузите на клиент через WebRTC (или WebSockets, если они не поддерживают)

Это хорошо работает. Задержка есть, но если вы держите тайм-аут достаточно низким, это нормально.


Теперь мой вопрос:

Как я могу воспроизвести свой «поток» без какой-либо звуковой задержки?

Я говорю «поток», но я не реализовал его с помощью API Streams, это очередь больших двоичных объектов, которая обновляется каждый раз, когда клиент получает новые данные.

Я пробовал много разных вещей, как:

  • Создание BufferSource и объединение двух BLOB-объектов (преобразованных в AudioBuffers) с последующим воспроизведением этого
  • Передача фактического потока из Stream API клиентам вместо BLOB-объектов
  • Последовательное проигрывание капель, опираясь на ended событие
  • Загрузка следующего BLOB-объекта во время воспроизведения текущего BLOB-объекта

Каждый из них имеет проблемы, трудности или все еще приводит к слышимой задержке.

Вот моя последняя попытка сделать это:

 let firstTime = true; const chunks = []; Events.on('audio-received', ({ detail: audioChunk }) ={amp}gt; { chunks.push(audioChunk); if (firstTime {amp}amp;{amp}amp; chunks.length {amp}gt; 2) { const currentAudio = document.createElement("audio"); currentAudio.controls = true; currentAudio.preload = 'auto'; document.body.appendChild(currentAudio); currentAudio.src = URL.createObjectURL(chunks.shift()); currentAudio.play(); const nextAudio = document.createElement("audio"); nextAudio.controls = true; nextAudio.preload = 'auto'; document.body.appendChild(nextAudio); nextAudio.src = URL.createObjectURL(chunks.shift()); let currentAudioStartTime, nextAudioStartTime; currentAudio.addEventListener("ended", () ={amp}gt; { nextAudio.play() nextAudioStartTime = new Date(); if (chunks.length) { currentAudio.src = URL.createObjectURL(chunks.shift()); } }); nextAudio.addEventListener("ended", () ={amp}gt; { currentAudio.play() currentAudioStartTime = new Date(); console.log(currentAudioStartTime - nextAudioStartTime) if (chunks.length) { nextAudio.src = URL.createObjectURL(chunks.shift()); } }); firstTime = false; } }); 

Полученное audio-received событие вызывается каждые ~ 1000 мс. Этот код работает; он воспроизводит каждый «фрагмент» после того, как проигрывался последний, но в Chrome задержка ~ 300 мс очень слышна. Он воспроизводит первый фрагмент, затем замолкает, затем воспроизводит второй, и так далее. На Firefox задержка составляет 50 мс.

Можешь мне помочь?

Я могу попытаться создать воспроизводимый пример, если это поможет.

Понравилась статья? Поделиться с друзьями:
JavaScript & TypeScript
Adblock
detector