目前网上视频聊天室、视频会议软件、可视IP电话软件随处可见,你是否想自己做一个玩玩?其实这类软件无非是视频加上网络而建成的。如果熟悉视频捕 捉和网络传输技术,根本就难不倒你。本文详细介绍了如何利用别人提供的sdk来开发视频聊天室
首先介绍一下视频聊天技术发展历程

  1 C/S结构的视频聊天软件或插件。这是最早的视频聊天开发技术,已经被淘汰。

  2 P2P模式的视频聊天软件或插件。这是前几年以及目前很多大型视频聊天项目的主要使用技术。也是很多小型视频聊天室使用的技术。

  3、基于P2P模式+C/S模式混合。这是目前来说,性能最高的技术架构模式。比如QQ等聊天工具的视频聊天功能。在P2P双方网络连接速度快的情况下使用P2P,速度慢的情况下使用C/S模式。

  4、纯WEB的,基于视频服务器搭建的B/S结构视频聊天网站。这是前1-2年视频技术的主要研究方向。这种模式准确的说是在网站上可以使用的C/S结构。和第一阶段C/S结构性能差别不大,但拥有强大的跨平台优势。由于其性能上无法和第2、第3阶段的性能相比,而导致研究的多,但实用少,产品少。

5 、 纯WEB的基于视频服务器的B/S结构+加上FLASH P2P结构。此阶段是目前视频技术的主要研究方向。但是目前的FLASH P2P无法实现数据分发、转发等功能,采用1个人和多个人同时建立P2P连接传输数据的模式,所以,当人数比较多的时候,此模式会很大的占用客户端的带宽。所以,此模式需要和B/S模式进行搭配。当人数多的时候,使用视频服务器,当人数少的时候,使用P2P

接下来就是开发所会用到的工具以及用什么语言来开发的介绍

为了让大家更好的开发自己所需要的与音视频即时通讯相关的系统。我向大家介绍介绍如何利用这个SDK来去开发,大家可以理解成为开发指南吧

首先下载这个SDK,已经上传到了51cto的网站上面去,大家放心使用。( windows平台音视频即时通讯应用开发包

支持Windows平台音频即时通讯应用开发

支持C++C#JavaDelphiVB.NetQt等开发语言

集成H.264AACAMR等编解码技术

封装音视频的采集、编解码、传输、显示和播放等模块

提供客户端SDK和服务器SDK API接口

 
下面是使用指南:(以 c++ 为例子)

一、初始化

该部分是首先要完成的,用于设置 SDK 的一些行为,包括设置对应的回调函数、设置 SDK 组件路径、设置是否产生日志文件等,通常初始化 AnyChat SDK 的代码如下( C++ ):

 

 
InBlock.gif // 打开(关闭)SDK的日志记录功能
InBlock.gifBRAC_ActiveCallLog(TRUE);
InBlock.gif    
InBlock.gif // 设置SDK核心组件所在目录
InBlock.gifCHAR szCoreSDKPath[MAX_PATH] = {0};
InBlock.gifGetModuleFileName(NULL,szCoreSDKPath, sizeof(szCoreSDKPath));
InBlock.gif(strrchr(szCoreSDKPath,'\\'))[1] = 0;
InBlock.gifBRAC_SetSDKOption(BRAC_SO_CORESDK_PATH,szCoreSDKPath,strlen(szCoreSDKPath));
InBlock.gif    
InBlock.gif // 根据BRAC_InitSDK的第二个参数:dwFuncMode,来告诉SDK该如何处理相关的任务(详情请参考开发文档)
InBlock.gifDWORD dwFuncMode = BRAC_FUNC_VIDEO_CBDATA | BRAC_FUNC_AUDIO_AUTOPLAY | BRAC_FUNC_CHKDEPENDMODULE | BRAC_FUNC_AUDIO_VOLUMECALC | BRAC_FUNC_NET_SUPPORTUPNP | BRAC_FUNC_FIREWALL_OPEN |
InBlock.gifBRAC_FUNC_AUDIO_AUTOVOLUME | BRAC_FUNC_CONFIG_LOCALINI;
InBlock.gifBRAC_InitSDK( this->GetSafeHwnd() /*NULL*/,dwFuncMode);
InBlock.gif    
InBlock.gif // 设置录像临时文件保存路径
InBlock.gifCHAR szRecordDirectory[MAX_PATH] = {0};
InBlock.gif::GetModuleFileName(NULL,szRecordDirectory,MAX_PATH);
InBlock.gif(strrchr(szRecordDirectory,'\\'))[1] = 0;
InBlock.gifstrcat(szRecordDirectory, "Record");
InBlock.gifBRAC_SetSDKOption(BRAC_SO_RECORD_TMPDIR,szRecordDirectory,strlen(szRecordDirectory));
InBlock.gif
// 设置录像文件质量参数
InBlock.gifDWORD dwVideoBitrate = 200 * 1000;     // 200kbps
InBlock.gifBRAC_SetSDKOption(BRAC_SO_RECORD_VIDEOBR,(PCHAR)&dwVideoBitrate, sizeof(DWORD));
InBlock.gifDWORD dwAudioBitrate = 96 * 1000;     // 96kbps
InBlock.gifBRAC_SetSDKOption(BRAC_SO_RECORD_AUDIOBR,(PCHAR)&dwAudioBitrate, sizeof(DWORD));
InBlock.gif    
InBlock.gif // 设置快照临时文件保存路径
InBlock.gifCHAR szSnapShotDirectory[MAX_PATH] = {0};
InBlock.gif::GetModuleFileName(NULL,szSnapShotDirectory,MAX_PATH);
InBlock.gif(strrchr(szSnapShotDirectory,'\\'))[1] = 0;
InBlock.gifstrcat(szSnapShotDirectory, "SnapShot");
InBlock.gifBRAC_SetSDKOption(BRAC_SO_SNAPSHOT_TMPDIR,szSnapShotDirectory,strlen(szSnapShotDirectory));
InBlock.gif    
InBlock.gif // 设置SDK临时文件路径
InBlock.gifCHAR szTempPath[MAX_PATH] = {0};
InBlock.gif::GetModuleFileName(NULL,szTempPath,MAX_PATH);
InBlock.gif(strrchr(szTempPath,'\\'))[1] = 0;
InBlock.gifstrcat(szTempPath, "Temp");
InBlock.gifBRAC_SetSDKOption(BRAC_SO_CORESDK_TMPDIR,szTempPath,strlen(szTempPath));
InBlock.gif
// 启用音频自动参数功能(默认关闭)
InBlock.gifDWORD bAudioAutoParam = TRUE;
InBlock.gifBRAC_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 将不再工作。