阅读 2784

基于声网的音视频SDK和FreeSWITCH开发WebRTC2SIP Gateway

本文源自 RTC 开发者社区成员,分享了他们基于 Agora SDK 与 FreeSWITCH 开发 WebRTC2SIP 网关的经验,他们以此方案改善了一个原本基于 SIP 协议开发的音视频平台系统。如果大家感兴趣可以点击这里,与作者交流。

方案和思路

为什么做这个?

今年初接到一个项目任务,客户要求在自己的音视频平台系统中集成webrtc功能(原系统是基于SIP协议开发的,已经稳定运行多年,已有一定数量的存量客户)。在对比多家RTC产品的效果后,客户对声网音视频DEMO效果后非常满意,指定要求用声网的SD-RTN传输网络,全面改造客户端软件,改善音频通话质量。据客户实测,在某些国家和地区,同样网络环境下比微信的音频通话质量要好很多,比如在东非和中国之间语音通话,延迟很小、声音也更清晰。

目前系统已经上线运行了几个月没出过问题,通话质量也非常好,满足了客户的预期目标。公司要求总结开发阶段中碰到的问题,另外我们也希望能回馈一下社区,形成一个良性互动及不断加强一下社区浓厚的学习交流氛围。有感于这一段时间的开发工作,于是写下这篇文章,我们会在这篇帖子中定期更新,分享开发思路、方案、遇到的问题、解决方法,希望能对大家有所帮助。我会敲代码,不太会表达,如果大家在实现这个模块的过程中也碰到类似的问题,想了解一些细节,欢迎联系回帖提问或者邮箱交流(交流邮箱地址:bd@qzlink.com),咱们尽量答复大家。

一路走来,几个同事经常分析代码到半夜。终于在测试4个月后稳定下来。其实现在回头看,就是因为没有吃透声网的API文档,没有好好利用社区的功能。如果你碰到的坑是跟咱们的类似,那么花点时间仔细撸几遍API文档就可以搞掂了。

话不多说,先列下客户需求:

1、全面改造Android、iOS、Windows、MacOS、Web版5个平台的客户端软件,原来的客户端分别是基于Pjsip、Linphone、Sipjs开发的;

2、要求在网络环境差的地方,也能满足清晰语音通话的要求(声网的音视频实时传输网提供支持);

3、最小侵入性,尽量不改变服务器端的系统功能,实现客户无感升级;

4、解决SIP协议常碰到的丢包、被过滤UDP、无法呼叫和呼叫听不清等问题;

5、解决SIP服务器经常被尝试攻击呼叫、恶意扫描注册攻击等行为,提高系统稳定性;

6、实现WebRTC协议和SIP协议的双向互通,既要兼容SIP呼叫,又支持RTC客户端送呼叫到SIP Server,也要支持SIP Server呼入到客户端软件(在声网的音视频实时传输网传输)。.

其实刚接到需求的时候,大家一起讨论分析过:这种项目看着有不少预算,但是要做全平台客户端,开发任务繁重,要考虑的细节也比较多,没准是个坑,能否达到客户的期望要打一个问号,因此多数同事建议不做。然后在领导和客户一起去happy一晚后,这活儿不知道怎么就接下来了。

老板理由很简单,这也不做那也不做,那我们可以做什么?如果谁都能做,客户还会找我们吗?那就干吧,马上行动,各种查资料,翻阅声网的技术开发文档,并咨询声网的技术同学,2天后拿出初步方案。

系统架构图

解决思路有6步:

1、自己写信令模块,保持灵活性,简单实现。开发TCP Server承担信令服务器;

2、核心是开发一个SIP2WebRTC/WebRTC2SIP协议转换网关,维护一个状态机;

3、开发音视频编解码处理器,解决声网语音和SIP语音编码互通;

4、开发一个状态管理模块,SessionManger,以维护客户端的状态IP和端口;

5、结合声网的音视频SDK,集成自己的信令模块,实现和WebRTC2SIP 模块通讯;

6、自定义常见的SIP呼叫信令,供各平台客户端保持一致。

常用的SIP 信令有:1注册、2呼叫、3接听、4挂断、5拒接、6取消、7Hold、8DTMF、9用户未反映、10用户离线、11Transfer、12会议(我会简单介绍前面的6个)。

PS:我们暂且把这个系统命名为 WebRTC2SIP Connector 或者SIP2WebRTC Connector吧。至于为什么这么叫,我也不知道,可能叫XX Gateway的太多了,不这么叫显不出声网的SD-RTN有多厉害,我是他爹,想叫什么都可以,哈哈

理清思路后,我们需要确认几个核心问题:

以哪个平台的SDK为基础开发WebRTC2SIP Connector核心模块?

Agora SDK是否支持多并发呼叫?

声网的语音编码格式和视频编码格式是什么?采样率多少?

SIP客户侧有没有什么具体的编码要求?客户可接受固定一个语音编码,我选择PCMA

这里特别感谢一下声网,对我们这种小众需求做出了快速响应,也感谢声网技术支持同学,专门来到公司交流了几个小时,并分享了一些技术信息,点一个大大的赞。

声网建议我们:

用Agora Windows SDK 或者 Linux SDK 开发协议转换模块;

2个SDK都支持多并发呼叫;

语音是pcm格式,视频是yuv格式,采样率是48khz;

到这里心里有数了。

简要文字描述下大概流程就是:

1、各客户端SDK启动时,发起TCP连接,登录TCP Server信令服务器, WebRTC2SIP转接模块初始化也发起TCP连接登录TCP Server ,由TCP Server记录UID,IP和端口等信息。

2、呼叫的具体流程大概是这样的:

(1)呼叫的时候,申请一个房间号,并根据自定义信令格式发起calling 报文,TCP Server收到后,转发给转接模块WebRTC2SIP ;

(2)WebRTC2SIP收到后创建1个线程,解析报文,并启动声网的SDK,加入指定房间号;

(3)开始读取音频流程,同时启动线程,封装SIP标准报文,发起sip invite请求给电话服务器SIP Server;

(4)SIP Server收到呼叫请求就去呼叫被叫电话号码,并返回ring振铃信号。

(5)WebRTC2SIP收到振铃信号,封装自定义的振铃信息给客户端SDK;

(6)被叫接听后,WebRTC2SIP,启动Media Coder开始解析媒体流,并resample 后,写入到声网的房间里面。实现语音通话。

3、从SIP呼入到声网的SDK,大同小异,反过来就行。

这里要注意:

1、每个终端都要自定义编号;

2、每个呼叫都要加入声网的房间channel 实现音视频互通;

3、因为编码不一样,所以需要resample,这个很重要,不然接通了没有声音,双方不匹配。

4、WebRTC2SIP模块要多线程方式处理,以实现并发呼叫;

5、WebRTC2SIP模块要维护一个完整的状态机,给每个通话加唯一编号,避免出错。

到现在我们讲清楚了大概的解决方案和技术思路,看到这里,各位客官应该明白了,其实这个做起来没啥难度,至少现在看来是这样的。

报文设计

上面我们提到,常用的SIP 信令有:1注册、2振铃、3呼叫、4接听、5挂断、6取消

有了这几个报文,电话的呼入和呼出就可以基本实现,其他拒接、DTMF等类似。

如图所示:

约定:

1.客户端和服务器端JSON格式交互;

必传参数:msgtag 是消息唯一标志,userid是谁触发的,appid 作为一个应用的标记。sign 签名加密 (看情况)

2.服务器返回的报文必须包括msgtag \appid\errcode

errcode=1 说明有错误 errmsg就会有值 ,如果errcode=0 说明返回结果正确一般是返回的msgtag 是请求的msgtag+”_res”做为区分

3.roomID 是房间号,对应声网的渠道号channel ID,每个通话报文必须包括roomID 用途是什么自己想。

4.callType 是video \ audio前者代表视频呼叫,后者代表语音呼叫

5.direction 呼叫方向in呼入 (SIP Server 把呼叫送到声网的SDK)out呼出(声网的SDK把呼叫送到SIP Server)

6.isSIP YES / NO代表这通呼叫是内部呼叫(声网客户端实现) 还是SIP呼叫(走落地)

这篇文章我只是简单列出核心的报文DEMO格式。

信令1:注册报文

响应报文:

信令2:呼叫报文

响应报文:

信令3:振铃报文

响应报文:

信令4:接听报文

响应报文:

信令5:挂断报文

响应报文:

信令6:取消报文

响应报文:

如上图设计的报文非常简单,不需要过多言语说明,供大家参考吧。

后续处理

不论客户端还是WebRTC2SIP Connector本质上都是声网的音视频SDK客户端,然后集成了自定义的信令报文,所以在初始化时,需要调用一个专门的的接口(暂时叫做initSIP),调用这个接口时传递type类型参数。

(1)如果是手机端或者电脑端、网页端调用,返回TCP Server地址和端口,供他们建立TCP连接。

(2)如果是Connector转接服务器请求,除了返回TCP Server地址和端口外,还要返回SIP Serve地址及端口和呼叫送号前缀。不然SDK发起电话呼叫时,Connector不知道电话要转送到哪里。这个开发一个http接口就可以实现。

APP初始化,调用initSIP接口,建立TCP连接,或者呼叫的时候在建立TCP连接;

TCP Server维持所有终端的状态及网络位置做Session Manager角色;

主叫输入的号码编辑封装calling报文,通过tcp socket发给服务器,同时UI呈现拨号等待页面;

被叫收到calling报文,就封装ringing报文,通过tcp socket 发给服务器,服务器查询Session Manager查询主被叫的IP和端口,实现消息的路由转发,主叫收到就显示振铃页面。同时WebRTC2SIP Connector启动Media coder线程去解析和resample读取到的音频流。就这样一个个的报文交互串起来,就可以实现整个SIP呼叫逻辑。

有兴趣的同学,快去试试吧。

关注下面的标签,发现更多相似文章
评论