Декодирование HTTP Audio Stream из Icecast с минимальной задержкой

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

Наивным решением было бы просто получить доступ http://myhostname:8000/my_mountpoint чтобы получить поток, но <audio> tag выполняет внутреннюю буферизацию перед воспроизведением и приводит к довольно высокой задержке.

Текущее решение: я использовал ReadableStreams API для декодирования (используя decodeAudioData Web Audio API) и воспроизводить фрагменты данных, перенаправляя декодированные данные к месту назначения аудиоконтента (внутренние динамики). Это работает и значительно снижает задержку.

Проблема: этот API потоков, будучи экспериментальным, должен технически работать на последних версиях Chrome, Safari, Opera, FF (после установки определенного флага). Однако у меня проблемы с decodeAudioData во всех других браузерах, кроме Chrome и Opera. Я считаю, что FF и Safari не могут декодировать частичные данные MP3, потому что я обычно слышу короткую активацию динамиков, когда начинаю потоковую передачу. На Safari обратный вызов на успешном decodeAudioData никогда не звонят, а FF просто говорит EncodingError: The given encoding is not supported.

Есть ли какие-то обходные пути, если я хочу, чтобы он хотя бы работал на Safari и FF? Это decodeAudioData реализация в Chrome и Safari на самом деле отличается, так что одна работает на частичном MP3, а другая нет?

2 ответа

Не используйте Icecast, если вам нужна задержка менее секунды!

Не используйте Icecast, если вам нужна задержка менее 10 секунд и вы не имеете полного контроля над всей цепочкой программного обеспечения и сети!

Да, это ответ, а не комментарий. Icecast не предназначен для таких случаев использования. Он был спроектирован для несинхронной передачи данных по протоколу HTTP от 1 к n.

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

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

Как упомянул @Brad, Opus отлично подходит для малой задержки. Я написал декодер WASM Opus с низкой задержкой, который можно использовать с Streams, и запустил еще одну демонстрацию, которая демонстрирует, как воспроизводить частичные файлы с decodeAudioData():

  • опус-стрим-декодер готов к производству
  • fetch-stream-audio- это необслуживаемая демонстрация POC, которая должна указывать вам правильное направление.

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

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

  • HTTP Progressive (тип потоковой передачи, используемый Icecast и т. П.), Работает через TCP, надежный транспорт. Если пакет потерян, существует некоторая задержка во время его повторной передачи клиенту, прежде чем данные будут доставлены в браузер. Это гарантирует, что каждый бит звука будет слышен по порядку, но может вызвать задержку. Для малой задержки обычно используются UDP-пакеты, так что любые потерянные пакеты можно просто пропустить, а не ждать, что вызовет сбой, но клиент снижает задержку.

  • MP3 не является хорошим кодеком для малой задержки. Есть лучшие кодеки, такие как Opus, которые более эффективны и могут генерировать меньшие сегменты.

  • Как вы уже видели, клиенты будут буферизовать больше по умолчанию при потоковой передаче по HTTP.

Однако в идеальных условиях я использовал потоковую передачу HTTP Progressive с задержкой менее 250 мс в Chrome с настраиваемым сервером. Могу поспорить, вы могли бы получить аналогичную производительность из Icecast, если бы вы отключили буферизацию на стороне сервера и использовали другой кодек.

Однако у меня проблемы с decodeAudioData во всех других браузерах, кроме Chrome и Opera. Я считаю, что FF и Safari не могут декодировать частичные данные MP3

Да, decodeAudioData() предназначен для декодирования всего файла. Вам будет сложно декодировать произвольно сегментированные фрагменты с точностью до выборки.

К счастью, есть способ сделать то, что вы хотите... Расширения MediaSource.

https://developer.mozilla.org/en-US/docs/Web/API/Media_Source_Extensions_API

По сути, вы можете использовать тот же интерфейс ReadableStream и передать данные в SourceBuffer, чтобы в итоге воспроизвести их как обычный <audio> тег. Это работает с обычным звуком MP3 от Icecast и аналогичных серверов, при условии, что вы работали с любыми проблемами, связанными с происхождением.

Другие вопросы по тегам