C#实现多人语音聊天
在上一篇文章 实现一个简单的语音聊天室(多人语音聊天系统)中,我用C#实现了一个简单的语音聊天室,并给出了源代码下载。尽管有源代码,可是非常多朋友反映,理解起来还是有些模糊、不够清楚。如今想来,是由于我忘了先将底层的原理介绍一下,语音聊天室是基于OMCS实现的,那么这里我就补上OMCS中与多人语音视频相关部分的原理及方案的介绍。
一. 动态组
OMCS採用“动态组”的模式来实现多人语音/视频聊天组,所谓“动态组”,就是在执行时动态创建和销毁的组,其包括例如以下几层意思:
(1)当某个用户要增加一个不存在的动态组时,OMCSserver会首先自己主动创建这个组,然后,再把用户放进这个组。
(2)当用户退出组、或掉线时,OMCSserver会将该用户从相应的组中移除。
(3)当某个组中的最后一个人退出时,OMCSserver会销毁这个组。
在服务端,这一切都是自己主动完毕的,我们不须要额外编写代码。
二. OMCS.Passive.MultiChat 命名空间
在client,OMCS.Passive.MultiChat命名空间提供:IChatGroupEntrance接口、IChatGroup接口、IChatUnit类,通过这三个元素,我们便能够使用OMCS提供的对多人语音/视频聊天组的功能了。
1. IChatGroupEntrance
IChatGroupEntrance 是client使用多人语音/视频组的入口。

- /// <summary>
- /// 语音视频聊天组入口。
- /// </summary>
- public interface IChatGroupEntrance
- {
- /// <summary>
- /// 增加某个聊天组。假设目标组不存在,将自己主动创建目标组。
- /// </summary>
- /// <param name="chatType">聊天组的类型。</param>
- /// <param name="chatGroupID">目标组ID。</param>
- IChatGroup Join(ChatType chatType ,string chatGroupID);
- /// <summary>
- /// 离开聊天组。假设掉线,也会自己主动从聊天组中退出。
- /// </summary>
- /// <param name="chatType">聊天组的类型。</param>
- /// <param name="chatGroupID">目标组ID。</param>
- void Exit(ChatType chatType, string chatGroupID);
- }

OMCS将语音聊天组和视频聊天组是分开管理的,它们使用ChatType枚举来进行区分:

- /// <summary>
- /// 聊天组的类型。
- /// </summary>
- public enum ChatType
- {
- /// <summary>
- /// 语音聊天组。
- /// </summary>
- Audio = 0,
- /// <summary>
- /// 视频聊天组。
- /// </summary>
- Video
- }

(1)我们能够通过OMCSclient的核心组件 -- 多媒体管理器IMultimediaManager的ChatGroupEntrance属性获取到聊天组入口的引用。
(2)当调用IChatGroupEntrance 的Join方法增加某个聊天组,方法会返回一个IChatGroup引用,它代表了目标聊天组。
(3)语音聊天组和视频聊天组的ID能够同样,可是因为它们的类型(ChatType)不同,所以,它们仍然是不同的两个组。
(4)当调用Exit方法主动退出聊天组时,OMCS内部会自己主动释放该组内部持有的全部多媒体连接器实例(这些连接器实例位于即将介绍的IChatUnit内)。
2. IChatGroup
IChatGroup封装了一个聊天组的相关信息,其定义例如以下:

- /// <summary>
- /// 封装一个聊天组的信息。
- /// </summary>
- public interface IChatGroup
- {
- /// <summary>
- /// 当有新成员增加聊天组时,将触发此事件。
- /// </summary>
- event CbGeneric<IChatUnit> SomeoneJoin;
- /// <summary>
- /// 当某成员掉线或离开聊天组时,触发此事件。
- /// </summary>
- event CbGeneric<string> SomeoneExit;
- /// <summary>
- /// 聊天组的ID。
- /// </summary>
- string GroupID { get; }
- /// <summary>
- /// 聊天组的类型。假设为语音聊天,则DynamicCameraConnector为null。
- /// </summary>
- ChatType ChatType { get; } /// <summary>
- /// 获取组成员的信息。
- /// </summary>
- IChatUnit GetMember(string memberID);
- /// <summary>
- /// 获取组内除自己之外的其他成员的信息。
- /// </summary>
- List<IChatUnit> GetOtherMembers();
- }

(1)当有人增加或退出当前组时,IChatGroup会自己主动触发SomeoneJoin、SomeoneExit事件。
(2)GetOtherMembers方法将返回组内其他成员的信息,每一个成员都相应着一个IChatUnit实例。
3.IChatUnit
IChatUnit 主要是封装了与目标组成员相关的麦克风连接器、摄像头连接器。

- /// <summary>
- /// 用于封装聊天组一个成员的相关信息的单元。
- /// </summary>
- public interface IChatUnit
- {
- /// <summary>
- /// 相应的组成员的ID。
- /// </summary>
- string MemberID { get; }
- /// <summary>
- /// 是否有效?假设相应的组成员退出组或者掉线,则将返回false。
- /// </summary>
- bool Valid { get; }
- /// <summary>
- /// 摄像头连接器。(可将其连接到相应组成员的摄像头)。假设为语音聊天,则DynamicCameraConnector为null。
- /// </summary>
- DynamicCameraConnector DynamicCameraConnector { get; }
- /// <summary>
- /// 麦克风连接器。(可将其连接到相应组成员的麦克风)
- /// </summary>
- MicrophoneConnector MicrophoneConnector { get; }
- }

(1)特别注意:在通过IChatGroup获取到的IChatUnit时,其DynamicCameraConnector和MicrophoneConnector属性所代表的摄像头连接器及麦克风连接器都还没有与目标设备建立联系。
我们须要手动调用其BeginConnect方法,连接到该聊天成员的摄像头和麦克风设备。
同一时候,我们也能够预定其DynamicCameraConnector和MicrophoneConnector的种种事件和查看其种种属性,就像我们使用自己new的连接器组件一样。
而其实也是:IChatUnit 不过帮我们实例化了一下连接器组件而已,除此以外再没有做其他的不论什么动作。
(2)当组成员退出组或者掉线时,OMCS会自己主动断开IChatUnit中的连接器到目标设备的连接,而且将Valid属性设置为false。
三. 怎样使用
如果我们要开发一个视频会议的系统,在这个系统中,登录的用户能够输入一个视频会议房间的RoomID,便能够增加该视频会议。那么,实现的步骤大致例如以下:
1. 初始化多媒体管理器IMultimediaManager。
2. 调用IMultimediaManager的IChatGroupEntrance属性的Join方法,把RoomID传进去。便会返回一个IChatGroup引用。
3. 遍历IChatGroup的GetOtherMembers方法返回的集合中的每一个IChatUnit:
(1)为之创建一个UI控件,绑定到ChatUnit的DynamicCameraConnector,以显示成员的视频。
(2)预定IChatUnit的DynamicCameraConnector和MicrophoneConnector的相关事件,以获取所需的通知。
(3)调用IChatUnit的DynamicCameraConnector和MicrophoneConnector的BeginConnect方法,与该成员的设备进行连接。
4. 预定IChatGroup的SomeoneJoin、SomeoneExit事件。
(1)处理SomeoneJoin事件时,可与第3点一样。
(2)处理SomeoneExit事件时,仅仅需在UI上将退出的成员相应的视频显示控件移除掉。
5. 当自己要退出视频会议时,调用IMultimediaManager的IChatGroupEntrance属性的Exit方法就可以。
四. 扩展
OMCS内置的使用“动态组”模式对语音视/频聊天组的支持,不过最核心的支持,它只封装了最纯粹的逻辑。假设须要实现更复杂的自己定义业务逻辑,那就须要基于OMCS做很多其它的开发。
继续上面的样例,我们如果增加视频会议之前,须要先提交一个申请,在管理员批准之后,才干正式增加到视频会议中。那么类似这种业务需求单靠OMCS提供的API是无法实现的。
那么怎么做了?
我们能够在外围利用类似ESFramework等通信技术实现这一业务逻辑,详细步骤可參考例如以下:
(1)当用户输入了视频会议的房间号,并点击“申请增加”button时,client通过ESFramework发一条消息给在线的该视频会议的管理员。
(2)管理员所在的client收到请求消息后,在UI上弹出一个询问框,管理员点击“允许”button时,当前client就发送一条回复消息给申请的用户。
(3)申请的用户收到允许的回复后,就能够调用IMultimediaManager的IChatGroupEntrance属性的Join方法,来继续第三点中叙述的流程了。
OK,OMCS中对多人语音视频支持的部分介绍就到这里,大家如今再来看实现一个简单的语音聊天室(多人语音聊天系统)的源代码,应该就非常easy理解了。,
C#实现多人语音聊天的更多相关文章
- cordova使用webrtc与网页端及移动端视频、语音聊天
最近在做一个移动端与移动端.网页端文字.视频.语音聊天的功能.文字聊天使用websocket,在网上很多资料,也没什么难度.但是在视频.语音聊天上遇到了小小的难点.之前一直在找一些SDK想快速开发,例 ...
- 微信2.1 for Windows发布 微信群可多人语音或视频通话
5月31日,windows电脑版微信发布更新,微信2.1 for Windows带来最主要的功能是微信群可以多人语音或视频通话了,建个家庭群组,常年在外工作的家人也可以每天见面了,多亲切! 除了可以建 ...
- Android 高仿微信语音聊天页面高斯模糊效果
目前的应用市场上,使用毛玻璃效果的APP随处可见,比如用过微信语音聊天的人可以发现,语音聊天页面就使用了高斯模糊效果. 先看下效果图: 仔细观察上图,我们可以发现,背景图以用户头像为模板,对其进行了高 ...
- Unity3D 实现简单的语音聊天 [iOS版本]
现在很多手机游戏中的聊天系统都加入语音聊天的功能,相比于传统的文字聊天,语音聊天在MMORPG中显得尤为重要,毕竟直接口头交流总比你码字快得多了,也更直观些. 实现语音聊天的方法很多,U3D中有不少第 ...
- 基于JQuery+JSP的无数据库无刷新多人在线聊天室
JQuery是一款非常强大的javascript插件,本文就针对Ajax前台和JSP后台来实现一个无刷新的多人在线聊天室,该实现的数据全部存储在服务端内存里,没有用到数据库,本文会提供所有源程序,需要 ...
- Android 即时语音聊天工具 开发
使用融云SDK 1. 功能需求分析 1.1 核心功能需求: * 即时通讯 * 文字聊天 * 语音聊天 1.2 辅助功能需求: * 注册.登录 * 好友添加功能 * 好友关系管理 2. 融云即时通讯平台 ...
- 基于C#局域网语音聊天
基于C#局域网语音聊天室,可实现文本消息的发送.接收及语音聊天,是一个很不错的,适合初学者的软件开发 ...
- C# 实现语音聊天
一.语音聊天说专业点就是即时语音,是一种基于网络的快速传递语音信息的技术,普遍应用于各类社交软件中,优势主要有以下几点: (1)时效性:视频直播会因为带宽问题有时出现延迟高的问题,而语音直播相对来说会 ...
- html5聊天案例|趣聊h5|仿微信界面聊天|红包|语音聊天|地图
之前有开发过一个h5微直播项目,当时里面也用到过聊天模块部分,今天就在之前聊天部分的基础上重新抽离模块,开发了这个h5趣聊项目,功能效果比较类似微信聊天界面.采用html5+css3+Zepto+sw ...
随机推荐
- 雪碧图(sprite)
雪碧图 是一种将网页上常用且不经常变动的小图标集中在一张大图中,根据网页需求来显示图片的技术. 可以提高网页加载速度,增加用户体验. 其原理是通过html块状元素建立一个满足需求的视图窗口,然后在窗口 ...
- 虎说:bootstrap源码解读(重置模块)
------<!--action-->------ 开场show:前不生“不犹豫”,后半生“不后悔”.今天又逃课,我不后悔 素材:推特公司的前端框架bootstrap(下称bt),解读源码 ...
- [LeetCode]题解(python):001-Two-Sum
题目来源: https://leetcode.com/problems/two-sum/ 题意分析: 这道题目是输入一个数组和target,要在一个数组中找到两个数字,其和为target,从小到大输出 ...
- (Problem 49)Prime permutations
The arithmetic sequence, 1487, 4817, 8147, in which each of the terms increases by 3330, is unusual ...
- 读取IOS的相应路径
// IOS相应路径 NSString* bundlePath = [[NSBundle mainBundle] bundlePath]; NSLog(@"bundlePath = % ...
- 关于Qt信号与槽机制的传递方向性研究(结论其实是错误的,但是可以看看分析过程)
最近由于项目的需求,一直在研究Qt.信号与槽机制是Qt的一大特色,该机制允许两者间传递参数,依次来实现对象间的通信.这个参数会分别存在于信号的参数列表和槽函数的参数列表中.需要注意的是,若将槽函数绑定 ...
- html img 使用data格式加载图片
背景 这久闲来无事给一位客户测试一款体检软件,是winform结构的,其中有一个功能是需要把生成的体检报告导出为html格式.测试导出后直接在谷歌浏览器里查看,体检详细内容.医生签名.条形码都能正常显 ...
- Java学习之DBUtils工具的学习
简介 commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影 ...
- .c和.h文件的区别(头文件与之实现文件的的关系~ )
.c和.h文件的区别 一个简单的问题:.c和.h文件的区别 学了几个月的C语言,反而觉得越来越不懂了.同样是子程序,可以定义在.c文件中,也可以定义在.h文件中,那这两个文件到底在用法上有什么区别呢 ...
- 利用jxl读取excel合并的单元格的一个小样例
工作中我们可能要把Excel文件的记录保存到数据库, 今天我用jxl读取Excel文件时遇到了合并格的问题,记录例如以下: 如Excel文件例如以下: watermark/2/text/aHR0cDo ...