将多个RTP流混合为一个

时间:2017-10-12 13:48:03

标签: audio udp rtp

我正在尝试建立一个基于普通RTP的基本电话会议系统。

                         _____
RTP IN #1  ______       |     |      _______ MIX RTP receiver #1
                 |______| MIX |_____|
           ______|      | RTP |     |_______ MIX RTP receiver #2
RTP IN #2               |_____|

我正在通过AudioStream类在Android上创建RTP流,并使用Node.js编写的服务器来接收它们。

我一直在使用的天真方法是服务器接收UDP数据包并将它们转发给对话的参与者。只要有两个参与者,这就完美无缺,并且它们基本上就像两个人彼此发送他们的RTP流一样。

我希望这可以与多个参与者一起工作,但是当它们到达服务器时转发RDP数据包似乎不起作用,可能是出于显而易见的原因。如果有两个以上的参与者,将来自不同来源的数据包传送给每个参与者(不包括此类数据包的发送者)的结果会导致音频完全中断。

在不改变网络拓扑(星形而不是网格)的情况下,我假设服务器需要对数据包进行一些操作,以便提取包含混合输入RTP流的唯一输出RTP流。

我只是不确定该怎么做。

2 个答案:

答案 0 :(得分:0)

在你的情况下,我知道两个选择:

  • MCU或多点控制单元<​​/ li>
  • 或RTP同播

MCU控制单元<​​/ strong>

这是获得多个RTP流并生成一个或多个RTP流的中间框(网络元素)。

你可以自己实现,但这不是一件容易的事,因为你需要处理:

  • 流解码(因此您需要抖动缓冲区和编解码器实现)
  • 流混合 - 因此您需要在流之间进行一些同步(从源1和源2收集一些数据,混合它们并发送到目标3)

还有几个项目可以为你做(如Asterisk,FreeSWITCH等),你可以尝试用它们写一些集成级别。我还没有听说过关于Node.js的任何事情

<强>联播

这是一项非常新的技术,其规格仅适用于IETF草案。这里的核心思想是同时在一个RTP流中发送几个RTP流。

当目的地收到几个RTP流时,它需要与MCU完全相同 - 解码所有流并将它们混合在一起,但在这种情况下,目的地可以使用硬件音频混合器来做到这一点。

此方法的主要缺点是客户端设备的带宽。如果你有N个参与者,你需要:

  • 将所有N个流发送到所有其他
  • 或根据某些元数据(如语音活动或音频级别)选择流

第一个效率不高,第二个非常棘手。

答案 1 :(得分:0)

Dimtry的回答建议的选项在我的案例中是不可行的,因为:

  • 中间盒解决方案难以实现,需要太多资源或需要依赖外部软件,我不想依赖它,特别是因为Android RTP堆栈应该开箱即用具有服务器组件的基本支持,尤其是用于打孔的
  • 无法使用联播广播解决方案,因为Android RTP package无法处理该广告解决方案,因为我的理解是它只能处理简单的RTP

我一直在评估的其他选项:

SIP

Android supports it但它更像是一个高级功能,我想将解决方案构建到我自己的自定义应用程序中,而不依赖于高级协议(如SIP)引入的其他抽象。此外,这感觉太复杂而无法设置,会议似乎甚至不是核心功能,而是扩展

的WebRTC

这应该是对等2对等语音和视频会议的事实标准,但通过代码示例查看它看起来太难以设置。还需要服务器支持打孔。

我们的解决方案

即使我已经并且仍然没有这方面的经验,我认为必须有一种方法可以使用普通的RTP和一些简单的服务器组件提供支持。

服务器组件对于打孔是必要的,否则让客户端相互通信真的很棘手。

因此,我们最后为会议呼叫做的是将呼叫者充当混音器,将服务器组件作为中间人,将RTP数据包传递给参与者。

在实践中:

  • 每当N - 用户呼叫启动时,我们实例化N-1个简单的 UDP广播服务器,在N-1个不同的端口上侦听
  • 我们通过socket.io上构建的信令机制将这些N-1端口发送给呼叫的发起方,并为每个剩余的参与者发送1个端口
  • 侦听这些端口的服务器组件将仅用作中继:每当收到包含RTP数据的UDP数据包时,它就会将其转发到所有连接的客户端(它具有的套接字见到到目前为止)除了发件人
  • 来电的发起人将接收并向其他参与者发送数据,并通过Android AudioGroup
  • 进行混合
  • 参与者只会向呼叫发起人发送数据,他们将在已分配给他们的服务器端口上接收混合音频(连同呼叫者自己的声音和其他参与者的声音)

这允许在客户端和服务器端实现非常简单的实现,只需要最少的信令工作。它当然不是一个防弹会议解决方案,但考虑到简单性和功能完整性(特别是关于NAT遍历的常见网络问题,使用服务器辅助基本上是一个非问题)在我看来比编写大量需要的代码更好许多用于混合服务器端的资源,依赖于SIP服务器之类的外部软件,或者使用像WebRTC这样的协议,这些协议基本上可以实现同样的功能,并且需要付出更多努力。