Потоковое аудио: получение RTP-потока с помощью Gstreamer - Задержка
В настоящее время я играю с проектом AudioOverIP и задаюсь вопросом, не могли бы вы мне помочь. У меня есть локальная сеть с источником звука (Dante/AES67-RTP-Stream), который я хотел бы распространить на несколько приемников (SBC (например, RaspberryPi) с аудиовыходом (например, разъем для наушников):
PC-->Audio-USB-Dongle-->AES67/RTP-Multicast-Stream-->LAN-Network-Switch-->RPI (Gstreamer --> AudioJack)
В настоящее время я использую Gstreamer для конвейера:
gst-launch-1.0 -v udpsrc uri=udp://239.69.xxx.xx:5004 caps="application/x-rtp,channels=(int)2,format=(string)S16LE,media=(string)audio,payload=(int)96,clock-rate=(int)48000,encoding-name=(string)L24" ! rtpL24depay ! audioconvert ! alsasink device=hw:0,0
Все работает нормально, но если я смотрю видео на ПК и слушаю аудио из RPI, у меня возникает некоторая задержка (~200-300 мс), поэтому мои вопросы:
- Пропускаю ли я что-то в моем конвейере Gstreamer, чтобы уменьшить задержку?
- Какова минимальная задержка, ожидаемая при использовании RTP-потоков, <50 мс?
- Будет ли задержка возникать из-за сети или из-за скорости RPi?
- Поскольку мой аудиовход не является входом Gstreamer, я предполагаю
rtpjitterbuffer
или подобное не помогло бы уменьшить задержку?
1 ответ
TL;DR: Проверьте размерupdsrc
буфер, если вы настаиваете на использовании gstreamer. Вместо этого я рекомендую использовать реализацию Равенны.
В вопросе большое внимание уделяется gstreamer, который может не понадобиться для достижения вашей цели. Этот ответ больше касается звука через IP (AoIP ) в ARM Linux в целом, а также вопросов 2 и 3.
Во-первых, вы упоминаете Видео и Аудио в своих настройках. Если все сделано профессионально, для этого потребуется решение AV over IP, которое обеспечивает синхронизацию звука и видео. Примерами являются DanteAV или что-то совместимое с SMPTE 2110. Мне кажется, ваш подход подходит для хобби-проектов. Имейте в виду, что Dante в режиме AES67 имеет некоторые ограничения .
2. AoIP с низкой задержкой:
Да, вполне возможно получить задержку Dante/AES67/RTP ниже 50 мс, если ваше устройство имеет сопоставимые характеристики с NXP i.MX8 . Для справки: задержка туда и обратно в 4–5 мс легко достигается с помощью Dante и профессионального оборудования.
Если ваша цель: «Передача потока AES67 с малой задержкой в RPi», я предлагаю взглянуть на реализацию Ravenna для Linux. Равенна похожа на Данте, но более совместима с AES67. Равенна и AES67 используют RTP точно так же.
Существует две основные реализации Linux с открытым исходным кодом:
- Merging Technologies предоставляет « оригинал » только с коммерческой поддержкой. Инструмент управления является проприетарным и предназначен только для x86.
- Существует форк , содержащий полезные патчи и программное обеспечение для управления с открытым исходным кодом.
- В обоих случаях вам все равно придется перекрестно скомпилировать код для ARM/RPi.
- Лично я рекомендую использовать вилку.
Dante предоставляет производителям реализацию Linux, но вы, вероятно, не получите ее: https://www.audinate.com/products/manufacturer-products/dante-embedded-platform.
3. Источники задержки
Для AoIP существуют разные источники задержки:
- Время упаковки: время учета образцов в пакете, ок. 1 мс.
- Сеть: зависит от вашего оборудования и настроек, ок. От < 1 мс до многих секунд.
- Буфер приемника: настраиваемый, ок. < 1 мс до многих мс.
- Обработка и ЦАП на ресивере.
Время пакета должно составлять 1 мс, поскольку Dante использует обязательный профиль AES67 (48 кГц, 48 выборок/пакет). Я предполагаю, что ваш отправитель обработал это правильно, но я не могу сказать.
В сети вам следует использовать как минимум гигабитные коммутаторы и кабели Cat 5e. Обязательно следуйте рекомендациям по переключателям и настройке (особенно отключите EEE). Если часы отправителя и получателя синхронизированы, запустите tcpdump или Wireshark на обоих, чтобы получить точную оценку задержки в сети. Фильтровать полезную нагрузку проще всего по порту, например RTP:port 5004 or port 9875
Данте:portrange 14336-14591
. Включение/выключение звука легко заметить на снимке (latency = T_send - T_recv
).
Если все в порядке, посмотрите на буфер приема или обработку на получателе. Звук с низкой задержкой RPi кажется возможным . Тем не менее, вы можете измерить скорость АЦП/ЦАП на RPi, а также оптимизировать свой Linux (от безголового режима до исправления ядра в реальном времени до создания оптимизированного дистрибутива с помощью Yocto в крайнем случае.
1., 4. Гстример
Как уже было сказано, если вы можете это сделать, используйте реализацию Ravenna Linux. Вся его цель — эффективно получать потоки AES67. И все же, некоторые идеи по поводу вашего конвейера:
Документы говорят _udpsrc
добавляет настраиваемый буфер размером ок. от 50 КБ до макс. 100 КБ. Пакет RTP AES67 с временем пакета 1 мс и частотой дискретизации 48 кГц имеет 342 байта. Таким образом, буфер эквивалентен50 kB / 342 Byte * 1ms = 146ms
-> Это вероятный виновник.
Я думаю, тебе не нуженrtpjitterbuffer
. В его документах говорится о «ретрансляции». AES67 не выполняет повторную передачу полезных данных (AFAIK). Кроме того, в конвейер добавляется еще один буфер на 200 пакетов, то есть 200 мс при времени пакета 1 мс. Заказ и т. д. по-прежнему должны работать, поскольку AES67 использует стандартные временные метки RTP. Но это будет стоить вам задержки и, вероятно, не понадобится в локальной сети. Кажется, rtpjitterbuffer больше ориентирован на RTP глобальной сети, чем AES67 локальной сети.
Также нашел эту статью , в которой используется тот же конвейер, что и у вас.
Если это не решит вашу проблему, выясните, где именно возникает задержка. Также расскажите нам, как измерялась задержка.