項目中需要在瀏覽器中播放Camera的監(jiān)控視頻窃页,之前對視頻監(jiān)控不太了解脉让,以為只要是Ip camera出來的視頻流通過H5的Video控件就能直接播放,實際測試時發(fā)現(xiàn)不是那么容易奈附,網(wǎng)上也有很多種方法刁赦,但大多都是介紹性的內(nèi)容娶聘,而且很多代碼也會因為各種原因無法運行,比如框架庫的更新甚脉,代碼不全等導(dǎo)致很多編譯和運行錯誤丸升,因此在深入的分析和驗證了每個方法的可行性的基礎(chǔ)上,總結(jié)出這篇文章牺氨,希望對有類似需求的人有所幫助狡耻。在實現(xiàn)這個需求前,首先需要腦補一下與視頻相關(guān)的知識猴凹。
背景知識
主流的視頻傳輸協(xié)議
Http Live Streaming(HLS)
是蘋果公司實現(xiàn)的基于Http的流媒體傳輸協(xié)議夷狰,可實現(xiàn)流媒體的直播以及點播,HLS傳輸協(xié)議與其他傳輸協(xié)議的不同在于客戶端獲取到的并不是一個完整的數(shù)據(jù)流郊霎,而是將數(shù)據(jù)流存儲為連續(xù)的沼头、短時長的媒體文件,即MPEG-TS格式的文件书劝,客戶端這是通過不斷的下載這些小文件进倍,然后進(jìn)行按順序的播放從服務(wù)器那邊獲取到的文件,就實現(xiàn)了視頻的直播效果 购对。而且數(shù)據(jù)是通過Http來傳輸?shù)幕ィ筒挥脫?dān)心防火墻或者代理的問題,唯一的缺點就是延遲會比其他傳輸協(xié)議大一些洞斯。
Real Time Messaging Protocol(RTMP)
主要采用TCP傳輸毡庆,如果互聯(lián)網(wǎng)的環(huán)境較差,采用RTMP可以保證視頻的傳輸質(zhì)量烙如,但是延遲還是相對來說有點高么抗。使用RTMP有個特點,就是使用 Flash Player 作為播放器客戶端亚铁,而Flash Player 現(xiàn)在已經(jīng)安裝在了全世界將近99%的PC上蝇刀,因此一般情況下收看RTMP流媒體系統(tǒng)的視音頻是不需要安裝插件的。實時視頻采用RTMP作為流媒體傳輸協(xié)議徘溢,F(xiàn)LV作為封裝格式吞琐,直播服務(wù)器可以選擇Nginx+rtmp實現(xiàn),客戶端采用librtmp進(jìn)行推流然爆,F(xiàn)Fmpeg負(fù)責(zé)編解碼站粟,查看視頻采用VLC即可。
Real Time Serial Protocol(RTSP)
由Real network 和 Netscape共同提出的如何有效地在IP網(wǎng)絡(luò)上傳輸流媒體數(shù)據(jù)的應(yīng)用層協(xié)議曾雕,相對于其余兩種協(xié)議來說實時性是比較高的奴烙,并且易于擴(kuò)展,新的一些方法和參數(shù)都是比較容易加入RTSP, 獨立于傳輸 RTSP傳輸通道切诀,可使用不可靠數(shù)據(jù)包協(xié)議(UDP)或可靠數(shù)據(jù)包協(xié)議(RDP)揩环。RTSP還是一種雙向?qū)崟r數(shù)據(jù)傳輸協(xié)議,它允許客戶端向服務(wù)器端發(fā)送請求幅虑,如回放丰滑、快進(jìn)、倒退等操作倒庵。
常見IP Camera傳輸協(xié)議
RTSP/H.264: 這類型的攝像頭通常用于安防場合褒墨。它們使用RTSP協(xié)議來建立一個RTP媒體會話。換句話說哄芜,媒體傳輸時通過RTSP發(fā)生的信令基于plain(簡單的)RTP貌亭。不同的攝像頭廠商可能支持不同的RTP規(guī)格,但是就我看到的大部分?jǐn)z像頭而言认臊,AVP是唯一可用的選項。在這些攝像頭中锄奢,同樣典型的失晴,H.264是編解碼器唯一的選項。
HTTP/MJPEG: 這類型攝像頭使用HTTP流來signaling拘央,傳輸涂屁,將一系列的JPEG圖像編碼為視頻。這些攝像頭的硬件相對更簡單灰伟,只需要很少的資源來操作拆又。這就是為什么他們被更多用在電池功耗或者在意負(fù)載的場合(如機(jī)器人,無人機(jī)等)栏账。不足的是帖族,它們的視頻質(zhì)量顯著下降。
旱簿簦康竖般,大華,霍尼等安防領(lǐng)域的攝像頭目前都支持是RTSP傳輸協(xié)議茶鹃。
HTML5 Video支持的格式
有了上面的知識后涣雕,就發(fā)現(xiàn)直接在瀏覽器中播放當(dāng)前主流IP Camera的視頻是不太可能,因為Ip camera出來的視頻流不被H5支持闭翩。在網(wǎng)上收集了很多的方案挣郭,認(rèn)為以下幾個方案可行性比較高,所以就列舉出以下的方案分別驗證疗韵。
常見方案匯總
商業(yè)流媒體代理服務(wù)
Streamedian
H5Stream
瀏覽器插件
VLC插件
VXG插件
開源的WebRTC服務(wù)
Kurnto
WebRTCStreamer
基于Ffmpeg搭建流媒體服務(wù)
Transcode from RTSP to HLS
商業(yè)流媒體服務(wù)
零視技術(shù)(H5Stream)
現(xiàn)在有很多這種流媒體云服務(wù)兑障,包括阿里云也提供了視頻流解決方案,我收集了兩個出現(xiàn)頻率比較高的流媒體云服務(wù),一個是國內(nèi)一家公司旺垒,叫零視技術(shù)的物聯(lián)網(wǎng)視頻解決方案彩库。它支持RTSP/RTMP拉流/RTMP推流/GB28181 攝像機(jī)NVR集成,支持HLS/RTSP/RTMP/WS/RTC 服務(wù)先蒋,并且在不轉(zhuǎn)碼的情況下支持H.264骇钦。參考產(chǎn)品官網(wǎng):
https://www.linkingvision.cn/product/h5stream
Streamedian
它提供了對RTSP流進(jìn)行轉(zhuǎn)換為MP4文件,并提供了一個Javascript庫來實時播放視頻流竞漾。功能應(yīng)該沒有H5Stream強大眯搭,支持的格式也比較少。下面是它的架構(gòu)圖和官網(wǎng):
https://streamedian.com/
小結(jié)
如果要求支持所有的視頻流和協(xié)議格式比較多业岁,建議使用H5Stream鳞仙,搭建云流媒體服務(wù)。
如果是僅支持有限格式的視頻流和協(xié)議笔时,建議使用Streamedian棍好,它提供了免費的license,只支持部署一個ip或域名允耿,兩個瀏覽器同時瀏覽借笙。
瀏覽器插件
有兩種瀏覽器插件,VLC和VXG兩個插件可以直接播放RTSP和RTMP的視頻流较锡,我們也可以使用這兩個工具來測試RTSP和RTMP的視頻流业稼。
VLC視頻播放軟件下載:
https://www.videolan.org/vlc/index.zh_TW.html
VXG視頻播放軟件下載:
https://www.chromefor.com/vxg-media-player_v1-8-44/
VLC插件
安裝 VLC 客戶端,直接在瀏覽器中調(diào)用 VLC 的視頻控件蚂蕴,通過監(jiān)控視頻 RTSP 串流進(jìn)行預(yù)覽低散。該方式調(diào)用時比較方便,在360安全瀏覽器的極速模式下是可運行的骡楼,但是在谷歌和Firefox等瀏覽器依舊因為插件的原因不能預(yù)覽熔号。具體參考這篇文章可以驗證:
https://videoconverter.wondershare.com/vlc/vlc-web-plugins-for-top-browsers.html#part1
VXG插件
VXG插件的播放方式,首先在chrome里搜索VXG君编,安裝Chrome VXG插件跨嘉,然后下載Github上的代碼
https://github.com/aitexiaoy/rtsp_chrome_demo
就可以通過VXG插件來播放RTSP視頻流。
小結(jié)
通過插件方式來播放視頻流吃嘿,對用戶不夠友好祠乃,需要安裝插件,特別是在國內(nèi)還無法在線安裝Chrome插件兑燥,只能離線安裝亮瓷,比較麻煩,而且隨時有被Chrome disable的風(fēng)險降瞳。
VLC插件只能適用于360瀏覽器嘱支,不適用于Chrome和Firefox瀏覽器
VXG插件會在視頻中出現(xiàn)VXG三個字樣的水印蚓胸,影響使用,如果需要去除水印除师,需要付費
VXG只支持HTTP
優(yōu)點就是開發(fā)比較簡單沛膳,不需要搭建流媒體服務(wù),適合于快速Demo視頻流這種場景
開源的WebRTC服務(wù)
WebRTC汛聚,即Web Real-Time Communication, web實時通信技術(shù)锹安。簡單地說就是在web瀏覽器里面引入實時通信,包括音視頻通話等倚舀。WebRTC實現(xiàn)了基于網(wǎng)頁的語音對話或視頻通話叹哭,目的是無插件實現(xiàn)web端的實時通信的能力。
WebRTC提供了視頻會議的核心技術(shù)痕貌,包括音視頻的采集风罩、編解碼、網(wǎng)絡(luò)傳輸舵稠、展示等功能超升,并且還支持跨平臺,包括linux哺徊、windows廓俭、mac、android等唉工。雖然WebRTC主要用于在Chrome中視頻聊天,但我們也可以利用它來進(jìn)行視頻轉(zhuǎn)換汹忠,將視頻流轉(zhuǎn)成WebRTC協(xié)議淋硝,然后可以在支持WebRTC協(xié)議的瀏覽器上直接播放。我驗證了兩個WebRTC技術(shù)宽菜,webrtc-streamer和kurento谣膳。
webrtc-streamer
WebRTC-streamer是一個將RTSP流轉(zhuǎn)成WebRTC的開源demo,它提供了restful service來視頻轉(zhuǎn)換請求铅乡,并使用Ajax在前端發(fā)起視頻轉(zhuǎn)換請求和播放視頻继谚。使用Docker進(jìn)行部署。官網(wǎng):
https://github.com/mpromonet/webrtc-streamer
提供的api如下:
/api/call : send offer and get answer
/api/hangup : close a call
/api/addIceCandidate : add a candidate/api/getIceCandidate : get the list of candidates
Kurento
Kurento 是一個開源的WebRTC媒體服務(wù)阵幸,它提供了一系列的Client API花履,使得在移動和瀏覽器上開發(fā)視頻應(yīng)用變得簡單。它可以進(jìn)行分組視頻通訊挚赊,視頻轉(zhuǎn)碼诡壁,錄像,廣播等功能荠割,是一個功能比較強大的視頻流媒體服務(wù)妹卿。但是它提供的Demo程序因為版本不兼容的問題旺矾,沒有測試成功。git網(wǎng)址:
https://github.com/Kurento
我測試的方法是使用它提供的Kurento javascript util庫來實現(xiàn)夺克,實現(xiàn)方式參考開源demo:
https://github.com/lulop-k/kurento-rtsp2webrtc
測試沒有任何錯誤拋出箕宙,但無法顯示視頻頁面,可能是因為服務(wù)器版本和此demo程序版本不匹配導(dǎo)致铺纽,demo的代碼比較久遠(yuǎn)柬帕。但kurento自身庫中提供的demo樣例有明顯的語法錯誤,因為demo代碼還沒來得及更新室囊,使用的js庫在代碼中不能找到雕崩,期望以后更新再進(jìn)行測試。
小結(jié)
對比了這兩種開源的WebRTC技術(shù)融撞,Kurento開源社區(qū)更活躍盼铁,WebRTC-Streamer相比之下功能比較簡單,但WebRTC更加適合的場景是多人視頻聊天尝偎,技術(shù)也相當(dāng)復(fù)雜饶火,對于IP Camera的實時播放有點大材小用的味道。
基于Ffmpeg視頻流媒體服務(wù)
這種開發(fā)方式是當(dāng)前大部分網(wǎng)站推薦的視頻實時播放方法致扯,實現(xiàn)方式的步驟可以參考以下博客肤寝,很多文章中都給出的是此方法,但沒有一個完整的實例
https://blog.csdn.net/weixin_41774153/article/details/98082280
自己部署比較麻煩抖僵,現(xiàn)在docker技術(shù)已經(jīng)可以完全簡化部署鲤看,因此推薦使用docker部署,比較簡單耍群。我使用下面的docker部署方式义桂,并針對ffmpeg的新版本做了腳本更新,并且在鏡像中增加了一個測試實例蹈垢。更新的腳步部分下面會詳細(xì)給出腳本代碼慷吊,其他參考git上的腳本,下面是我部署后的架構(gòu)圖曹抬。
https://github.com/gihad/streamer
1)Dockerfile
在docker file里更新了ffmpeg版本溉瓶,創(chuàng)建了一個網(wǎng)站目錄,來部署html網(wǎng)站谤民。
FROM?alpine:3.12
#?Install?nginx?and?ffmpeg
RUN?apk?add?--update?nginx?ffmpeg?&&?rm?-rf?/var/cache/apk/*?&&?mkdir?/tmp/stream?&&?mkdir?/tmp/examples
COPY?nginx/nginx.conf?/etc/nginx/nginx.conf
COPY?examples?/tmp/examples
COPY?./startup.sh?/
COPY?./create_ffmpeg_cmd.sh?/
RUN?["chmod",?"+x",?"/startup.sh"]
RUN?["chmod",?"+x",?"/create_ffmpeg_cmd.sh"]
CMD?["/startup.sh"]
2)ffmpeg命令
為了防止生成的ts文件重名堰酿,因此使用時間戳的方式來命名ts文件,保證部署多個ip camera攝像頭下不會出現(xiàn)重名赖临。此外胞锰,新增了一個參數(shù)在忽略網(wǎng)絡(luò)連接引起的錯誤。-hls_start_number_source datetime -ignore_io_errors 1
#!/bin/sh
OUTPUT_PATH=/tmp/stream/
DEFAULT_AUDIO="copy"
DEFAULT_VIDEO="copy"
LACKING_AUDIO=""
IS_RTSP=""
INPUT=$1
OUTPUT=$2
#?Check?if?codecs?are?already?in?the?format?supported?by?Chromecast?devices?(aac?for?audio?and?h264?for?video)
AUDIO_RESULT="$(ffprobe?-v?error?-select_streams?a:0?-show_entries?stream=codec_name???-of?default=noprint_wrappers=1:nokey=1?$INPUT)"
VIDEO_RESULT="$(ffprobe?-v?error?-select_streams?v:0?-show_entries?stream=codec_name???-of?default=noprint_wrappers=1:nokey=1?$INPUT)"
if?[?"$AUDIO_RESULT"?!=?"aac"?];?then
??DEFAULT_AUDIO=aac
fi
#?Check?if?it's?empty?to?add?silent?dummy?stream
if?[?-z?"$AUDIO_RESULT"];?then
??LACKING_AUDIO="-f?lavfi?-i?aevalsrc=0"
fi
if?[?"$VIDEO_RESULT"?!=?"h264"?];?then
??DEFAULT_VIDEO=h264
fi
if?[?"$INPUT"?==?rtsp://*?];?then
??IS_RTSP="-rtsp_transport?tcp"
fi
FFMPEG_CMD="ffmpeg?-rtsp_transport?tcp?-i?${INPUT}?${LACKING_AUDIO}?-acodec?${DEFAULT_AUDIO}?-vcodec?${DEFAULT_VIDEO}?-hls_start_number_source?datetime?-ignore_io_errors?1?-hls_list_size?2?-hls_init_time?1?-hls_time?1?-hls_flags?delete_segments?${OUTPUT_PATH}${OUTPUT}.m3u8"
echo?"${FFMPEG_CMD}"
3)Nginx的配置
在原有的Nginx配置下兢榨,新增了一個測試網(wǎng)站來測試視頻的播放嗅榕。網(wǎng)站代碼放在/tmp/examples目錄下顺饮。
user?nginx;
worker_processes?auto;
error_log?/var/log/nginx/error.log?warn;
pid?/var/run/nginx.pid;
events?{
????worker_connections?1024;
}
http?{
????sendfile?off;
????tcp_nopush?on;
????directio?512;
????default_type?application/octet-stream;
????access_log?/var/log/nginx/access.log;
????server?{
????????listen?80;
????????location?/?{
????????????#?Disable?cache
????????????add_header?'Cache-Control'?'no-cache';
????????????#?CORS?setup
????????????add_header?'Access-Control-Allow-Origin'?'*'?always;
????????????add_header?'Access-Control-Expose-Headers'?'Content-Length';
????????????#?allow?CORS?preflight?requests
????????????if?($request_method?=?'OPTIONS')?{
????????????????add_header?'Access-Control-Allow-Origin'?'*';
????????????????add_header?'Access-Control-Max-Age'?1728000;
????????????????add_header?'Content-Type'?'text/plain?charset=UTF-8';
????????????????add_header?'Content-Length'?0;
????????????????return?204;
????????????}
????????????types?{
????????????????application/dash+xml?mpd;
????????????????application/vnd.apple.mpegurl?m3u8;
????????????????video/mp2t?ts;
????????????}
????????????root?/tmp/stream;
????????}
????????location?/examples?{
????????????root?/tmp/;
????????}
????????location?~?\.css?{
????????????default_type?text/css;
????????????root?/tmp/;
????????}
????????location?~?\.js?{
????????????default_type?application/x-javascript;
????????????root?/tmp/;
????????}
????}
}
4)部署測試程序
在Chrome下播放HLS協(xié)議的視頻需要使用開源庫video js和h5 video控件,video.js是一個通用的在網(wǎng)頁上嵌入視頻播放器的javascript庫凌那,Video.js會自動檢測瀏覽器對html5的支持情況兼雄,如果不支持html5則自動使用Flash播放器。
https://videojs.com/getting-started/
這是官網(wǎng)帽蝶,使用Safari不需要使用videojs赦肋,只需要使用h5 video控件。
5)NPM安裝video js
npm?install?--save-dev?video.js
6)測試網(wǎng)頁
<!DOCTYPE?html>
<html?lang="en">
<head>
????<title>Video.js?|?HTML5?Video?Player</title>
????<link?href="../node_modules/video.js/dist/video-js.min.css"?rel="stylesheet">
????<script?src="../node_modules/video.js/dist/video.min.js"></script>
</head>
<body>
????<video?muted="muted"?id="example_video_1"?class="video-js"?controls?width="640"?height="264"
????????data-setup='{?"autoplay":?true,?"preload":?"auto","loadingSpinner":?false?}'>
????????<source?src="http://your?ip?address:8089/hello1.m3u8"?type="application/x-mpegURL">
????</video>
</body>
</html>
注意chrome中不支持視頻自動播放励稳,如果需要自動播放佃乘,需要設(shè)置muted,因此在video中設(shè)置muted為"muted"驹尼。
7)Build docker鏡像
docker?build?.?-t?gihad/streamer
8)運行docker容器
docker?run?-e?PARAMETERS='rtsp://username:password@192.168.1.55:554/cam/realmonitor?channel=1&subtype=0?hello'?-v?/tmp/stream:/tmp/stream?-v?/home/deploy/streamer-master/examples:/tmp/examples?-v?/home/deploy/streamer-master/nginx/nginx.conf:/etc/nginx/nginx.conf?-p?8089:80?gihad/streamer
為了便于調(diào)試趣避,我把測試網(wǎng)頁源碼和nginx配置文件和生成的m3u8路徑都外掛到宿主機(jī)的/home/deploy/streamer-master文件夾下,192.168.1.55是IP camera的地址新翎,username和password是IP Camera的用戶名和密碼程帕,tmp/stream是轉(zhuǎn)換的m3u8和ts文件的路徑。
9)運行測試網(wǎng)站
使用Chrome打開http://your server ip:8089/examples/index.html地啰,即可以實時播放IP Camera視頻愁拭。
寫在最后
隨著視頻直播技術(shù)的迅猛發(fā)展,在瀏覽器中無插件播放視頻未來肯定會越來越簡單亏吝,Webrtc技術(shù)肯定會成為未來的發(fā)展趨勢岭埠。但現(xiàn)階段成本最低的播放方式應(yīng)該是基于瀏覽器插件的播放方式,不需要搭建流媒體服務(wù)蔚鸥。而縱觀整個視頻相關(guān)技術(shù)枫攀,視頻播放只是其中一個很小的部分,視頻實時通訊(RTC)從功能流程上來說株茶,包含采集、編碼图焰、前后處理启盛、傳輸、解碼技羔、緩沖僵闯、渲染等很多環(huán)節(jié)。每一個細(xì)分環(huán)節(jié)藤滥,還有更細(xì)分的技術(shù)模塊鳖粟。