Декодирование 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 и аналогичных серверов, при условии, что вы работали с любыми проблемами, связанными с происхождением.