Я сформулировал свой заголовок и теги так, чтобы их можно было искать как для видео, так и для аудио, поскольку этот вопрос не относится только к одному из них. Мой конкретный случай касается только аудио, поэтому мое тело вопроса будет написано специально для этого.
Во-первых, общая картина:
Я отправляю аудио на несколькоP2P клиенты, которые будут подключать и отключать случайные интервалы. Аудио, которое я посылаю, является потоком, но каждому клиенту нужна только часть потока, откуда он подключен. Вот как я решил, что:
- Каждый {тайм-аут} (например, 1000 мс) создайте новый звуковой BLOB-объект
- BLOB-файл будет полным аудиофайлом со всеми метаданными, которые должны бытьиграбельно
- Как только будет создан BLOB-объект, преобразуйте его в буфер массива (улучшенная поддержка браузера) и загрузите на клиент через WebRTC (или WebSockets, если они не поддерживают)
Это хорошо работает. Задержка есть, но если вы удерживаете тайм-аут достаточно низким, это нормально.
Теперь мой вопрос:
Как я могу воспроизводить свой «поток», не имеялюбая задержка звука?
Я говорю поток, но я не реализовал его с помощью API Streams, это очередь больших двоичных объектов, которая обновляется каждый раз, когда клиент получает новые данные.
Я пробовал много разных вещей, таких как:
- Создание BufferSource и объединение двух BLOB-объектов (преобразованных в AudioBuffers) с последующим воспроизведением этого
- Передача реального потока изПотоковый API для клиентов вместо BLOB-объектов
- Последовательное воспроизведение BLOB-объектов, опираясь на
ended
событие - Загрузка следующего BLOB-объекта во время воспроизведения текущего BLOB-объекта
У каждого есть проблемы,трудности или все же приводят к звуковой задержке.
Вот моя самая последняя попытка:
let firstTime = true;
const chunks = [];
Events.on('audio-received', ({ detail: audioChunk }) => {
chunks.push(audioChunk);
if (firstTime && chunks.length > 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", () => {
nextAudio.play()
nextAudioStartTime = new Date();
if (chunks.length) {
currentAudio.src = URL.createObjectURL(chunks.shift());
}
});
nextAudio.addEventListener("ended", () => {
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 мс.
Вы можете мне помочь?
Я могу попытаться создать воспроизводимый пример, если это поможет.