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

場景描述前端

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

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

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

 

解決方案web

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

實時流播放結構圖數據庫

若是多個用戶須要播放同一個實時流數據,那麼理想狀況下,推流端的數據應該能夠複用,也就是說,推流端只須要推一路流,供多個播放終端使用。此時推流端和播放端是一對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 後臺。

 

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

相關文章
相關標籤/搜索