音频流:使用 Gstreamer 接收 RTP-Stream - 延迟

CVX*_*DEV 6 rtp audio-streaming gstreamer dante

我目前正在研究一个 AudioOverIP 项目,想知道你是否可以帮助我。我有一个 LAN,带有一个音频源(Dante/AES67-RTP-Stream),我想将其分发到多个带有音频输出(例如耳机插孔)的接收器(SBC(例如 RaspberryPi)):

PC-->Audio-USB-Dongle-->AES67/RTP-Multicast-Stream-->LAN-Network-Switch-->RPI (Gstreamer --> AudioJack)
Run Code Online (Sandbox Code Playgroud)

我目前使用 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
Run Code Online (Sandbox Code Playgroud)

一切正常,但如果我在 PC 上观看视频并收听 RPI 的音频,我会出现一些延迟(~200-300ms),因此我的问题是:

  1. 我是否错过了 Gstreamer Pipeline 中的某些内容来减少延迟?
  2. RTP-Streams 的预期最小延迟是多少,可以实现 <50 毫秒吗?
  3. 延迟是由网络还是 RPi 的速度造成的?
  4. 由于我的音频输入不是 Gstreamer 输入,我认为rtpjitterbuffer或类似的输入不会有助于减少延迟?

Mo_*_*Mo_ 0

廉价的解决方法:将视频延迟 200 毫秒,例如使用 VLC。

长话短说

  1. alsasink是的,您可以通过缓冲区减少延迟
  2. AoIP 延迟轻松< 5ms
  3. 处理和网络可能是瓶颈,但可能不是这里
  4. 添加rtpjitterbuffer增加更多延迟

1.Gstreamer管道

通过减少缓冲区,该管道显示了 40 毫秒的往返延迟alsasink

gst-launch-1.0 udpsrc address=239.69.x.x port=5004 multicast-iface=eth0 !\
    application/x-rtp, clock-rate=48000, channels=2 !\
    rtpL24depay !\
    audioconvert ! audio/x-raw,format=S24LE,channels=1 !\
    alsasink device=hw:CARD=Loopback,DEV=0 buffer-time=5000 latency-time=500 sync=false
Run Code Online (Sandbox Code Playgroud)

我只调整了alsasink部分。运行gst-inspect alsasink显示缓冲时间默认为200ms。在看到音频伪影之前,我能够将其减少到 5 毫秒。减少它时,请确保将Latency-time(“写入的最小数据量”)调整为比buffer-time更小的值。还必须添加sync=false来消除一些警告。

往返延迟

我对管道进行了测量。必须将 Audacity 延迟补偿设置为等于 Audacity 缓冲区。您会看到一个小工件,可能是由于非实时操作系统造成的。

Ubuntu-PC -> DanteAVIO USB-C -> Cat5e -> Gstreamer

40 毫秒往返延迟,带有 Audacity 和改进的管道

2.低延迟AoIP:

如果您的设备具有与NXP i.MX8相当的规格,则绝对有可能使 Dante/AES67/RTP 延迟低于 50 毫秒。

如果您的目标是:“将低延迟 AES67 流传输到 RPi”,我建议您查看适用于 Linux 的 Ravenna 实现。Ravenna与 Dante类似,但更符合 AES67。Ravenna 和 AES67 使用 RTP 的方式完全相同。另外,pipewire 最近支持 AES67(我没有测试)。

我知道这些可行的选择:

  • Merging Technologies 提供“原创”以及仅商业支持。该控制工具是专有的且仅限 x86。
  • 有一个包含有用补丁和开源控制软件的分支。
  • Pipewire AES67 实施。目前尚未发布,但您已经可以从 master 分支编译工作版本。
  • Dante 嵌入式平台,但您可能不会接触到它。

3. 延迟来源

对于 AoIP,延迟有不同的来源:

  • 数据包时间:处理数据包中的样本的时间,约。1毫秒。
  • 网络:取决于您的硬件和设置,大约。< 1 毫秒到很多秒。
  • 接收缓冲区:可配置,约。< 1 毫秒到很多毫秒。
  • 接收器处的处理和 DAC。

在本例中, gstreamer 将 alsa 中的接收缓冲区设置为 200ms。

数据包时间应为 1ms,因为 Dante 使用 AES67 强制配置文件(48 kHz,48 个样本/数据包)。我假设您的发件人正确处理了此问题,但我无法判断。

在网络上,至少应该使用千兆交换机和Cat 5e电缆。确保遵循有关开关和配置的建议(尤其是禁用EEE)。如果发送方和接收方的时钟同步,请在两者上运行 tcpdump 或 Wireshark,以更好地估计网络延迟。按端口过滤有效负载是最简单的,例如 RTP: port 5004 or port 9875。在捕获中很容易发现取消静音/静音 ( latency = T_send - T_recv)。

RPi 低延迟音频似乎是 可能的。尽管如此,您仍然可以测量 RPi 上 ADC/DAC 的速度。实时优化你的 Linux 可以让你进一步减少 alsa 缓冲区。

4.Gstreamer Rtpjitterbuffer

你不需要rtpjitterbuffer。它的文档谈论“重传”。AES67 标准不包括有效负载的重传。此外,rtpjitterbuffer 元素添加了另一个 200 个数据包的缓冲区,即 1ms 数据包时间的 200ms。

专业音频+视频

您在设置中提到了视频和音频。如果以专业方式完成,这将需要 AV over IP 解决方案来保持音频和视频同步。例如 DanteAV 或 SMPTE 2110 兼容的东西。对于我的爱好项目来说,你的方法似乎很好。请记住,AES67 模式下的 Dante 有一些限制