转:http://ticktick.blog.51cto.com/823160/1746136

PigeonCall:一款Android VoIP网络电话App架构分析

2016-02-29 20:12:19

标签:Android Pigeoncall 飞鸽电话
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://ticktick.blog.51cto.com/823160/1746136

1.概述

PigeonCall,中文名“飞鸽电话”,是一款Android平台的VoIP网络电话应用,但只工作于局域网,支持给任意局域网内使用该App的其他用户拨打网络电话,可以在各大应用市场下载安装,也可以直接点击这里直接下载。

本应用是我利用了断断续续将近大半年的业余时间开发出来的,目的是想研究一下Android平台的P2P语音传输技术,开发过程中重构了很多次,也尝试了很多不同的方案,本文则是对此的一个总结,从宏观上分析了整个应用的架构和所涉及到的技术,欢迎持续关注本博客,后续有时间会慢慢分享更多的细节。

2.需求分析

 

2.1 功能定义

 

本应用支持的功能如下所示:

(1) 运行于Android平台

(2) 自动搜索和显示局域网内的其他用户

(3) 支持拨打电话和来电提醒

(4) 通话过程流畅清晰无卡顿,低延时

2.2 性能指标

 

ITU-TG.114规定,对于高质量语音可接受的时延是300ms。一般来说,如果时延在300~400ms,通话的交互性比较差,但还可以接受。时延大于400ms时,则交互通信非常困难。

2.3 开发难点

 

(1)低延迟,语音通话对延时非常敏感

(2)降低噪声、回声消除,静音检测(省流量)

(3)无服务器,去中心化,全双工P2P通信

3 软件架构

整个软件分为四大模块: Android UI,VoipSdk(主控模块),设备发现与通话协议,语音编解码与传输模块,语音采集与输出模块,如图所示:

 

3.1 Android UI(平台相关,采用Java开发)

Android UI 主要有2个界面,一个是 MainAcitivity,以列表的形式显示当前局域网内的所有其他用户,另一个则是电话拨打/接听界面,当用户点击拨打电话或者收到来电时显示。

为了保证App进入后台依然能够收到来电消息,因此需要开启一个Service服务,该服务封装了整个应用最核心的逻辑和接口,包括:搜索局域网内其他用户、拨打电话、监听来电、语音传输等等。

UI界面如下所示,由于没有美工,自己设计的界面不是很协调和美观,这个后期再慢慢改进吧:

3.2 设备发现与通话协议 (平台无关,采用C++开发)

这一模块我研究和尝试过三种方案,分别介绍如下:

3.2.1 成熟的 UPnP 框架

UPnP框架天生就是为对等网络连接(P2P)的结构设计的,可用于局域网之间的设备发现、远程服务调用。官方提供了各种实现了该协议框架的第三方库,可以快速实现设备发现功能。

UPnP协议规定,每个UPnP设备节点通过组播来发送设备描述、服务描述(XML文档),网络中的其他节点即可知道对方的信息,以及所提供的服务,因此,我们需要设计一套简单的通话协议的“服务描述”XML文档,包含:Make Call、Cancel Call、Accept Call、Refuse Call、End Call 等命令,这样,其他的设备节点即可通过"RPC"远程过程调用的方式,实现通话的请求和响应过程。

这就是采样UPnP方案的基本思路,我采用UPnP官网提供的"PlatinumKit"库实现了这套功能,后来发现本应用并不需要搞得如此复杂,没必要引入UPnP框架,因此又自己编写了一套更加简单的方案。

3.2.2 SIP协议

SIP协议被广泛用于VoIP网络通话,但是更多地用于面向广域网的语音电话应用场景,它需要一个SIP网络服务器的参与,该网络服务器负责各个SIP终端之间的会话建立、维护和终止。

本应用是局域网内的P2P网络电话,去中心化,并不需要"服务器"的存在,因此并不适合采用SIP协议。

3.2.3 自定义设备发现与通话协议

基于上述考虑,最终我选择了自己来写一套简单且满足本应用场景的设备发现与通话协议。

首先,协议的网络传输部分采用UDP组播,相比与广播包,对本地局域网的影响更小。其次,采用二进制格式的协议,相比于XML、JSON等格式,效率更高,占用带宽更少。

本协议采用“T-L-V”链接格式,每个组播包由一个或多个“T-L-V”子包链接而成,示例如下:

当前协议中已存在的子包如下所示:

每一个Device都有一个唯一的Id值,由 Source Id 和 Target Id 的值决定该组播包的发送者和目标接受者,当 Target Id == 0 的时候,代表该组播包是发给所有人的。

由 Packet Id 决定此包的种类,不同种类的包有着不同的 optional 子包,例如:

Device Info 包是当前唯一发给所有人的组播包,用来通知局域网内其他对象自己的设备名称和IP地址,目前的设计是默认每个5秒钟发一次,超过10s未收到包则认为该设备已掉线。

具体协议实现的过程中,“T-L-V”协议部分,采用了我自己编写的开源库(TLV编解码器),可以快速实现多个“T-L-V”格式的序列化与反序列化,而多播的部分则可以参考我的clib库:multicast。

3.3 语音编解码传输模块(平台无关,采用C++开发)

3.3.1 概述

一个完整的语音数据流图如下所示,从采集到远端播放,需要经过多项处理,包括:回声消除、去噪、编码、网络传输、解码等等,本模块就是负责实现音频数据的 "编解码和网络传输" 部分。

3.3.2 编解码

一套双声道数字音频若取样频率为44.1KHz,每样值按16bit量化,则其码率为:44.1kHz*16bit*2 = 1.411Mbit/s

对于网络电话应用,语音传输是双向的,因此上述码率还要乘以2,可见其数据量还是蛮大的,因此,必须进行编码压缩之后再通过网络进行传输,这样才能达到更好的通话效果。

Opus是一个有损声音编码的格式,通过诸多的对比测试,低码率下Opus完胜曾经优势明显的HE AAC,中码率就已经可以媲敌码比它率高出30%左右的AAC格式,而高码率下更接近原始音频。因此非常适合作为VoIP语音电话首选的压缩格式。

其官方网站:http://www.opus-codec.org,该网站上提供了基于C语言的编解码库,可以很容易地移植到其他平台。

3.3.3 网络传输

网络传输协议可以选择TCP、UDP或者RTP,像TCP这样的可靠传输协议,通过超时和重传机制来保证传输数据流中的每一个bit的正确性,从而带来了明显的延时,因此并不适合作为音视频传输的首先方案。关于TCP与UDP/RTP的讨论,网上资料很多,在此不再赘述,有兴趣的朋友也可以看看我的这篇《为什么要使用RTP》来了解一下RTP协议的种种好处。

本应用中,既可以采用RTP协议,也可以简单地采样UDP来完成语音数据的网络传输,如果采样RTP协议,则可以考虑常见的RTP库,包括:Jrtplib和ortp,前者是C++开发,后者采用C语言开发,都很不错,我最后实现了两个版本,一个是采用ortp,另一个是采用udp,其实,如果不做RTCP控制的话,还是采用udp更加简单点。

3.3.4 去噪和回声消除

去噪和回声消除也是语音电话非常重要的一部分,必须得做,否则你会发现做出来的应用根本无法使用,噪音、嗞嗞声和回声影响实在是太大了,这也是做语音开发的难点所在,对噪声、回声、延时超级敏感,想做好,还需要下一番很大的功夫。

本应用采用了著名的Speex库来完成去噪和回声消除,它接口非常简单易用,目前效果还不够好,估计它的详细配置我还研究得不够,以后还需要继续研究研究,慢慢优化通话效果。

3.3.5 语音采集输出模块(平台相关)

Android 语音的采集和输出有两种方案,第一种方案是采用 Android SDK提供的 Java 端的 API,即 MediaRecoder类(采集)和 AudioTrack类(播放)来完成,第二种方案则是采用Android NDK提供的 Android OpenSL ES 接口,在 Native 层直接完成语音的采集与输出。

两种方案我都尝试过,最后决定采用 Android OpenSL ES 方案,因为不需要频繁在 Java 和 Native 层直接传递数据,无论是代码的编写还是程序运行的效率,优势都非常明显。

有一个老外,Victor Lazzarini,封装了一套 OpenSL ES 的 API,非常好用,可以作为参考,地址点击这里。

4. 小结

限于篇幅,本文只是简单列出了本应用的一些关键的设计和方案,并没有完全详细地展开,真正着手实现的过程中,你会发现还有很多很有价值值得研究和积累的地方,源码我就不公开了,但我会慢慢写一些文章剖析其中涉及到的技术,希望对Android音频开发有兴趣的小伙伴们自己动手实践一下,这样才能真正地得到提高,开发过程中有任何疑问欢迎来信 lujun.hust@gmail.com 交流,也可以关注我的新浪微博 @卢_俊 或者微信公众号 @Jhuster 获取最新的文章和资讯。

本文出自 “Jhuster的专栏” 博客,请务必保留此出处http://ticktick.blog.51cto.com/823160/1746136

转:android实时语音问题分析相关推荐

  1. [转] Android实时抓包分析 : 善用adb调试桥

    Android实时抓包分析 : 善用adb调试桥 谈到android网络抓包,很多人都能想到牛逼轰轰的神器tcpdump.方法就是在android机器上面安装tcpdump,然后通过-w参数把抓包记录 ...

  2. Android实时语音聊天

    近些天一直在做利用RTMP实现实时语音聊天的Android聊天室,中间遇到不少问题,终于有时间记录一下. 1.关于RTMP RTMP协议不必多说.http://www.cnblogs.com/haib ...

  3. Android混流技术,基于Android的实时语音混沌保密技术的实现

    摘要: 网络和多媒体技术的发展和成熟,使之通过网络进行语音交流越来越流行,同时,网络的开放和共享性使信息安全问题也得到更多的关注.因此,怎样实现语音的安全通信的研究变得越来越重要.混沌系统由于自身独特 ...

  4. 呼叫中心的实时语音分析

    呼叫中心的实时语音分析 Digital Communication Platform)Twilio(www.twilio.com)于本月6日,首次发布其实时呼叫分析服务 - Media Streams ...

  5. 研究Android即时聊天、实时语音通话、实时对讲机等的必备知识Audio

    本文转载自大神的Android深入浅出之Audio 第一部分 AudioTrack分析 一目的 本文的目的是通过从Audio系统来分析Android的代码,包括Android自定义的那套机制和一些常见 ...

  6. 如何做好游戏内实时语音体验

    游戏内语音沟通需求 早在2015年,艾媒咨询即有移动游戏社交相关数据统计:近40%的玩家因为社交因素选择一款游戏:15.6%的玩家因为一款游戏社交性差而选择离开.因此,如何提高游戏的社交属性已成为各大 ...

  7. BIGO | imo实时语音传输优化揭秘

    ​2020年新冠疫情持续蔓延全球,亿万人的生活因此发生了巨大的改变,人们对实时音视频通话的日常需求也越来越大.作为BIGO公司旗下重要的全球性即时通讯产品imo为全球2亿多用户提供优质稳定的即时通讯服 ...

  8. 【视频文稿】车载Android应用开发与分析 - 走进车载操作系统

    本期内容的视频地址:https://www.bilibili.com/video/BV1rR4y1B7Qd/ Hello,各位好,我是一个做车载软件开发的软件工程师,之前在CSDN.稀土掘金这些平台上 ...

  9. 如何做好游戏内实时语音体验 1

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~. 作者:张晓愚,腾讯云游戏行业资深架构师 由腾讯游戏云发表在云+社区 游戏内语音沟通需求 早在2015年,艾媒咨询即有移动游戏社交相关数据统计: ...

最新文章

  1. iOS 8 UITableView分隔符插入0不起作用
  2. 深入redis内部--实现字符串
  3. 如何在 Microsoft Visual C# .NET 中实现 Microsoft Excel 自动化
  4. Spark精华问答 | Spark的计算方法是什么?
  5. mysql 数据库 更新_mysql数据库更新
  6. 一步一步搭建mysql_Linux——搭建PHP开发环境第一步:mysql
  7. python下载包没用_Python下载各种功能包出问题
  8. [Java] 蓝桥杯PREV-5 历届试题 错误票据
  9. linux 永久添加路由表,Linux 添加永久静态路由的方法
  10. 拨号720错误解决记.txt
  11. Julia : 关于类型的匹配和规范建议
  12. 随手记:Ubuntu16.04.1安装Chrome浏览器以及解决root下无法启动的问题
  13. 最全的软件开发报价标准
  14. android robotium教程,Robotium + Android studio
  15. 版本控制系统(vcs)Git
  16. 小程序获取oppenid
  17. 查询linux下的业务端口,Linux系统查询显示端口信息用什么命令
  18. 浏览器标准模式和怪异模式之间的区别是什么——整理自网页
  19. PHP剧影评系统的设计与实现毕业设计源码140859
  20. python白噪声检验_时间序列 平稳性检验 白噪声 峰度 偏度

热门文章

  1. 企业文化建设不能仅仅靠大声疾呼
  2. JAVA性能诊断与调优
  3. [解题报告]10929 - You can say 11
  4. Web3.js 0.20.x API 中文版翻译 1
  5. 【TensorFlow篇】--DNN初始和应用
  6. android 51 有序广播
  7. 制作OS X El CAPITAN安装U盘
  8. 自定义全局按键修饰符
  9. 阿里云Redis多线程性能提升思路解析
  10. Linux : Bridge support not available: brctl not found