在客製化開發視訊會議系統時,有客戶需要將視訊會議的過程錄製下來。一個視訊會議是多個使用者參與的,每個使用者都有自己的視訊和聲音。錄製視訊會議就需要將他們的視訊和聲音錄製到一個mp4檔案中。
這個時候,在視訊方面就涉及到影象的合成,在聲音方面就涉及到混音。所謂混音,就是將多路聲音資料經過混音演演算法計算後,合成一路輸出。其示意圖如下所示:
有的視訊會議系統專案要求在使用者端錄製,有的則需要在伺服器端錄製,這兩種情況,對於所採用的混音器會有所區別。
OMCS提供的兩種混音器元件:AudioInOutMixer 和 MicrophoneConnectorMixer,分別用於支援這兩種情況。
AudioInOutMixer 用於在使用者端錄製時使用,MicrophoneConnectorMixer 用於在伺服器端錄製時使用。
在使用者端錄製時,一般需要錄製當前使用者所參與的語音視訊對談。 OMCS.Passive.Audio.AudioInOutMixer 的作用就是將本地話筒裝置的輸入資料以及本地聲音播放的輸出資料進行混音。
AudioInOutMixer 介面定義如下所示:
public classIAudioInOutMixer { /// <summary> /// 本地話筒裝置採集的一幀音訊資料以及本地揚聲器播放的一幀輸出資料進行混音。(音訊資料長度:10ms) /// </summary> event CbGeneric<byte[]> AudioMixed; /// <summary> /// 初始化 /// </summary> /// <param name="mgr"></param> void Initialize(IMultimediaManager mgr); /// <summary> /// 釋放混音器。 /// </summary> void Dispose(); }
(1)呼叫Initialize 初始化混音器後,混音器變開始正常工作。
(2)AudioMixed 會每隔10ms觸發一次,每次輸出10ms的混音資料。
(3)當使用完畢後,需要呼叫混音器的Dispose方法釋放混音器。
在伺服器端錄製與在使用者端錄製是非常不一樣的,差別在於:
(1)一般在使用者端只需要錄製一個對談,即當前登入使用者參與的那個對談。而在伺服器端,通常需要同時錄製多個對談。
(2)使用者端錄製時,只需要將麥克風的聲音與喇叭播放的聲音混音,就是全部了。
而在伺服器端錄製時,需要拿到參與目標對談的所有使用者的聲音資料進行混音。而且,還要考慮到使用者動態地加入或退出目標對談的情況。
在伺服器端錄製時,每個錄製任務都需要new一個對應的OMCS.Passive.Audio.MicrophoneConnectorMixer 。
MicrophoneConnectorMixer 用於將多個MicrophoneConnector的聲音資料進行混音。
MicrophoneConnectorMixer 介面定義如下:
public class MicrophoneConnectorMixer { /// <summary> /// 每隔20毫秒觸發一次,輸出混音資料。引數:聲音最大的發言人UserID - data。 /// 如果此時無人發言,則UserID引數為null,data為靜音資料。 /// </summary> event CbGeneric<string, byte[]> AudioMixed; /// <summary> /// 新增要參與混音的MicrophoneConnector。 /// </summary> void AddMicrophoneConnector(MicrophoneConnector mc); /// <summary> /// 移除參與混音的MicrophoneConnector。 /// </summary> void RemoveMicrophoneConnector(string ownerID); /// <summary> /// 釋放混音器。 /// </summary> void Dispose(); }
(1)呼叫AddMicrophoneConnector、RemoveMicrophoneConnector 可以動態新增和移除使用者。
(2)請特別注意: 混音器僅僅是從MicrophoneConnector 獲取聲音資料,並不會呼叫其 BeginConnector 或 Disconnect 方法。
MicrophoneConnector 必須要連線成功後,才呼叫AddMicrophoneConnector將其加入到混音器中。
(3)使用完畢時,切記要呼叫Dispose方法釋放混音器。
在混音器實際使用的過程中,為了達到最佳的混音效果,還有一些可以優化的地方。
(1)當很多人都同時在發言時,如果將所有的聲音都加入到混音,可想而知,混音的結果就是亂哄哄的。
這種情況下,我們可以只混音發言音量最大1~3個人。
(2)在騰訊視訊會議裡,有個很人性化的功能,就是當某個人發言時(或其音量最大時),其視訊影象會放大,以將使用者的注意力焦點集中在發言人身上。
這兩種優化都是在混音器裡實現的,其底層的實現原理大致是這樣的:
(1)將多路語音幀在混音之前,先分別計算每個幀的分貝值。(通過傅立葉變換就可以計算出聲音的分貝值)
(2)將計算出的多個分貝值進行排序,從大到小排列。
(3)只將分貝值最大的前1~3的語音幀提交給混音演演算法。
(4)在輸出混音結果時,同時將分貝值最大的使用者的ID也同時輸出。
通過設定IMultimediaManager的Advanced的AudioMixedStrategy屬性,即可指定需要將分貝值最大的前幾個混音。
/// <summary> /// 混音策略。 /// </summary> public enum AudioMixedStrategy { /// <summary> /// 只要有聲音資料的line,都參與混音。 /// </summary> All = 0, /// <summary> /// 只混音分貝值排名第一的line。 /// </summary> DecibelTop1, /// <summary> /// 只混音分貝值排名前二的line。 /// </summary> DecibelTop2, /// <summary> /// 只混音分貝值排名前三的line。 /// </summary> DecibelTop3 }
我們再看MicrophoneConnectorMixer 的 AudioMixed事件,它不僅輸出了混音資料,而且還輸出了發言聲音最大音量的那個使用者的ID。
經過上述優化後,混音器輸出的資料就非常好用了,可以滿足當前視訊會議專案實際的錄製需求了。