實時流(直播流)播放、上牆(大屏播放)解決方案


場景描述

將實時流采集終端的視頻數據實時推送到另外一個(多個)播放終端,完成遠距離實時視頻播放的功能。典型場景:

(1)遠程查看監控攝像頭。選擇指定攝像頭,將該攝像頭采集到的實時數據推送到指定播放終端,供值班(監控中心)人員查看。包括實時視頻上牆,推送到指定大屏幕上;

(2)直播系統。用戶在PC上安裝推流工具,抓取屏幕(麥克風)實時數據,推送給觀看直播的觀眾。

 

解決方案

要完成端到端的流推送,我們需要借助中間件來完成,常用到的有Nginx Rtmp模塊,用來中轉視頻數據。實時流采集終端根據給定的地址將數據推送到Nginx流媒體服務器,播放終端根據給定的地址從Nginx流媒體服務器上拉取數據,呈現給用戶。

實時流播放結構圖

如果多個用戶需要播放同一個實時流數據,那么理想情況下,推流端的數據應該可以復用,也就是說,推流端只需要推一路流,供多個播放終端使用。此時推流端和播放端是一對N的關系

多個用戶播放同一個實時流數據

如果播放用戶很多,推流端和播放端數量大,只靠一台流媒體服務器轉發數據肯定不行。這時候需要多台流媒體服務器協同工作,當有多個流媒體服務器時,就會出現一個問題:當用戶請求實時流,該如何為它分配流媒體服務器呢?此時,就會引入另外一個概念:負載均衡。當有多台流媒體服務器時,我們需要通過某種策略去計算,得出最適合的流媒體服務器,比如找出當前負載量最小的服務器,給用戶使用。

多個流媒體服務器

如上圖,存在多個流媒體服務器時,負載均衡需要根據指定的策略計算出最佳的服務器地址,然后推流端和播放端根據地址分別推流拉流。圖中由計算得出,使用流媒體服務器1

 

 

實現技術

用到的技術、工具:

(1)CentOS 6.5 + Tomacat 8.0 + Mysql + Spring,java web后台,接收用戶請求、負載計算、流狀態同步、發送推流指令等等;

(2)ffmpeg,推流工具,供C++調用;

(3)RabbitMQ,web后台與推流端傳遞消息;

(4)Nginx 1.12.0 + rtmp module,具體可以查看官方第三方module list, 流媒體轉發;

(5)VLC C#開發工具,用來拉流,網上有公開API調用方法,用來做客戶端demo,后面的截圖都是基於該demo;

(6)jwplayer,實際中web前端實時流播放控件。

 

詳細實現

(1)關於Nginx+rtmp模塊實現實時流轉發的內容這里就不再寫了,網上很多教程,也非常簡單,不需要手寫任何代碼;

(2)Java web后台采用SpringMVC + Mybatis,只需要實現一些http接口即可;

這里詳細說一下負載計算這塊的邏輯,該模塊與web后台分開,可以單獨部署。

該模塊屬於java 后台的一部分,當然也可以分開部署,它與web后台是通過數據庫中的請求表同步數據。接下來是負載均衡中生成rtmp的邏輯,rtmp也就是本文開頭提到的推流\拉流地址了。

推流端和拉流端可以通過給定的rtmp進行推拉流,Nginx流媒體服務器(具體應該是rtmp模塊)在收到推流開始(publish_start)、推流結束(publish_done)、拉流開始(play_start)以及拉流結束(play_done)時,都會按照配置文件中的配置進行http回調,該回調地址配置成java 負載均衡后台。我們需要在該回調中更新流媒體服務器的狀態,比如流媒體服務器的當前負載數,用於下次負載計算。

 

有時候http回調會失敗,這就會導致負載均衡模塊中保存的流媒體服務器的狀態有誤差,所以我們需要主動同步流媒體服務器的負載狀態:

 

負載計算的另一個非常重要的標准就是檢查流媒體服務器是否在線,如果不在線,那么這台流媒體服務器就不在我們考慮的范圍之內。主動檢查流媒體服務器狀態:

 

Demo演示

由於各種原因,這里只能掛一些demo的圖片:

Demo1

在百度地圖中按區域查找攝像頭,選擇攝像頭,查看攝像頭實時視頻數據。流程為:請求視頻->負載計算rtmp->推流開始->拉流開始。百度地圖控件請參照之前開源的代碼:https://github.com/sherlockchou86/BMap.NET

 

Demo2

選擇攝像頭,將攝像頭實時流推到大屏上。流程為:請求大屏上牆(攜帶大屏ID)->計算rtmp->推流開始->拉流開始。下圖為大屏模擬管理器:

 

當大屏就緒后,開始播放,管理器狀態更新:

大屏模擬器界面,支持斷線恢復。關閉終端后,再次打開,流推送不會中斷:

方案總結

(1)推流端和拉流端是1->N的關系,對於每一路推流,可以同時存在多個拉流端,即推流可以復用。當多個用戶請求同一資源(如同一攝像頭)時,只需要推一路流即可,這時候每個用戶的拉流地址rtmp相同。

(2)推流和拉流之間需要流媒體服務器作為橋梁,負責實時流的轉發工作。這里使用的時Nginx+rtmp module,網上有詳細教程。

(3)流媒體服務器的選擇需要經過負載均衡計算得出,負載計算的策略包含:流媒體服務器是否在線、負載數(當前播放鏈路)是否達到服務器的上限、請求的資源是否已被推流(即可以復用,這種情況下,直接返回之前的rtmp即可,不需要重新分配服務器)。

(4)Nginx+rtmp模塊的配置文件中,有一項是配置‘狀態回調’的地址,當流媒體服務器的狀態發生變化時,會通過該回調告知java 后台。

 

沒有源碼提供,有問題的朋友可以留言或者私信。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM