如何實現在服務端錄制視頻會議?
隨著遠程辦公與異地協作越來越頻繁,視頻會議系統的使用也是越來越普遍。同時,用戶對視頻會議系統的功能也提出了更高的要求,比如,其中之一就是希望可以將整個視頻會議的過程錄制下來,以備之后可以查閱觀看。
我們可以選擇在視頻會議系統的服務端或客戶端來錄制整個視頻會議過程,在服務端錄制與在客戶端錄制各有優劣。比如,在服務端錄制對服務器配置要求更高,因為同時可能有很多個會議同時錄制;而在客戶端錄制,錄制的文件存放在客戶端本地電腦上,只能在本地播放,如果其他人需要觀看,則需要在錄制完成后將該文件再上傳到服務器。
無論是在服務端錄制,還是在客戶端錄制,其技術原理是一樣的。這里我就 傲瑞視頻會議(OrayMeeting)在服務端(Windows、Linux、信創國產OS、銀河麒麟、統信UOS)錄制會議過程的技術原理和實現介紹給大家。
如下圖就是某會議錄制文件使用QQ影音播放的效果:

接下來,我們將具體介紹傲瑞視頻會議是怎么實現會議錄制的。
一. 錄制流程說明
(1)會議信息中心包含了一個字段,用于指示該會議是否開啟錄制。
(2)當第一個人進入會議時,啟動錄制。
(3)當到會議結束時間:若會議室沒有人,這立即結束錄制;若會議室還有人,等最后一個人退出時,結束錄制。
(3)任何時候,主持人結束會議,則將同時結束錄制。
(4)中途若會議室沒有人時,則暫停錄制;當再有人進入會議時,則繼續錄制。
二. 傲瑞會議錄制的畫面布局
(1)錄制畫面最上面有一行高為30px標題欄,將實時顯示如下信息:會議名稱、系統時間、參會人數。
(2)標題欄下面的剩下區域為內容區,用來渲染用戶視頻/頭像,或者是渲染用戶分享屏幕的桌面圖像。
(3)當參會人數不超過4個人時,采用2x2四宮格;當參會人數多于4個人時,采用3x3九宮格。
(4)錄制時最多渲染9個人的視頻或頭像(3x3),開啟了視頻的用戶排在最前面,其次是開啟了麥克風的用戶。
(5)如果用戶開啟了視頻,錄制時就渲染其視頻圖像,否則,就渲染該用戶的默認頭像。
(6)如果參會人員中有人開啟了屏幕分享,這錄制畫面的內容區將不再渲染用戶視頻/頭像,而是改為渲染被分享屏幕的桌面圖像。
三. 程序實現技術要點
(1)獲取參會人員的PCM聲音數據和RGB圖像數據。
使用 OMCS 提供的 MicrophoneConnector 和 DynamicCameraConnector 就可以獲取每個參會人員的聲音數據以及圖像數據。
(2)拼接并渲染要錄制的視頻圖像幀
在Windows可使用GDI+技術、在Linux上則可使用Skia技術來完成錄制圖像幀的拼接渲染。
if (desktopShare) //如果有人分享桌面,這主體內容區就是桌面圖像 { //獲取屏幕分享的最新桌面圖像幀 Image image = this.connectorManager.GetCurrentImage(null); canvas.SetDesktopImage(image); } else { for (int i = 0; i < recordMembers.Count; i++) { string userID = recordMembers[i]; Image image = null; if (!meeting.CamClosedMemberList.Contains(userID)) { //獲取參會成員的最新視頻圖像幀 image = this.connectorManager.GetCurrentImage(userID); } DrawInfo renderModel = this.drawInfoManagers.Get(userID); renderModel.SetCameraImage(image); renderModel.SetMicState(!meeting.MuteMemberList.Contains(userID)); } //繪制主體內容區 canvas.SetCameraImage(this.drawInfoManagers.GetAll()); } byte[] bytes = canvas.RenderImage(); //準備好要錄制的圖像 if (bytes != null) { this.videoFileMaker?.AddVideoFrame(bytes); //提交給錄制器 }
(3)混音
使用 OMCS 提供的 MicrophoneConnectorMixer 可以將參會人員的聲音混成一路。
IConnectorManager connectorManager = new OMCSConnectorManager(globalCache); connectorManager.AudioMixed += ConnectorManager_AudioMixed; private void ConnectorManager_AudioMixed(string userID, byte[] data) { if (recording && data != null) { this.videoFileMaker?.AddAudioFrame(data); //將混音數據提交給錄制器 } }
(4)定時器
使用定時器來調度聲音數據和圖像數據。比如:每隔10毫秒就從各個MicrophoneConnector獲取一幀語音數據,并將它們混音。每隔40毫秒就從各個 DynamicCameraConnector 獲取相應的圖像數據,并將它們拼接,并按照前面描述的畫面布局進行渲染。
//開啟錄制線程,定時調用 internal void StartRecord() { recording = true; Task.Factory.StartNew(() => { RecordThread(); }); } private void RecordThread() { int sleepSeconds = 1000 / frameRate; while (true) { System.Threading.Thread.Sleep(sleepSeconds); //record ... } }
(5)將圖像幀和聲音幀編碼并生成MP4文件。
將混音好的聲音數據、拼接好的渲染圖像提交給 MFile,MFile會將它們編碼并寫入到MP4文件中。
會議結束時,將結束錄制,并釋放相關的資源。
internal void FinishRecord() { recording = false; //釋放麥克風、攝像頭、桌面設備連接器 connectorManager.DisconnectAllConnect(); //釋放錄制器 videoFileMaker?.Close(true); }
四. 結語
在將錄制會議的流程、畫面布局、技術要點做了簡單介紹后,相信大家對視頻會議服務端在程序上是如何實現會議錄制功能的,已經初步了解了。
本文只是粗略地介紹了視頻會議錄制的原理與技術實現,如果你有更具體的實現細節需要了解的,歡迎與我討論。

浙公網安備 33010602011771號