背景分析
在之前的一篇博客《web無插件播放RTSP攝像機方案,拒絕插件,擁抱H5!》中,描述了實現一套H5無插件直播方案的各個組件的參考建議,又在博客《EasyNVR H5流媒體服務器方案架構設計之視頻能力平臺》中對整體的架構設計思路做了總結,做高內聚、低耦合的視頻能力平臺,不涉足業務部分!那麼今天,我們來公開一下EasyNVR到底是如何實現這些功能的;
一、程序框架
熟悉EasyDarwin的同學都知道,EasyDarwin作爲老牌的流媒體功能框架,在很多領域是完全能夠滿足開發者需求的,尤其是在安防領域,綜合其架構和性能,性價比極高,尤其是在網絡、多線程線程池、模塊化設計等方面,熟悉之後,可以衍生出很多功能類型的服務,這裏將要描述的EasyNVR就是其框架產物之一:EasyNVR based on EasyDarwin,底層網絡事件模型完全沿用EasyDarwin,只對其HTTPSession、Module部分做二次開發,包括HTTP協議、Json的協議棧都完全複用EasyDarwin的HTTPProtocol類和EasyProtocol框架,非常方便;
二、模塊設計
EasyNVR一共設計了兩個Module:EasyNVRModule和EasyCMSModule:
-
EasyNVRModule的主要工作就是做EasyNVR通道管理的功能,進行攝像機源與推流的銜接,EasyNVRModule總管理多個EasyNVRChannel,一路EasyNVRChannel就是一個設備源,EasyNVRChannel繼承自Darwin框架的Task類,這樣每一個EasyNVRChannel就可以獨立進行Task、Timeout、Event等多種功能了,這樣就能非常方便地實現:設備在線監測、設備定時快照、設備直播流獲取等多種功能,每一個EasyNVRChannel的所有輸出都共享一個RTSPSource源,這樣就能保證一路流媒體數據輸入,多種協議(JPEG、RTMP、HLS)輸出了!
-
EasyCMSModule是EasyNVR爲了擴展雲平臺對接功能擴展的,與具體平臺進行協議交互用到的,這個部分可以完全參考EasyDarwin的EasyCMSModule:https://github.com/EasyDarwin/EasyDarwin/tree/master/EasyDarwin/APIModules,對外的對接方法根據協議而定,這裏就不多描述了;
三、接口調用
在博客《基於EasyNVR二次開發實現自己的攝像機IPC/NVR無插件化直播解決方案》中,我們大概描述了EasyNVR是如何進行接口設計的,在代碼實現上,我們直接複用了EasyDarwin的HTTPSession功能,實現基於http+json的接口協議,例如獲取廣場視頻列表部分,我們在讀取到請求後,直接從EasyNVRModule獲取列表清單,反饋給客戶端:
QTSS_Error HTTPSession::execNetMsgCSGetChannelsRESTful(const char* queryString)
{
if(QTSServerInterface::GetServer()->GetPrefs()->liveStreamingAuth())
{
if (!isAuthenticate())
return EASY_ERROR_CLIENT_UNAUTHORIZED;
}
QTSS_Error theErr;
QTSS_RoleParams params;
params.easyNVRChannelsParams.inChannels = NULL;
theErr = EasyNVRUtil::CallDispatch(Easy_NVRGetChannels_Role, QTSSModule::kGetChannelsRole, params);
EasyProtocolACK rsp(MSG_SC_SERVER_GET_CHANNELS_ACK);
EasyJsonValue header, body;
header[EASY_TAG_VERSION] = EASY_PROTOCOL_VERSION;
header[EASY_TAG_CSEQ] = 1;
header[EASY_TAG_ERROR_NUM] = EASY_ERROR_SUCCESS_OK;
header[EASY_TAG_ERROR_STRING] = EasyProtocol::GetErrorString(EASY_ERROR_SUCCESS_OK);
if (theErr == QTSS_NoErr)
{
std::map<int, EasyNVRChannel*>* pChannels = static_cast<std::map<int, EasyNVRChannel*>*>(params.easyNVRChannelsParams.inChannels);
if (!pChannels) return QTSS_BadArgument;
Json::Value* proot = rsp.GetRoot();
int i = 0;
std::map<int, EasyNVRChannel*>::iterator it = (*pChannels).begin();
while (it != (*pChannels).end())
{
CameraInfo* item = it->second->GetChannelInfo();
if (item->enable != 0)
{
Json::Value value;
value[EASY_TAG_CHANNEL] = item->id;
//value[EASY_TAG_ENABLE] = item->enable;
value[EASY_TAG_ONLINE] = item->online;
value[EASY_TAG_NAME] = item->name;
value[EASY_TAG_SNAP_URL] = item->snap.empty() ? "" : item->snap;
value[EASY_TAG_ERROR_STRING] = item->lasterror.empty() ? "" : item->lasterror;
(*proot)[EASY_TAG_ROOT][EASY_TAG_BODY][EASY_TAG_CHANNELS].append(value);
++i;
}
++it;
}
body[EASY_TAG_CHANNEL_COUNT] = EasyUtil::Int2String(i);
}
rsp.SetHead(header);
rsp.SetBody(body);
string msg = rsp.GetMsg();
this->SendHTTPPacket(msg, false, false);
return QTSS_NoErr;
}
諸如此類,按照這種方式實現每一個http接口功能即可實現完整一套的http接口功能,對外進行能力輸出!
四、配套組件
在《web無插件播放RTSP攝像機方案,拒絕插件,擁抱H5!》中描述了很多組件:live555、ffmpeg、librtmp、faac等等,基於這些組件可以非常好地幫助您實現這些功能,但是這些組件都會存在不成熟或者不易使用的問題,EasyDarwin社區的開發者也實現了一系列此類功能的功能組件,例如:
-
EasyRTSPClient:類似於live555的RTSPClient功能組件,進行RTSP拉流;
-
EasyAACEncoder:AAC轉碼,將各種類型的安防音頻格式轉碼成標準H5需要的AAC格式,開源項目地址:https://github.com/EasyDarwin/EasyAACEncoder
-
EasyRTMP:RTMP推流工具,能非常好地實現推流,重連,數據緩衝,過濾等等功能;
五、細節亮點
- 按需直播
EasyNVR獨特設計了一套按需直播的方案,也就是可以配置EasyNVR的通道只有在有人看的時候,纔會從攝像機設備源取流到EasyNVR流媒體服務器進行直播,當沒有客戶端觀看的時候,直接切斷與源的連接,只做常態的設備狀態監測和快照功能,降低帶寬和服務器的壓力;
具體實現:客戶端頁面需要不斷向EasyNVR發送心跳包,保持具體某一個通道的流狀態,當超時時間內某通道沒有獲得心跳包,那麼就認爲該通道無人觀看,即停止從設備拉流!
- token認證
EasyNVR實現了一套authToken驗證機制,客戶端調用登陸接口後,客戶端會獲取到一個token,在本次操作的過程中,只要在http cookies中攜帶token,即可操作EasyNVR其餘接口,如果不攜帶token或者攜帶的token已經過期,EasyNVR會返回401,這樣客戶端需要重新調用EasyNVR登陸接口獲取新的token!
- 佔位設計
我們經常在做服務器時會遇到內外網映射的問題,當外網客戶端請求一個通過端口映射出來的內網服務器時,內網服務器往往不知道其所在的公網的IP地址,如果每次都是通過配置IP的方式,一方面是很麻煩,另一方面,很多網絡路由規則會限制內網的客戶端不能請求該內網所在的公網的IP,也就是內網的客戶端不能請求自己的公網IP的對外服務,內網的只能通過內網路由,而且內網請求內網IP就獲取到的是內網的直播流地址也是很合理的需求,於是,我們設計了一套佔位方案,比如客戶端請求一個RTMP的直播地址,我們返回給客戶端的地址是:rtmp://{host}:10935/hls/channel_1,那麼客戶端再根據自己請求到EasyNVR的host IP,替換{host}佔位符,就實現了,內網用內網的IP,公網用公網的IP了!
EasyNVR應用場景
- 把傳統分散的校園監控彙總到EasyNVR系統,實現把傳統的本地監控提升到隨時隨地的遠程監控,把傳統的純粹的監控上升到管理,使視頻監控成爲學校教學管理的有力工具。更重要的是讓家長一起參與,提升教學的主動性,提升學校聲譽和學校品牌。
- 將工地的攝像頭通過平臺對施工方、監理方和監管部門開放,方便實時瞭解工程進度,工地人員安全以及財產情況,自成力能平臺,專爲工地構建的視頻監控平臺。
- 隨着互聯網和移動互聯網被廣大消費者接受,“社會共治”將是是明廚亮竈目前的核心理念。採用社會共治方式,將各餐飲企業的後廚視頻通過EasyNVR系統讓老百姓通過手機可實時看到後廚的情況,既起到全社會監督的效果也是對餐飲企業的宣傳。
- 企業直播是以將企業內的環境、產品製作流程和產品等以直播的方式呈現出來,讓客戶看到企業的環境和透明化的生產,通過直播可以清清楚楚地看到所購買的產品生產過程。
關於EasyNVR
EasyNVR是一款擁有完整、自主、可控知識產權,同時又能夠具備軟硬一體功能的安防互聯網化流媒體服務器,能夠通過簡單的網絡攝像機通道配置,將傳統監控行業裏面的高清網絡攝像機IP Camera、NVR等具有RTSP、Onvif協議輸出的設備接入到EasyNVR,EasyNVR能夠將這些視頻源的音視頻數據進行拉取,轉換爲RTMP/HLS,進行全平臺終端H5直播(Web、Android、iOS),並且EasyNVR能夠將視頻源的直播數據對接到第三方CDN網絡,實現互聯網級別的直播分發。詳情可訪問EasyNVR官網:http://www.easynvr.com