“微信要收费?”昨天,南京白领穆林一上班就向同事打听这个消息。“腾讯公司的微信即将收费”的传闻不胫而走,互联网上一片议论:微信走的是网络,网费我们交了的。如果微信收费,那邮政局也可以对Email按封收费了。收费可以,拜托想个创新的、隐蔽的办法,让人心服口服才好。

  据了解,互联网公司越过电信运营商,发展基于开放互联网的各种视频及数据服务业务(0TT)已成趋势。比如,各国运营商都把Skype这样的OTT公司视为头号敌人,网络电话的包月套餐让互联网公司盈利,却对运营商的语音和视频业务形成了巨大冲击。据统计,目前国际通话分钟数的25%是由Skype完成的,Skype公司每年收入几十亿美元,而受OTT影响,全球运营商语音收入预计将从去年的9704亿美元下降至2020年的7996亿美元。

  眼下,国内三大电信运营商碰到了一个更强大的OTT业务对手——具有3亿用户的腾讯微信。在被微信等OTT业务沦为通道的当口,三大运营商醒悟过来,开始向微信等OTT业务讨个说法。据电信运营商内部人士透露,笼统地收取宽带租赁费、不限流量包月费模式将被取消,可能采用按用户收费。这样,超过3亿用户的微信,面临着向运营商缴纳巨额“过路费”。

  持“免费至上主义”的中国网民,几乎没人同意对微信收费。一个有代表性的观点是转移阵地:“如果微信收费,那就不用微信,改用Whatzup、Line,声色都有,都不比微信差。”很多网友还在质问:运营商也出了类似于微信的产品,飞聊,翼聊,沃友,你们为什么不火?“因为你们的号码还要漫游。”

  “建立数据通道,就像修高速路,建设和维护都需要成本,运营商的要求天经地义。”中国移动互联网产业联盟秘书长李易认为,电信运营商向OTT业务收费,这也是许多国外电信运营商梦寐以求的事情。

  但是,从国外来看,运营商真要对OTT语音服务发难,总体很难,不仅要跨越诸多法律的障碍和限制,而且还要面对同业竞争所导致的失去市场份额和客户的风险。南京通信业内人士分析说,在竞争充分的市场上,电信运营商应当致力于应对OTT语音业务对电信业务的不利影响。一是电信运营商下调资费,让OTT语音业务软件的使用相形之下变得麻烦而多余;二是顺应趋势,与OTT企业合作;三是运营商提供自己开发的OTT业务。

  比如,美国最大的移动通讯运营商Verizon已经同Skype携手合作,让其用户免费或者以更加便宜的费用拨打国际电话,以此来增加手机用户的市场份额;而德国电信则推出相应的聚合了众多OTT的服务,让用户可以免费拨打其他移动电话或固定电话,而仅以数据流量的形式计费。

  收不收费,还没有定论。虽然腾讯公司14日下午“辟谣”称“外界有关微信收费的言论纯属谣传”,但现有的运营商向OTT业务只收取宽带租赁费或包月流量费的模式已被普遍认为“后果严重”,在封杀已不可能的情况下,运营商将对微信等业务如何收费成为双方博弈的阵地。南京一位通信业内部人士私下告诉记者,0TT的影响有时候是正面的,比如数据业务收入在上升。下一步,运营商至少在两方面将发力:一是必须按用户收费,不能再笼统地收取宽带租赁费;二是不再提供不限流量包月费。

    如果微信真要收费,你还使用吗?
    难道市面上就没有一些能开发即时通讯的平台?让一些开发团队基于这个平台更好更快的去开发各种各样的音视频通讯的应用出来?
答案是有的,接下来小编就给各位开发人员介绍一款能够快速运用来开发的音视频互动开发平台。并且给大家一个开发指南。

为了让大家更好的开发自己所需要的与音视频即时通讯相关的系统,如频会议系统、语音视频聊天系统、远程教育平台以及即时通讯平台(IM)等。我向大家介绍介绍如何利用这个SDK来去开发,大家可以理解成为开发指南吧
首先下载这个SDK,已经上传到了51CTO的网站上面去,大家放心使用。(windows平台音视频即时通讯应用开发包
支持Windows平台音频即时通讯应用开发,同时还有其他的SDK可以开发安卓,ios等移动终端的音视频应用
支持C++、C#、Java、Delphi、VB.Net、Qt等开发语言
集成H.264、AAC、AMR等编解码技术
封装音视频的采集、编解码、传输、显示和播放等模块
提供客户端SDK和服务器SDK API接口

一、初始化
该部分是首先要完成的,用于设置SDK的一些行为,包括设置对应的回调函数、设置SDK组件路径、设置是否产生日志文件等,通常初始化AnyChat SDK的代码如下(C++):
 
 
  1. 01.// 打开(关闭)SDK的日志记录功能 
  2. 02.BRAC_ActiveCallLog(TRUE); 
  3. 03.      
  4. 04.// 设置SDK核心组件所在目录 
  5. 05.CHAR szCoreSDKPath[MAX_PATH] = {0}; 
  6. 06.GetModuleFileName(NULL,szCoreSDKPath,sizeof(szCoreSDKPath)); 
  7. 07.(strrchr(szCoreSDKPath,'\\'))[1] = 0; 
  8. 08.BRAC_SetSDKOption(BRAC_SO_CORESDK_PATH,szCoreSDKPath,strlen(szCoreSDKPath)); 
  9. 09.      
  10. 10.// 根据BRAC_InitSDK的第二个参数:dwFuncMode,来告诉SDK该如何处理相关的任务(详情请参考开发文档) 
  11. 11.DWORD dwFuncMode = BRAC_FUNC_VIDEO_CBDATA | BRAC_FUNC_AUDIO_AUTOPLAY | BRAC_FUNC_CHKDEPENDMODULE | BRAC_FUNC_AUDIO_VOLUMECALC | BRAC_FUNC_NET_SUPPORTUPNP | BRAC_FUNC_FIREWALL_OPEN | 
  12. 12.BRAC_FUNC_AUDIO_AUTOVOLUME | BRAC_FUNC_CONFIG_LOCALINI; 
  13. 13.BRAC_InitSDK(this->GetSafeHwnd()/*NULL*/,dwFuncMode); 
  14. 14.      
  15. 15.// 设置录像临时文件保存路径 
  16. 16.CHAR szRecordDirectory[MAX_PATH] = {0}; 
  17. 17.::GetModuleFileName(NULL,szRecordDirectory,MAX_PATH); 
  18. 18.(strrchr(szRecordDirectory,'\\'))[1] = 0; 
  19. 19.strcat(szRecordDirectory,"Record"); 
  20. 20.BRAC_SetSDKOption(BRAC_SO_RECORD_TMPDIR,szRecordDirectory,strlen(szRecordDirectory)); 
  21. 21.  
  22. 22.// 设置录像文件质量参数 
  23. 23.DWORD dwVideoBitrate = 200 * 1000;  // 200kbps 
  24. 24.BRAC_SetSDKOption(BRAC_SO_RECORD_VIDEOBR,(PCHAR)&dwVideoBitrate,sizeof(DWORD)); 
  25. 25.DWORD dwAudioBitrate = 96 * 1000;   // 96kbps 
  26. 26.BRAC_SetSDKOption(BRAC_SO_RECORD_AUDIOBR,(PCHAR)&dwAudioBitrate,sizeof(DWORD)); 
  27. 27.      
  28. 28.// 设置快照临时文件保存路径 
  29. 29.CHAR szSnapShotDirectory[MAX_PATH] = {0}; 
  30. 30.::GetModuleFileName(NULL,szSnapShotDirectory,MAX_PATH); 
  31. 31.(strrchr(szSnapShotDirectory,'\\'))[1] = 0; 
  32. 32.strcat(szSnapShotDirectory,"SnapShot"); 
  33. 33.BRAC_SetSDKOption(BRAC_SO_SNAPSHOT_TMPDIR,szSnapShotDirectory,strlen(szSnapShotDirectory)); 
  34. 34.      
  35. 35.// 设置SDK临时文件路径 
  36. 36.CHAR szTempPath[MAX_PATH] = {0}; 
  37. 37.::GetModuleFileName(NULL,szTempPath,MAX_PATH); 
  38. 38.(strrchr(szTempPath,'\\'))[1] = 0; 
  39. 39.strcat(szTempPath,"Temp"); 
  40. 40.BRAC_SetSDKOption(BRAC_SO_CORESDK_TMPDIR,szTempPath,strlen(szTempPath)); 
  41. 41.  
  42. 42.// 启用音频自动参数功能(默认关闭) 
  43. 43.DWORD bAudioAutoParam = TRUE
  44. 44.BRAC_SetSDKOption(BRAC_SO_AUDIO_AUTOPARAM,(PCHAR)&bAudioAutoParam,sizeof(DWORD)); 
 
二、登录系统
当第一步初始化完成之后,便可以连接服务器、验证用户身份。通常调用代码如下(C++):
 
  1. 1.// 连接服务器 
  2. 2.BRAC_Connect("211.155.25.90",8906); 
  3. 3.// 登录系统 
  4. 4.BRAC_Login("testuser","",0); 
连接服务器与登录系统都是一个异步的过程,调用后会立即返回,其中:
a、连接服务器成功,或是失败,将会触发异步消息
b、登录系统成功,或是失败,将会触发异步消息
所以应用程序需要响应这些异步消息才能知道连接服务器、登录系统是否成功。
 
登录系统成功后,如果需要实现即时通讯应用中的好友列表(AnyChat默认没有实现),则需要利用AnyChat的扩展API接口与Server SDK来配合实现,具体实现方案可参考SDK包中的:doc\server\目录下的《AnyChat Server SDK 开发指南》第6章节。
 
登录系统成功后,服务器会返回一个32位的用户ID,如果登录时没有传入密码参数,则系统会认为是游客登录,并分配一个独立的用户ID(如-1、-2等),如果登录时传入了密码参数,则登录请求将会交给“SDK Filter Plus”接口,或“Server SDK”对应的接口,用户可开发一个自己的服务器插件“SDK Filter Plus”,或是调用“Server SDK”所对应的API来处理用户身份验证的请求,完成对用户ID的管理,实现与第三方系统的互联互通,详细内容可参考SDK包中的:doc\server\目录下的相关文档。
 
三、进入房间
在第二步登录系统成功之后,就可以进入房间,因为只有在房间中,才能完成语音和视频的交互。通常调用代码如下(C++):
 
  1. 1.// 进入房间 
  2. 2.BRAC_EnterRoom(1,"",0); 
房间由服务器动态管理,由32位的房间ID号来唯一标示,当客户端指定的房间ID号不存在时,服务器将会自动创建。进入房间也是一个异步的过程,是否成功将会触发异步消息,进入房间成功后,服务器会把当前房间的在线用户列表传给客户端,传输完成后,将会触发异步消息(该消息只触发一次),只有收到服务器的在线用户列表后,才能对房间内的用户进行音视频的相关操作。
 
当自己进入房间成功,且收到服务器的在线用户消息后,有新的用户进入房间,或是老用户离开房间,将会触发异步消息,这样自己便知道谁进入,或是离开了房间。
 

1、打开自己的音视频

进入房间成功之后,便可以打开自己的音视频设备,通常调用代码如下(C++):
 
  1. 1.// 打开自己的视频设备 
  2. 2.BRAC_UserCameraControl(-1,TRUE); 
  3. 3.// 打开自己的音频设备 
  4. 4.BRAC_UserSpeakControl(-1,TRUE); 
打开自己的设备后,并不会立即上传音视频流,只有当其它用户请求自己的音视频数据时(可单独请求音频流,或视频流)才对外传输,打开自己的音视频设备,默认是按服务器的配置信息来初始化设备(如采样分辨率、视频帧率、音频的采样频率等)
 

2、请求其它用户的音视频

如果需要显示其它用户的音视频,则必须在收到房间用户列表消息后,请求对方的音视频流,然后对方才将音视频流传输过来,通常请求其它用户的音视频数据调用代码如下(C++):
 
  1. 1.// 请求对方的视频流 
  2. 2.BRAC_UserCameraControl(dwUserId,TRUE); 
  3. 3.// 请求对方的音频流 
  4. 4.BRAC_UserSpeakControl(dwUserId,TRUE); 
数据传输优先P2P方式,只有当P2P不通时,才由服务器转发,P2P的NAT打洞过程,以及数据流传输策略均由服务器控制,只要有请求,而且对方已打开了自己的音视频设备,则就能收到对方的音视频流数据。
 

3、音视频的播放与显示

当收到其它用户的音频数据后:
a)如果在初始化时设置了“BRAC_FUNC_AUDIO_AUTOPLAY”标志,则SDK内部将会自动播放,自动混音;
b)如果在初始化时设置了“BRAC_FUNC_AUDIO_CBDATA”标志,则SDK会将解码后的音频数据(PCM格式)通过回调函数回调给上层应用。
 
当收到其它用户的视频数据后
a)如果在初始化时设置了“BRAC_FUNC_VIDEO_AUTODISP”标志,并且调用了API,则SDK内部将会把视频显示到指定的窗体的指定位置(在指定位置上自动迭加一个视频窗口);
b)如果在初始化时设置了“BRAC_FUNC_VIDEO_CBDATA”标志,则SDK会将解码后的视频数据(RGB、YUV)通过回调函数回调给上层应用,由上层应用自己来绘制,或渲染,该模式适合于DirectX、HGE等没有窗口模式下的应用程序,或是上层应用需要对视频进行特殊处理的场合,如迭加文字、logo等。
 

4、文字交互

成功进入房间后, 便可以调用API接口向指定用户,或是房间中的所有用户发送文字消息:
 
  1. 1.// 发送文字消息 
  2. 2.CString strInput = "hello world"
  3. 3.BRAC_SendTextMessage(-1,FALSE,strInput.GetBuffer(0),strInput.GetLength()); 
其它用户收到自己发送的文字消息后,便会触发回调函数,通过处理回调消息,然后将收到的文字消息显示在界面上,便可实现文字的交互。
 

5、业务逻辑处理

 
AnyChat SDK内置的基本逻辑是:当自己的音视频设备打开后,别的用户有请求,便会将流媒体数据传输给对方,而没有任何何业务逻辑。
a)如要实现视频会议系统,则用户进入房间后,就需要知道谁是主持人,然后打开主持人的视频;
b)如要实现视频聊天系统,则用户进入房间后,就需要知道当前房间有几个公麦,谁在公麦上,然后打开对应公麦用户的视频等;
c)……
这些业务逻辑需要与服务器端的“SDK Filter Plus”或“AnyChat Server SDK”互相配合来实现,具体的实现方案可参考SDK包中的:doc\server\目录下的《AnyChat Server SDK 开发指南》第6章节。
 
四、释放资源
与前面连接服务器、登录系统、进入房间对应的,退出系统的过程是:离开房间、注销系统、释放资源,通常调用代码如下(C++):
 
  1. 1.// 离开房间 
  2. 2.BRAC_LeaveRoom(-1); 
  3. 3.// 注销系统(将关闭网络连接) 
  4. 4.BRAC_Logout(); 
  5. 5.// 释放资源 
  6. 6.BRAC_Release(); 
离开房间后,可以进入新的房间,系统注销之后,可以再次调用连接服务器的API接口,但是释放资源后,SDK将不再工作。