Browsed by
标签:audio

为什么放弃了webRTC?

为什么放弃了webRTC?

首先必须要说明的是:webRTC是非常好的技术,以至于我现在仍然在怀疑,放弃webRTC是不是个明智的决定,内心依然是忐忑不安。

然而现状就是将webRTC从MSS新版本中砍掉了。下面试图说明清楚做决定时的一些考虑。

从webRTC技术的发展脉络看,感觉ta更适合于公共网络的通信,尤其是越来越像专为google hangouts服务。由于是服务于公共网络,因此“加密”提高到一个非常重要的位置,几乎达到了神经质的地步。webRTC设计之初就没有考虑过传统的VoIP网络(尽管该技术来自于收购的GIPS团队,而该团队本身就是为VoIP网络开发出身的),从传输到业务,基本都特立独行。当然,这没什么不好,只是由于与传统VoIP网络切割开来,实在让人经常感到惋惜。

既然没有考虑传统VoIP网络,当然就更不可能考虑网络部署的多样性。全方位加密固然让自己显得安全,带来心理上的安慰,但也增加了网络部署的复杂性(VoIP本身已经够复杂了)。就一般的VoIP应用而言,“salt+MD5”以及SRTP已经足够保证通信的安全性和私密性。而最新的webRTC(不特别说明的话,这里我们总是指Chrome的webRTC实现)要求getUserMedia等操作必须是来自加密(HTTPS)的网站,websocket也必须进行加密。这也就是说,用户必须要为webRTC服务器(通常也是呼叫服务器或者IPPBX)部署单独的签名加密(TLS或者SSL)。对于提供公众服务的网站而言,部署TLS/SSL不是太大问题,而要求中小企业申请签名并部署在呼叫服务器中,这毫无疑问极大地增加了系统的复杂度,增加了部署难度,而且这样做的意义又有多大了?在企业通信网络里与其这样增加复杂度(网络复杂度和管理复杂度),还不如干脆直接建立VPN网络,方案很成熟,加密更全面,保护更周到,方式方法也简单得多。

这就是我们感觉webRTC只适合公众网络并且已经神经质的原因之一。何况,“加密”有时候更多的是个管理问题而不是技术问题。

webRTC另一个宏大的目标是提供各平台统一的用户体验。愿望是很美好的,但是是否能实现值得商榷。把所有的处理都放入浏览器,固然增加了可移植性,但最大的问题也就是牺牲了平台的独特性和高效性。比如在移动平台,webRTC的耗电量就明显偏高。而且在移动平台各种莫名其妙的设定,极大地损害了用户体验,比如播放ring-back tone,居然要求用户必须点击一个按钮才能继续(是我out了么?),这实在是太扯了。

而最被我们诟病的是兼容性。webRTC基本没有什么兼容性可言。按道理已经发布这么久了,多少应该在一些关键点上考虑一下兼容性,然而并没有。这对一个像google hangouts这样的网站来说,不是大问题,用户无非升级一下chrome好了。而对部署在许许多多用户voip网络中的PBX或者webRTC服务器而言,就是噩梦了。用户升级了Chrome,就必须同时升级服务器,如果不升级服务器,就必须降级Chrome。与之相比,microsoft对兼容性的考虑简直贴心贴肺。

这种对兼容性的唾弃有时候甚至直接表现在产品本身。比如当初的Gtalk,直接就放弃了,我们花费大量时间精力对接Gtalk,最后也是然并卵。对webRTC也会产生同样的顾虑。

webRTC当然有很多非常优秀的技术特点,比如源自GIPS的回音消除技术、超强的语音编解码技术等。思虑再三,决定还是不再跟随,砍了算了,以后再说吧。

Phonon程序无法播放语音文件的问题

Phonon程序无法播放语音文件的问题

问题基本情况如下:我们开发并发布了一个软终端产品,当然其中采用QT以及Phonon模块。在我们的开发环境中,一切都很美好,能正常地播放音乐。可是安装到客户的计算机上,出现问题了,无法播放提示语音(wav文件录制)。

这个问题的实质是我们没有将Phonon的插件一同打包进安装文件。Phonon实质上只是个前端封装模块,具体工作有赖于后台的解码器。在windows系统中,Phonon缺省采用DirectX作为后台解码器部分,具体实现为一个plugin。如果不安装这个plugin,则phonon无法正常播放语音文件。

假设QT安装在d:\qt\4.8.4目录下,则上述plugin可以在以下目录中找到:D:\Qt\4.8.4\plugins\phonon_backend\phonon_ds94.dll。

注意,不是简单地将这个文件拷贝到程序目录下即可,而是要拷贝到程序目录的phonon_backend子目录下。例如,我们的程序安装在d:\minisipphone目录,则上述dll应当拷贝为:d:\minisipphone\phonon_backend\phonon_ds94.dll。

另外需要注意的是,不同版本的QT要采用各自版本的phonon_ds94.dll,例如qt 4.6.2的程序就不能采用qt 4.8.4的phonon_ds94.dll,否则还是会出现放音错误。

WebRTC与SIP

WebRTC与SIP

毫无疑问,WebRTC是个好东西。之所以这么说,是因为他居然开源了GIPS的audio引擎。GIPS的回声抑制、噪声消除等方面的技术,几乎独步天下。当年GIPS仅靠这些个算法包,就活得有滋有味。Skype、MSN、QQ等等,凡是做IP语音通信的,都无一例外地使用了GIPS的技术,这里还没包括各硬件芯片厂商。

Google居然将它开源了,牛啊!实在是让人佩服!

既然已经开源了,我们也希望在已有的free项目中引入webrtc的相关模块(主要是EC, NS等)。看了一下webrtc的文档(目前还是非常简陋),忽然有个想法,其实我们没有必要将webrtc的模块引入我们的项目,相反,我们只需要基于webrtc,将我们已经实现的SIP会话层以及GUI层添加到webrtc中。从webrtc的模块分层看,这样似乎更可行一些。

替换掉webrtc的会话层,或者新增SIP会话层似乎都是可行的。不过编译webrtc实在是麻烦,居然要vc2005(还不能是express版本)/ Win7 SDK / DirectX SDK等等,个个都是巨无霸。

另外,这个对Speex项目应该也有影响吧?Speex项目自己实现了一个audio引擎,不过其中的EC,NS等关键部件效果还是不太让人满意,不知道他们会不会从webrtc中获得灵感。

iLBC相关说明

iLBC相关说明

在两篇RFC文档中对iLBC有比较全面的介绍:

1、RFC3591 Internet Low Bit Rate Codec (iLBC) 这篇主要是讲解iLBC的基本原理,非语音处理领域的专业人士很难看得明白。

2、RFC3952 Real-time Transport Protocol (RTP) Payload Format for internet Low Bit Rate Codec (iLBC) Speech 进行RTP传输是必须遵守的规范,VOIP领域人士基本能看明白。

简单点说:iLBC采用8KHZ,16bit采样,但是分成两种模式:30ms(毫秒)模式以及20ms(毫秒)模式。最初只定义了30ms模式,后来考虑到窄带网络丢包的情况,增加了20ms模式。目前大部分设备多采用的是30ms模式。

30ms模式是指每30ms发送一帧,则每帧数据是400bits (50bytes),如果是20ms一帧,则每帧数据是304bits(38bytes)。

在SDP描述中,必须明确指明codec名字是iLBC。

如果是20ms模式,必须在SDP中明确指明,否则会认为是30ms模式。在RFC文档中有如下描述:

If 20 ms frame size mode is used, remote iLBC encoder SHALL receive “mode” parameter in the SDP “a=fmtp” attribute by copying them directly from the MIME media type string as a semicolon separated with parameter=value, where parameter is “mode”, and values can be 0 and 20 (where 0 is reserved and 20 stands for preferred 20 ms frame size).  An example of the media representation in SDP for describing iLBC when 20 ms frame size mode is used might be:

m=audio 49120 RTP/AVP 97
a=rtpmap:97 iLBC/8000
a=fmtp:97 mode=20 <– 30ms模式中,多数厂家的设备不会携带这个attribute。

需要注意的是SDP协商与一般的codec协商有不同,其中比较关键的就是ptime不能应用到iLBC的协商中。iLBC总是采用最低速率模式,例如,只要一方要求30ms模式,双方都必须使用30ms模式:

That is, an offer of “mode=20” receiving an answer of “mode=30” will result in “mode=30” being used by both participants.  Similarly, an offer of “mode=30” and an answer of “mode=20” will result in “mode=30” being used by both participants.

注解:我想可能就是这个原因(当然,也有历史遗留的可能),大家都不约而同地采用30ms模式,避免对媒体资源的重新调配。

不能使用ptime的原因在于一个RTP包中,可能会封装若干个iLBC包,这种情况下ptime无法表述究竟是哪种模式:

Parameter ptime can not be used for the purpose of specifying iLBC operating mode, due to fact that for the certain values it will be impossible to distinguish which mode is about to be used (e.g., when ptime=60, it would be impossible to distinguish if packet is carrying 2 frames of 30 ms or 3 frames of 20 ms, etc.).

注解:在一个RTP包中封装多个iLBC包的方法,实在让人感觉多此一举。即没有减少流量,也不能降低丢包对语音质量的影响,反而增加了网络设备的复杂性。从实际应用来看,也没有什么人会采用这种方式。