在上一篇文章 實現一個簡單的語音聊天室(多人語音聊天系統)中,我用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理解了。,