最近需要在web項目中顯示監(jiān)控視頻,采用了webrtc+webrtc-streamer+coturn的方案實現(xiàn),能夠在公網(wǎng)上做很低的延時,對于實時監(jiān)控視頻有很好的效果,是目前來講比較好的一個選擇方案。
1、webrtc 用于視頻流的顯示。
2、webrtc-streamer負責去監(jiān)控視頻主機(這里多數(shù)是NVR或DVR)去拉取RSTP視頻流,并轉(zhuǎn)發(fā)到Webrtc中進行顯示。
3、coturn用于webrtc與webrtc-streamer之間的通信穿透服務,主要作用是穿透做NAT穿透,讓雙方找到能互相找到。
網(wǎng)絡(luò)邏輯結(jié)構(gòu)圖
一、webrtc-streamer安裝
這里采用的是CentOS 7系統(tǒng),直接采用的Docker安裝,關(guān)于Docker安裝可以參考《Kubernetes安裝記錄》的docker部分。
docker pull mpromonet/webrtc-streamer
docker run -itd -p 8000:8000 --name webrtc-streamer mpromonet/webrtc-streamer -s120.92.19.150:3478 -tnoka:noka@120.92.19.150:3478
這里后面的-t和-s參數(shù)分別指向cotum的strun和tun服務,這里同內(nèi)一定要用自己搭建的穿透服務,webrtc-streamer內(nèi)置的服務是指向goole提供的一個服務,國內(nèi)訪問及其不穩(wěn)定,關(guān)于cotum的安裝請參照官網(wǎng)。這里啟動好以后,就可以通過瀏覽器訪問8000端口的服務了,這里可以通過以下地址來驗證視頻流服是否成功。
http://ip:8000/webrtcstreamer.html?rtsp://admin:admin@ip:554/Streaming/Channels/101
如果上面的地址能播放視頻,說明配置成功了,地址后面的參數(shù)是視頻流的地址。
二、web端視頻顯示代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- webrtc公用庫-->
<script src="/js/adapter.js"></script>
<!-- webrtc-streamer調(diào)用庫,來自webrtc-streamer-->
<script src="/js/webrtcstreamer.js"></script>
</head>
<body>
<!-- 視頻顯示部分 -->
<div id="play_div"></div>
<script>
var webRtcServerList = [];//視頻流服務對象部分
var urls=[
'rtsp://admin:HUAN1415@192.168.1.106:554/Streaming/Channels/102',//視頻流地址
'rtsp://admin:HUAN1415@210.201.225.44:554/Streaming/Channels/202'//視頻流地址
];
var rsurl='http://210.201.225.42:8000/';//webrtc-streamer服務地址
//---------創(chuàng)建視頻播放界面--------------------------------------------------------
function plays(idx){
var videoelt = document.createElement("video");//創(chuàng)建一個播放器
var vi_tag='videoTag_'+idx;//播放器的id
videoelt.id = vi_tag;//播放器id
videoelt.muted = true;
videoelt.width=500;
videoelt.height=600;
videoelt.controls=true;//開啟進度條
document.getElementById ("play_div").appendChild(videoelt);//添加播放器到界面中
var webRtcServer = new WebRtcStreamer(vi_tag,rsurl);//創(chuàng)建webrtc流對象
//連接視頻,參數(shù)1 視頻地址,參數(shù)2 音頻地址(這里沒有),參數(shù)3 連接參數(shù)(這里采用的是tcp,120秒超時等)
webRtcServer.connect(urls[idx],undefined,"rtptransport=tcp&timeout=120&width=320&height=0");
webRtcServerList[idx]=webRtcServer;//緩存視頻流對象
}
//----------頁面退出時關(guān)閉播放流---------------------
window.onbeforeunload = function() {
for(var i=0;i<webRtcServerList.length;i++){
webRtcServerList[i].disconnect();
}
}
//---------初始化加載視頻----------------------------
window.onload= function() {
for(var i=0;i<urls.length;i++){
plays(i);
}
}
</script>
</body>
</html>
這樣就完成了整個項目實現(xiàn),這里如果視頻沒有播放成功,最有可能是穿透服務的問題,需要檢查穿透服務。
時的工作中常會遇到一些系統(tǒng)集成的需求,需要在軟件平臺集成視頻監(jiān)控系統(tǒng)。而軟件開發(fā)者往往不懂安防弱電系統(tǒng),不知道如何在自己的軟件界面中集成一些監(jiān)控的實時畫面。而監(jiān)控廠家提供的SDK比較復雜,很難在短時間完成集成的任務。最終導致軟件平臺的一些功能無法實現(xiàn),影響項目的質(zhì)量。
本文提供的方法主要基于VLC播放器的ActiveX插件,通過這個插件,在網(wǎng)頁中調(diào)用攝像機的RTSP流,實現(xiàn)圖像的實時預覽,音頻的監(jiān)聽等等功能。文章以海康的IP網(wǎng)絡(luò)攝像機為例給出具體的調(diào)用方法,供大家學習參照。
登錄VLC官網(wǎng) https://www.videolan.org/,選擇windows(32位)版本下載。
下載VLC軟件
運行安裝文件
選擇軟件安裝位置
一定記得要勾選網(wǎng)頁瀏覽器插件
完成安裝
可選用記事本(notepad)或?qū)I(yè)的編輯器,輸入如下代碼,保存為html網(wǎng)頁文件。
<html>
<body>
<title>TESTVDEIO-1-TEST</title>
<head>
<table>
<tbody>
<caption>視頻監(jiān)控演示</caption>
<tr>
<td>
<object type='application/x-vlc-plugin' pluginspage="http://www.videolan.org/" id='vlc' events='false' width="720" height="410">
<param name='mrl' value='rtsp://admin:q66668888@172.16.200.88:554/h264/ch1/main/av_stream' />
<param name='volume' value='50' />
<param name='autoplay' value='true' />
<param name='loop' value='false' />
<param name='fullscreen' value='false' />
<param name='controls' value='false' />
</td>
<td>
<object type='application/x-vlc-plugin' pluginspage="http://www.videolan.org/" id='vlc' events='false' width="720" height="410">
<param name='mrl' value='rtsp://admin:q66668888@172.16.200.89:554/h264/ch1/main/av_stream' />
<param name='volume' value='50' />
<param name='autoplay' value='true' />
<param name='loop' value='false' />
<param name='fullscreen' value='false' />
<param name='controls' value='false' />
</td>
</tr>
<tr>
<td>
<object type='application/x-vlc-plugin' pluginspage="http://www.videolan.org/" id='vlc' events='false' width="720" height="410">
<param name='mrl' value='rtsp://admin:q66668888@172.16.200.89:554/h264/ch1/main/av_stream' />
<param name='volume' value='50' />
<param name='autoplay' value='true' />
<param name='loop' value='false' />
<param name='fullscreen' value='false' />
<param name='controls' value='false' />
</td>
<td>
<object type='application/x-vlc-plugin' pluginspage="http://www.videolan.org/" id='vlc' events='false' width="720" height="410">
<param name='mrl' value='rtsp://admin:q66668888@172.16.200.88:554/h264/ch1/main/av_stream' />
<param name='volume' value='50' />
<param name='autoplay' value='true' />
<param name='loop' value='false' />
<param name='fullscreen' value='false' />
<param name='controls' value='false' />
</td>
</tr>
</tbody>
</table>
</object>
</body>
</html>
代碼編輯截圖
具體請參看海康專業(yè)文檔
先用Google Chrome瀏覽器測試,提示插件不支持。
Chrome瀏覽器提示插件不受支持
用微軟IE測試,需要安裝插件。
IE瀏覽器提示要安裝ActiveX插件
確認安裝插件
瀏覽器只顯示了第一個畫面。
IE瀏覽器顯示不完整
用編輯器測試,2種內(nèi)核都能正常顯示。
編輯器里測試效果
改用360瀏覽器,呈現(xiàn)2X2的畫面,實現(xiàn)最終的顯示效果。
360瀏覽器顯示的最終效果圖
本文參考了一些專業(yè)文章,就不一 一列出了,在這一并謝過!
由于本人水平有限,有不對的地方敬請指正。文章旨在拋磚引玉,通過討論,相互學習,共同進步。
我是WoNew弱電蝸牛,一名從業(yè)多年的弱電工程師,在頭條傳播弱電專業(yè)知識和行業(yè)信息,分享工作中的經(jīng)驗和心得。
喜歡我的文章或視頻,歡迎點贊和轉(zhuǎn)發(fā)。有疑問或建議,也歡迎留言,我會盡力解答。
?> 當瀏覽器開始尋找指定的音頻/視頻時,會發(fā)生 loadstart 事件。
HTML <video> 元素 用于在HTML或者XHTML文檔中嵌入視頻內(nèi)容
設(shè)置或返回視頻是否應該顯示控件(比如播放/暫停等)
<video src="./mt-baker_cibsgl.mp4" width="100%" controls></video>
image.png
設(shè)置或返回是否在就緒(加載完成)后自動播放視頻
<video src="http://codehtml.cn/code-demo/video/mt-baker_cibsgl.mp4" width="100%" controls autoplay></video>
設(shè)置是否去除去除下載按鈕nodownload
<video src="http://codehtml.cn/code-demo/video/mt-baker_cibsgl.mp4" width="100%" controls controlslist="nodownload"></video>
設(shè)置是否去除全屏顯示按鈕
<video src="http://codehtml.cn/code-demo/video/mt-baker_cibsgl.mp4" width="100%" controls controlslist="nodownload nofullscreen"></video>
設(shè)置視頻的封面
<video src="http://codehtml.cn/code-demo/video/mt-baker_cibsgl.mp4" width="100%" controls poster="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1526349212159&di=d6e00c2a2102cac0b50e0e622aa02618&imgtype=0&src=http%3A%2F%2Fimg5.duitang.com%2Fuploads%2Fitem%2F201411%2F06%2F20141106104720_WHEe2.jpeg"></video>
image.png
設(shè)置是否靜音(注意:移動端非靜音模式下無法自動播放)
<video src="http://codehtml.cn/code-demo/video/code.mp4" width="100%" controls muted></video>
設(shè)置循環(huán)播放
<video src="http://codehtml.cn/code-demo/video/mt-baker_cibsgl.mp4" width="100%" controls loop></video>
視頻預加載模式
<video src="http://codehtml.cn/code-demo/video/mt-baker_cibsgl.mp4" width="100%" controls preload></video>
音量控制,區(qū)間范圍在0-1
<video src="http://codehtml.cn/code-demo/video/code.mp4" width="100%" controls id="volume"></video> var time = document.getElementById("time"); time.currentTime = 60;// 秒
<video src="http://codehtml.cn/code-demo/video/code.mp4" width="100%" controls preload id="time"></video> <script type="text/javascript"> var time = document.getElementById("time"); time.currentTime = 60;// 秒 </script>
<video src="http://codehtml.cn/code-demo/video/code.mp4" width="100%" controls preload id="_src"></video> <script type="text/javascript"> var _src = document.getElementById("_src"); function changeSrc(){ _src.src = "http://codehtml.cn/code-demo/video/mt-baker_cibsgl.mp4"; } </script>
<video width="100%" controls id="_source"> <source src="http://codehtml.cn/code-demo/video/code1.mp4" type="video/mp4"> // 錯誤地址 <source src="http://codehtml.cn/code-demo/video/mt-baker_cibsgl.mp4" type="video/mp4"> </video> <script type="text/javascript"> var _source = document.getElementById("_source"); setTimeout(function () { console.log(_source.currentSrc);// 獲取當前url },2000) </script>
<video src="http://codehtml.cn/code-demo/video/code.mp4" width="100%" controls preload id="_speed"></video> <script type="text/javascript"> var _speed = document.getElementById("_speed"); _speed.playbackRate = 0.5; </script>
<video src="http://codehtml.cn/code-demo/video/code.mp4" width="100%" controls id="vs"></video>
?> 當瀏覽器開始尋找指定的音頻/視頻時,會發(fā)生 loadstart 事件。即當加載過程開始時
v.addEventListener('loadstart',function(e){ console.log("loadstart"); })
音頻/視頻的時長
v.addEventListener('durationchange',function(e){ console.log("時長", v.duration); })
當瀏覽器已經(jīng)加載完成視頻
v.addEventListener('loadedmetadata',function(e){ console.log("loadedmetadata"); })
當瀏覽器已加載視頻的當前幀時
v.addEventListener('loadeddata',function(e){ console.log("loadeddata"); })
?> 當瀏覽器正在下載視頻
v.addEventListener('progress',function(e){ console.log("progress"); })
判斷是否可以播放
v.addEventListener('canplay',function(){ console.log('canplay'); })
判斷是否可以流暢播放
v.addEventListener('canplaythrough',function(){ console.log('canplaythrough'); })
視頻播放
v.addEventListener('play',function(){ console.log('play'); })
視頻暫停
v.addEventListener('pause',function(){ console.log('pause'); })
當用戶開始移動/跳躍到音視頻中的新位置時
v.addEventListener('seeking',function(){ console.log('seeking'); })
當用戶已移動/跳躍到視頻中的新位置
v.addEventListener('seeked',function(){ console.log('seeked'); })
當視頻由于需要緩沖下一幀而停止,等待
v.addEventListener('waiting',function(){ console.log('waiting'); })
當視頻在已因緩沖而暫停或停止后已就緒時
v.addEventListener('playing',function(){ console.log('playing'); })
目前的播放位置已更改時,播放時間更新
v.addEventListener('timeupdate',function(){ console.log('timeupdate'); })
播放結(jié)束
v.addEventListener('ended',function(){ console.log('ended'); })
播放錯誤
v.addEventListener('error',function(e){ console.log('error', e); })
當音量已更改時
v.addEventListener('volumechange',function(){ console.log('volumechange'); })
當瀏覽器嘗試獲取媒體數(shù)據(jù),但數(shù)據(jù)不可用時
v.addEventListener('stalled',function(){ console.log('stalled'); })
當視頻的播放速度已更改時
v.addEventListener('ratechange',function(){ console.log('ratechange'); })
參考資料:
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。