項目背景是java,前端angular按照java的尿性做設備驅動如果沒有底層支持的話直播會是個入坑點。
直播的方案如果不去說主流直播行業(yè),攝像頭只是單獨的功能點的話,基本上都是繞不開ffmpeg的,有window系統(tǒng)直接用ffmpeg.exe拼接命令推流的,有使用javacv的。鑒于服務是多平臺部署,windows,linux多端運行的,還是考慮一下兼容性采用javacv方案。
sdk方式和onvif方式不同點在于云臺控制和預置點操作一個調(diào)用SDK,一個是采用onvif通信協(xié)議,兩者實現(xiàn)方式不盡相同,但是效果大同小異。
話不多說,開干!
去??灯脚_下載最新的sdk的實例,文檔寫的比較雜,但是還是能找到對應版本的實現(xiàn)的。
先解決sdk調(diào)用動態(tài)庫的問題,我們先需要一個sdk的實例。
寫一個SdkInstanceUtil的工具類來創(chuàng)建sdk的實例


加載實例需要注意windows加載實例和linux加載實例有區(qū)別,我們的動態(tài)庫放在配置文件中,

動態(tài)庫配置完成后,增加一個LoadRsource的類將動態(tài)庫加載,sdk文檔中有對應的加載方式,這里就不多寫了,這是第一個避坑點,多讀文檔沒壞處。(我是踩了幾次的,因為我們是docker部署的,那個酸爽。。。。)
還是介紹一下docker里面dockerfile的傻瓜配置方式,就是容器加載動態(tài)庫,不用增加loadResouce這個操作。

接下來就是調(diào)用sdk提供的接口進行業(yè)務組裝的過程。
首先我們是兩套sdk,windows和linux版本的,也就是說我們會有兩套sdk的接口代碼,但是我們的業(yè)務可以只寫一套撒,面向接口編程撒,
我們首先抽象出一套接口,建一個接口叫SdkProxyService,當當當當,粗線吧:

接下來需要實現(xiàn)一下具體平臺對應的service

然后根據(jù)平臺注入對應的service,

接下來就是我們的業(yè)務接口了,再寫一個接口,這個就是我們的業(yè)務組裝,需要sdk中哪些業(yè)務組合起來構成我們自身的業(yè)務邏輯。
具體的實現(xiàn)應該是播放,云臺和預置點操作等等:

sdk的實時播放有提供回調(diào)的方式和不提供回調(diào)的方式,兩者區(qū)別不大,基本上都有返回播放句柄的參數(shù),但是問題在于sdk播放時給的流是ps碼流,前端是無法直接播放的,關于ps碼流抽流的操作比較復雜,我翻了一篇文檔大概十幾萬字,看自閉了。
實時播放采用rtsp->javacv->rtmp容器,前端播放rtmp或者http地址。這里需要增加一個rtmp的容器。
推流引包:

真正的坑來了哈。
開始進坑,這個坑怎么說呢,rtsp協(xié)議是一種流媒體的協(xié)議,可以遠程查看攝像頭畫面,但是問題是前端瀏覽器么有一款播放器可以播放rtsp的流,有童鞋就說了 ,我可以用vlc插件,vlc可以,但是chrome41以上就不支持了,ie是可以的,火狐也不行,有童鞋又說了我們可以用websocket中轉幀,這就是另外的解決方案了,我們隨后再講,先講javacv的拉流推流的操作。
采用h264轉flv的方式直接轉碼推,talk is cheap,show me the code!




先把錄制器和解碼器構建完畢后放入線程開始推畫面

推流線程中有一個錄制器的結束標識,這里的作用主要是用來結束線程,之前用的callable這里后來改掉了可以改成runnable,這里的直播采用的是多個用戶看一個,也就是說一個攝像頭只推一路,再來一個人就把redis里面的計數(shù)器+1,當最后一個人關掉視頻時,將錄制器里的結束輸入流置為true,這時候線程就可以結束了。
dto.getGrabber().setCloseInputStream(true);
如果是多實例部署的話,需要注意訪問實例是否是推流線程所在實例,我們這邊采用的是kafka廣播做的,當然這種方法比較懶省事,可以記錄一下實例id去調(diào)對應實例的接口,多實例必然要用redis在記錄當前設備推流的信息,避免多個實例同時推一個設備的現(xiàn)象,比較浪費資源。
sdk可能會出現(xiàn)臨時文件限制的問題,這個百度一下即可解決,轉碼需要關注內(nèi)存消耗情況。
再講一下websocket代理轉幀的方式,以上方案采用的方式大體流程如下:
rtsp->ffpmeg->rtmp->前端
其中rtmp是一個容器,websocket轉幀的話采用的方式與這個方式大同小異前面兩部分不變,不再使用rtmp容器而是將流推入websocket服務器,前端使用jsmpeg.js將websocket中的幀畫面繪制在canvas中。
推流方式不變將轉碼的方式由flv變?yōu)閙peg1video(敲黑板),推流地址變?yōu)橐粋€websocket服務器,前端不再使用vedio.js這種播放器啦。具體實現(xiàn)方式看各自項目需求。下篇講onvif。