1. 程式人生 > >C#實現多人語音聊天

C#實現多人語音聊天

在上一篇文章 實現一個簡單的語音聊天室(多人語音聊天系統)中,我用C#實現了一個簡單的語音聊天室,並給出了原始碼下載。雖然有原始碼,但是很多朋友反映,理解起來還是有些模糊、不夠清楚。現在想來,是因為我忘了先將底層的原理介紹一下,語音聊天室是基於OMCS實現的,那麼這裡我就補上OMCS中與多人語音視訊相關部分的原理及方案的介紹。

一. 動態組  

  OMCS採用“動態組”的模式來實現多人語音/視訊聊天組,所謂“動態組”,就是在執行時動態建立和銷燬的組,其包含如下幾層意思:

(1)當某個使用者要加入一個不存在的動態組時,OMCS伺服器會首先自動建立這個組,然後,再把使用者放進這個組。

(2)當用戶退出組、或掉線時

,OMCS伺服器會將該使用者從對應的組中移除。

(3)當某個組中的最後一個人退出時,OMCS伺服器會銷燬這個組。

  在服務端,這一切都是自動完成的,我們不需要額外編寫程式碼。

二. OMCS.Passive.MultiChat 名稱空間

  在客戶端,OMCS.Passive.MultiChat名稱空間提供:IChatGroupEntrance介面、IChatGroup介面、IChatUnit類,通過這三個元素,我們便可以使用OMCS提供的對多人語音/視訊聊天組的功能了。

1. IChatGroupEntrance

  IChatGroupEntrance 是客戶端使用多人語音/視訊組的入口

複製程式碼
    /// <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)我們可以通過OMCS客戶端的核心元件 -- 多媒體管理器IMultimediaManagerChatGroupEntrance屬性獲取到聊天組入口的引用。 

(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是無法實現的。

  那麼怎麼做了?

  我們可以在外圍利用類似 等通訊技術實現這一業務邏輯,具體步驟可參考如下:

(1)當用戶輸入了視訊會議的房間號,並點選“申請加入”按鈕時,客戶端通過ESFramework發一條訊息給線上的該視訊會議的管理員。

(2)管理員所在的客戶端收到請求訊息後,在UI上彈出一個詢問框,管理員點選“同意”按鈕時,當前客戶端就傳送一條回覆訊息給申請的使用者。

(3)申請的使用者收到同意的回覆後,就可以呼叫IMultimediaManager的IChatGroupEntrance屬性的Join方法,來繼續第三點中敘述的流程了。

OK,OMCS中對多人語音視訊支援的部分介紹就到這裡,大家現在再來看 實現一個簡單的語音聊天室(多人語音聊天系統) 的原始碼,應該就很容易理解了。,