基于freeswitch+linphone客户端开发对讲系统

基本思路:

freeswitch开启conference call (3100), 并进行一些配置(例如,没有moh,刚刚进入时静音禁止视频等),linphone客户端界面改造:启动后自动拨号3100进入fs会议,当按下客户端的‘对讲’按钮后,客户端通过dtmf info发送命令给fs, fs收到dtmf命令后会激发相应的dtmf事件,一个专门的esl客户端监听此类事件,解析这个dtmf事件来获得收到的键值,得知客户端想要对讲,则调用fs的会议控制命令来打开这个会议成员的讲话权限,客户端的声音就可以传入会议中,会议里的所有与会者(客户端)都通过这样的逻辑来控制和协调,保证每次只能有一个客户端讲话(非混音模式),在一个客户端讲话期间,前10秒内其他客户端不能抢,超过10秒,其他客户端可以抢过话权即打断正在讲话的客户端,以及与会者的在线状态广播

功能特点:

集群对讲
点对点对讲
支持普通耳机、蓝牙耳机、外放、ptt切换
10秒超时抢话
多群组,每个群组之间不通话
领导模式:设定为领导,可以对多个群组进行广播
用户在线列表管理
...

1.linphone客户端改造:

采用linphone-android ver3.9.1,主要改动包括:
去掉linphone原有的联系人好友关联功能(会影响到相关activity的自动化转换)
好友在线状态订阅功能去掉--当时在客户端在线状态管理上纠结了一番,采用linphone的presence publish&subscribe还是通过服务器检测和广播呢?后来决定采用服务器广播的方式--是因为3.9.1版本的linphone对于presence publish & subscribe功能支持有bug--当然如果客户端数量达到百级别的话,无论如何都应该上presence机制了,我们的客户端一般不超过几十个
去掉多余的video/audio codecs选项,主要是简化sdp,减少sip流量及出错几率(当sdp超过mtu时,面临分包,可能会导致潜在的问题)
多账号登录问题,断线提示,状态刷新,mediabutton, 后台服务

2. 服务端实现:

服务器采用freeswitch ver1.6.9, 主要改动集中在三部分:
fs源代码的改动
sofia_reg.c:
禁止多点注册
mod_conference.c:
每3秒发一次静音包fs配置,主要包括(但不限于):
sip_profiles/internal.xml:
enable-timer=false
enable-rfc-5626=true
dtmf-type=info
sip-expires-late-margin=1
unregister-on-options-fail=false
all-reg-options-ping=true
ping-mean-interval=10
registration-thread-frequency=60
nat-options-ping=true
tcp-keepalive=true
disable-transcoding=true
inbound-proxy-media=true
ext-sip-ip=116.228.237.226
ext-rtp-ip=116.228.237.226
dialplan/default.xml:
修改拨号计划匹配特定格式的用户名(字母、数字和下划线组合)例如test1, zhangsan_1, lisi5等
autoload_cnofigs/switch.conf.xml中将数据库core.db放到事先建好的内存盘
dialplan/目录增加新的拨号计划文件例如zhidui1.xml, leaders(增加新的组,可以通过更改directory/目录下用户配置文件来将特定用户配置到譬如zhidui1或者leaders这些组中)esl客户端的实现
这部分是对讲系统的核心,对讲业务的逻辑实现都在这里,它定义了针对每个用户(=客户端,下同)的关键数据结构,然后通过hashmap总体管理所有用户譬如上下线状态,遍历查找特定用户,更改某用户状态等,这些都是通过事件驱动的,用户注册上线,进入会议,发起对讲等等都会使fs激发相应的事件,而esl客户端订阅了这些事件,收到这些事件后,进行解析然后得到期望的信息,然后去操作hashmap,具体的功能包括:
用户注册上线检测
用户下线检测
处理用户的对讲请求(当前对讲权是否被占用,此对讲请求能否被允许,如果可以,开启此用户的对讲即取消静音状态)
处理对讲完毕请求
处理客户端获取在线用户列表的请求
通过控制台将某用户静音或者踢掉或者..., 对hashmap进行同步处理
会议室取消后处理
备注:这里不得不提到一个教训,我的esl客户端直接基于fs的testclient.c写的,写到后面发现c语言处理大量的各种字符串操作真是噩梦,建议各位写一个完整功能的esl客户端尽量采用高级语言,例如java,python等,工作量和难度可以减少一个量级,bug也更少

3. 发布

3.1 fs在centos上编译
3.2 完成一个自动化脚本在centos上打包fs的部署所需要的文件和包

关键问题:

nat穿越:

    linphone端: 因为sip服务器通过映射到公网,所以sip不存在nat问题,rtp的nat支持常用的几种方式:stun,turn,ice,考虑到耗时、复杂度等因素,目前在我们的方案中均没有开启这几种方式,而是增加了基本的udp打洞,目的是保证通过sdp交换获得对方的ip后,能够让对方的rtp流穿透我方的路由器(nat)-如果对方的rtp流先到的话(在点对点对讲时用到)服务端:fs位于内网,通过端口映射暴露到公网,fs禁止了upnp和nat-pmp因为我们的路由器不支持此功能,服务器开启了rport功能帮助客户端发现自己的公网ip&port,另外fs开启了学习流功能,即在集群对讲模式下(fs的会议模式中),所有的rtp流都要经过fs,当fs收到某个客户端的rtp流后,会探测其来源端口,如果此端口和之前sdp协商时候获得的客户端rtp端口不一致,则以此实际端口为准(sdp协商的rtp端口作废)。

心跳:

    服务器和客户端之间必须维持‘保活心跳’,两个目的:1.保持sip&rtp的udp端口不被nat干掉(‘长时间’没有udp包的端口很可能会被nat回收) 2.让服务器知道客户端的在线状态,linphone-android 3.9.1支持cn(comfortable noise),但是有问题,所以我们禁止了这个功能,转而通过开启fs的option ping来保持sip心跳,通过发送间隔3秒的空rtp包来保持rtp心跳,同时通过options ping来检测客户端的在线状态

带宽

    基于会议模式的对讲系统,没有采用混音(虽然是混音的框架,但是通过esl控制每个时刻只能有一个客户端讲话,这样就降低了服务器CPU的负荷也降低了带宽占用)

功耗

    FS的会议模式,默认状态下即使客户端不讲话,fs也会按照sdp协商的ptime值发送空的rtp包,导致带宽占用和客户端wifi功耗、编解码功耗上升,不讲话时候fs改为3秒发送一次空rtp包会明显降低功耗

tcp vs udp:

rtp只能基于udp,在voip的实现中,sip over udp和sip over tcp是两种选择,我们的项目里一开始也是采用默认的udp sip, 但是后来改为了tcp,主要是考虑到穿透性,此外tcp相对于udp还具有如下优势:
udp keep alive timeout一般最多几十秒,而tcp keep alive timeout 要长很多,一般是几分钟起甚至十几分钟(路由对tcp port的保留优先级远高于udp port),对于移动设备,其直接的好处就是功耗的降低,并且tcp有自己的keep-alive机制,不用再重新造轮子了:)
在sip包大到一定程度(>=mtu-200)时候,rfc3261强制使用tcp-因为tcp本身具有分片功能-其好处就是一个分片丢失后可以重传恢复整个sip packet,而如果udp分包丢失,则整个sip包都要重传,导致效率低下。
在我们的实践中,当时发现联通的4G无法拨通移动4G,后来改为sip ,over tcp就可以了,另外linphone-android 3.9.1对于tcp的支持有问题,表现为每次通话都重新bind一个tcp socket,然后通话过程中会发现监听的tcp port越来越多,修复了此bug后一切ok

基于freeswitch+linphone客户端开发对讲系统相关推荐

  1. “从零到一“基于Freeswitch二次开发:Freeswitch入门与网络架构 (一)

    一. 简介与背景 在当前的互联网时代,想必大家对于网络电话或者通过网络进行语音.视频的场景再熟悉不过了.基于IP的语音传输(英语:Voice over Internet Protocol,缩写为VoI ...

  2. 手把手教大家在自己的Windows电脑上搭建一个视频电话系统(基于开源项目FreeSwitch+Linphone)

    目前可以做视频电话的流媒体开源项目有很多,那么今天我就手把手教大家(基于FreeSwitch+Linphone)搭建一个免费的开源的能在局域网中使用的视频电话系统,部署与配置都非常的简单,而且点对点的 ...

  3. 移动互联网服务客户端开发技巧 ( Webview及正则)

    随着微博.LBS 等移动互联网服务的火爆普及,越来越多的苹果开发者希望制作各网络服务的 iPhone 客户端.CocoaChina 会员 "qdvictory" 的<基于网络 ...

  4. 基于安卓的新闻客户端开发

     研究背景 当前市面上移动新闻客户端,包括网易移动新闻客户端,搜狐移动新闻客户端,凤凰移动新闻客户端等.这些客户端界面绚丽,版面较多,操作过程较为复杂.为简化流程,操作简单,方便用户使用和下载.所以, ...

  5. 基于Dotnetty和Protobuf的Unity客户端开发(一)

    目录 前言 链接 环境配置 安装NuGetForUnity 安装Protobuf 安装Dotnetty包 手动安装其他依赖包 前言 公司的前辈基于Netty开发了一个服务器,推荐我在前端也使用Nett ...

  6. OPC通讯开发简介——基于WTOPCSVR的OPC服务器端和基于WTCLIENT的OPC客户端开发

    OPC通讯开发简介--基于WTOPCSVR的OPC服务器端和基于WTCLIENT的OPC客户端开发 说明 一.OPC技术背景及介绍 二.OPC通讯的流程(OPC经典架构) 三.OPC标准官方文件部分变 ...

  7. 基于Android小巫新闻客户端开发---显示新闻详细内容UI设计

    基于Android小巫新闻客户端开发---显示新闻详细内容UI设计 2013年2月27日,天气潮湿!!! 距上一次写的主界面业务逻辑实现,已经过来11天,小巫觉得拖得太久了,所以决定尽量把所有的内容介 ...

  8. 暂停基于maplefetion的飞信客户端开发

    [size=small]制作飞信客户端的动机原来是想发循环短信骚扰下同学,恶作剧一下(这是我的性格). 现在因为快要期末考了. 然后还有老师给分配的SAT方面的论文没看,1月20号左右又要做SAT方面 ...

  9. 基于Android的小巫新闻客户端开发--UI设计(主界面)

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 基于An ...

最新文章

  1. Cocos2D-X2.2.3学习笔记5(UI系统)
  2. 嗯?原来if可以调用方法的?
  3. jstl与struts2 条件语句的区别
  4. java json 修改字段_JSON文件-Java:编辑/更新字段值
  5. android模拟器太卡,安卓模拟器安装之后太卡怎么解决
  6. mmorpg开发_MMORPG可以教给我们如何组建一支英勇的开发团队
  7. NPM Unexpected end of JSON input while parsing near
  8. java urlconnection乱码_HttpURLConnection 请求乱码
  9. 【w3cschool】MySQL 入门课程_简单复习
  10. [leetcode]5340. 统计有序矩阵中的负数
  11. html表格 溢出,html – 如何创建在溢出时滚动的表格单元格
  12. 在ios中制作3d文字球效果
  13. Java开发常见专业术语
  14. 芽庄新世界酒店将于2023年盛大揭幕
  15. 微信连WiFi关注公众号流程更新 解决ios微信扫描二维码不关注就能上网的问题
  16. 【离散数学笔记】逻辑运算之吸收律
  17. asp.net使用Aspose.Cells实现excel预览
  18. 腾讯云-即时通讯 IM
  19. android 手电筒开关,Android实现手电筒电源键关闭功能
  20. SAP的标准委外采购中都有哪些坑

热门文章

  1. RANSAC随机抽样一致算法
  2. 2020第二篇TED:The case for student health days
  3. 手机摄像头当做电脑摄像头使用-用于视频聊天
  4. 中创易票通打印票据支票 非凡软件
  5. 踢球还是搞笑?这是一届锦鲤和乌龙齐飞的亚洲杯
  6. PS磨皮神器更新为Portraiture V3中文汉化版(仅64位) 。
  7. PS磨皮滤镜插件:Portraiture 3 for Mac破解版永久激活方法
  8. python判断手机号码是否正确_Python:尝试检查有效的电话号码
  9. 射频同轴连接器常用型号
  10. 计算机网络知识点总结——第六章应用层