目錄
前言
一、webrtc-streamer的API
二、webrtc-streamer的啟動(dòng)命令介紹
1.原文
2.譯文?
三、webrtc-streamer的安裝部署
1.下載地址
? ??https://github.com/mpromonet/webrtc-streamer/releases
2.windows版本部署
3.Linux版本部署
四、springboot整合webrtc-streamer
五、公網(wǎng)使用webrtc-streamer訪問相機(jī)視頻
前言
最近公司在搞流媒體,我推薦了webrtc-streamer進(jìn)行搭建,使用了一段時(shí)間后,出現(xiàn)新的需求,需要將內(nèi)網(wǎng)的攝像機(jī)進(jìn)行公網(wǎng)訪問,我查詢了幾乎所有的帖子和github的問題回復(fù),都沒有給我一個(gè)準(zhǔn)確的答案,經(jīng)過不斷嘗試和摸索,我終于成功了,我希望將我的過程記錄下來,讓更多的中國(guó)開發(fā)者可以少走彎路,我對(duì)于webrtc不是很了解,但是這并不影響我使用開源的webrtc-streamer進(jìn)行開發(fā)。
一、webrtc-streamer的API
webrtc-streamer的服務(wù)地址:192.168.1.8:8000
查詢所有api:http://192.168.1.8:8000/api/help
[
"/api/addIceCandidate",
"/api/call",
"/api/createOffer",
"/api/getAudioDeviceList",
"/api/getIceCandidate",
"/api/getIceServers",
"/api/getMediaList",
"/api/getPeerConnectionList",
"/api/getStreamList",
"/api/getVideoDeviceList",
"/api/hangup",
"/api/help",
"/api/log",
"/api/setAnswer",
"/api/version"
]
關(guān)鍵api:
/api/getPeerConnectionList
我使用它來判斷當(dāng)前的webrtc-streamer正在連接的通道
2個(gè)通道:
ICE: 交互式連接建立(Interactive Connectivity Establishment)
ice_state:交互式連接狀態(tài)(2:已連接/5:斷開連接)
pc_state:客戶端連接狀態(tài)(2:正常/3:斷開)
- 已連接:
"ice_state": 2
"pc_state": 2
- 正在斷開:
"ice_state": 5
"pc_state": 3
- 這種狀態(tài)未知:
"ice_state": 0
"pc_state": 0
- 斷開:
無(wú)任何json數(shù)據(jù)
正常連接的json如下(sdp內(nèi)容過多已刪除):
[
? {
??? "0.07123060004985127": {
????? "ice_state": 2,
????? "pc_state": 2,
????? "sdp": "",
????? "signaling_state": 0,
????? "streams": {
??????? "15661718658374446496": {
????????? "15661718658374446496_video": {
??????????? "kind": "video",
??????????? "state": 1
????????? }
??????? }
????? }
??? }
? }
? ]
二、webrtc-streamer的啟動(dòng)命令介紹
1.原文
./webrtc-streamer [-H http port] [-S[embeded stun address]] -[v[v]] [url1]...[urln]
./webrtc-streamer [-H http port] [-s[external stun address]] -[v[v]] [url1]...[urln]
./webrtc-streamer -V
-v[v[v]] : verbosity
-V : print version
-H [hostname:]port : HTTP server binding (default 0.0.0.0:8000)
-w webroot : path to get files
-c sslkeycert : path to private key and certificate for HTTPS
-N nbthreads : number of threads for HTTP server
-A passwd : password file for HTTP server access
-D authDomain : authentication domain for HTTP server access (default:mydomain.com)
-S[stun_address] : start embeded STUN server bind to address (default 0.0.0.0:3478)
-s[stun_address] : use an external STUN server (default:stun.l.google.com:19302 , -:means no STUN)
-t[username:password@]turn_address : use an external TURN relay server (default:disabled)
-T[username:password@]turn_address : start embeded TURN server (default:disabled)
-a[audio layer] : spefify audio capture layer to use (default:0)
-q[filter] : spefify publish filter (default:.*)
-o : use null codec (keep frame encoded)
-C config.json : load urls from JSON config file
-R [Udp port range min:max] : Set the webrtc udp port range (default 0:65535)
-n name -u videourl -U audiourl : register a name for a video url and an audio url
[url] : url to register in the source list
2.譯文?
./webrtc-streamer [-H http port] [-S[embeded stun address]] -[v[v]] [url1]...[urln]
./webrtc-streamer [-H http port] [-s[external stun address]] -[v[v]] [url1]...[urln]
./webrtc-streamer -V
-v[v[v]] : verbosity
-V : 打印版本
-H [hostname:]port : HTTPServer綁定 (default 0.0.0.0:8000)
-w webroot : 獲取文件的路徑
-c sslkeycert : HTTPS的私鑰和證書路徑
-N nbthreads : HTTP服務(wù)器的線程數(shù)
-A passwd : 用于HTTP服務(wù)器訪問的密碼文件
-D authDomain : HTTP服務(wù)器訪問的身份驗(yàn)證域(默認(rèn)值:mydomain.com)
-S[stun_address] : 使用嵌入的STUN服務(wù)器綁定到地址(默認(rèn)值為0.0.0.0:3478)
-s[stun_address] : 使用外部的STUN服務(wù)器綁定到地址(默認(rèn)值為0.0.0.0:3478)
-t[username:password@]turn_address : 使用外部TURN中繼服務(wù)器(默認(rèn):禁用)
-T[username:password@]turn_address : 使用嵌入式TURN中繼服務(wù)器(默認(rèn):禁用)
-a[audio layer] : 指定要使用的音頻捕獲層(默認(rèn)值:0)
-q[filter] : 指定發(fā)布篩選器(默認(rèn)值:.*)
-o : 使用空編解碼器(保持幀編碼)
-C config.json : 從JSON配置文件加載URL
-R [Udp port range min:max] : 設(shè)置webrtc-udp端口范圍(默認(rèn)值為0:65535)
-n name -u videourl -U audiourl : 注冊(cè)視頻url和音頻url的名稱
[url] : 要在源列表中注冊(cè)的url
舉例:
指定綁定ip端口:./webrtc-streamer -H 192.168.1.8:8123
注意幾個(gè)細(xì)節(jié):
1、-o 這個(gè)命令務(wù)必要加上,不加的話你會(huì)發(fā)現(xiàn)你的cpu預(yù)覽幾路馬上飆升到100%。
2、 -s/-S/-t/-T這幾個(gè)命令后面不要有空格。
3、只支持H264的視頻碼流,H265不支持。
三、webrtc-streamer的安裝部署
1.下載地址
? ??https://github.com/mpromonet/webrtc-streamer/releases
? ? ?目前最新版本0.7.2版本
? ? ?
?紅框內(nèi)分別為windows版本和Linux版本。
2.windows版本部署
下載windows版本壓縮包,解壓后如下圖
?在當(dāng)前目錄下輸入命令webrtc-streamer.exe -H 192.168.1.227:8000 -o
再次強(qiáng)調(diào) -o? 為了不轉(zhuǎn)碼,進(jìn)而降低cpu負(fù)荷。
3.Linux版本部署
? ? ? ?? 系統(tǒng)環(huán)境都正常的情況安裝步驟如下:
? ? ? ? 1.webrtc-streamer包:webrtc-streamer-v0.7.2-Linux-x86_64-Release.tar.gz
? ? ? ? 2.拷貝到root下,解壓:tar -xvf webrtc-streamer-v0.7.2-Linux-x86_64-Release.tar.gz
? ? ? ? 3.進(jìn)入webrtc-streamer-v0.7.2-Linux-x86_64-Release:cd webrtc-streamer-v0.7.2-Linux-x86_64-Release
????????
? ? ? ? 4.執(zhí)行 ./webrtc-streamer -H 192.168.1.10:8000?-o
????????
? ? ? ? ?Linux大概率會(huì)報(bào)錯(cuò)缺少環(huán)境,這個(gè)自行搜索解決。如果實(shí)在解決不了,給我留言吧。
四、springboot整合webrtc-streamer
? ? ? ? ? ? ?這部分我就快速貼代碼了。
? ???? ? ? 1、前端部分:
? ? ? ? ? ? ? ? ? ?項(xiàng)目需要引入的js:webrtcstreamer.js、adapter.min.js、jquery-1.7.1.min.js
? ? ? ? ? ? ? ? ? ?我這里配置了24個(gè)video用來測(cè)試,分別支持宇視、大華、??档腞TSP流。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="adapter.min.js"></script>
<script type="text/javascript" src="webrtcstreamer.js"></script>
<script type="text/javascript" src="jquery-1.7.1.min.js"></script>
<style>
video {
width: 300px;
height: 200px;
}
</style>
</head>
<body>
<p>視頻播放</p>
<div>
<video id="video1" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video2" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video3" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video4" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video5" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video6" muted autoplay loop controls>muted controls disablePictureInPicture</video>
</div>
<div>
<video id="video7" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video8" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video9" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video10" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video11" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video12" muted autoplay loop controls>muted controls disablePictureInPicture</video>
</div>
<div>
<video id="video13" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video14" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video15" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video16" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video17" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video18" muted autoplay loop controls>muted controls disablePictureInPicture</video>
</div>
<div>
<video id="video19" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video20" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video21" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video22" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video23" muted autoplay loop controls>muted controls disablePictureInPicture</video>
<video id="video24" muted autoplay loop controls>muted controls disablePictureInPicture</video>
</div>
<script>
var cameralist = new Array();
var camera64 = {type: "hik", ipaddr: "192.168.1.64", username: "admin", password: "hik12345", port: 554};
window.onload = function () {
// 初始化內(nèi)容
cameralist.push(camera64);
console.log(cameralist);
}
let num = 0;
function getCamera() {
let obj = cameralist[num];
console.log(obj);
num++;
if (num == 1) {
num = 0;
}
return obj;
}
let webRtcServer = null;
let videoMap = new Map();
$('video').click(function (e) {
let ID = e.target.id;//獲取當(dāng)前點(diǎn)擊事件的元素
console.log(ID);
if (videoMap.get(ID) != null) {
closeVideo(ID, videoMap.get(ID));
} else {
let camera = getCamera();
console.log(camera);
if (camera.type == "ys") {
realViewYs("192.168.1.11", ID, camera.username, camera.password, camera.ipaddr, camera.port);
} else if (camera.type == "dh") {
realViewDh("192.168.1.11", ID, camera.username, camera.password, camera.ipaddr, camera.port);
} else {
realViewHik("112.98.126.2", ID, camera.username, camera.password, camera.ipaddr, camera.port);
}
}
});
//預(yù)覽??迪鄼C(jī)
function realViewHik(serverip, elem, username, password, ipaddr, port) {
webRtcServer = new WebRtcStreamer(elem, "http://" + serverip + ":28000");
let rtspUrl = "rtsp://" + username + ":" + password + "@" + ipaddr + ":" + port + "/ch1/main/av_stream";
let option = "rtptransport=tcp";
console.log("rtsp地址:" + rtspUrl);
webRtcServer.connect(rtspUrl, null, option, null);
videoMap.set(elem, webRtcServer);
}
//預(yù)覽大華相機(jī)
function realViewDh(serverip, elem, username, password, ipaddr, port) {
webRtcServer = new WebRtcStreamer(elem, "http://" + serverip + ":8000");
let rtspUrl = "rtsp://" + username + ":" + password + "@" + ipaddr + ":" + port + "/cam/realmonitor?channel=1&subtype=0";
let option = "rtptransport=tcp";
console.log("rtsp地址:" + rtspUrl);
webRtcServer.connect(rtspUrl, null, option, null);
videoMap.set(elem, webRtcServer);
}
//預(yù)覽宇視相機(jī)
function realViewYs(serverip, elem, username, password, ipaddr, port) {
webRtcServer = new WebRtcStreamer(elem, "http://" + serverip + ":8000");
let rtspUrl = "rtsp://" + username + ":" + password + "@" + ipaddr + ":" + port + "/media/video1/multicast";
console.log("rtsp地址:" + rtspUrl);
let option = "rtptransport=tcp";
webRtcServer.connect(rtspUrl, null, option, null);
videoMap.set(elem, webRtcServer);
}
function closeVideo(id, webrtc) {
webrtc.disconnect();
videoMap.delete(id);
}
//頁(yè)面退出時(shí)銷毀
// window.onbeforeunload = function () {
// alert("頁(yè)面關(guān)閉");
// webRtcServer.disconnect();
// }
//頁(yè)面離開或者瀏覽器關(guān)閉的時(shí)候觸發(fā)
window.onbeforeunload = function (event) {
$.ajax({
// url: "../getIp",
url: "http://127.0.0.1:12344/ard/videocall",
type: "post",
contentType: "application/json",
dataType: "json",
data: JSON.stringify({"cmd": "close", "url": "https://anruida.app.zihai.shop/?id=zns&pass=ard"}),
success: function (data) {
}
});
webRtcServer.disconnect();
};
</script>
? ? ? ? 2、后端部分
? ? ? ? 后端部分簡(jiǎn)單多了,初學(xué)者應(yīng)該都會(huì)吧,直接配置個(gè)controller找這個(gè)html就行了。
@GetMapping("/")
String index() {
return "view";
}
啟動(dòng)項(xiàng)目打開127.0.0.1:8080
至此,局域網(wǎng)內(nèi)訪問相機(jī)視頻就完成了。
五、公網(wǎng)使用webrtc-streamer訪問相機(jī)視頻
通過上面的步驟局域網(wǎng)內(nèi)訪問相機(jī)視頻流已經(jīng)可以實(shí)現(xiàn)了,但是如果你想把項(xiàng)目部署到公網(wǎng)中進(jìn)行訪問就不行了。
公網(wǎng)部署步驟:
1、配置webrtc-streamer所在服務(wù)器的內(nèi)網(wǎng)穿透地址,例如內(nèi)網(wǎng)192.168.1.8:8000 映射到公網(wǎng)為110.154.21.14:18000
2、部署一個(gè)本地coturn服務(wù)器,配置conturn服務(wù)器配置文件,同時(shí)將conturn服務(wù)器的3478的tcp和udp端口進(jìn)行公網(wǎng)映射。
3、前端js頁(yè)面使用公網(wǎng)地址也就是110.154.21.14:18000配置webrtc-streamer
4、啟動(dòng)命令增加turn和stun服務(wù)器:webrtc-streamer.exe -o -H 192.168.1.8:8000 -S110.154.21.14:3478 -Tadmin:123456@110.154.21.14:3478
正式開始:
第一步,使用路由器將webrtc內(nèi)網(wǎng)映射到公網(wǎng),這個(gè)我相信你玩這個(gè)肯定會(huì),不同的交換機(jī)配置不同。
第二步,Linux下WebRTC搭建私有turn/stun服務(wù),目前coturn只支持linux。
?? ?????????coturn是一個(gè)免費(fèi)的開源的TURN/STUN服務(wù)器。coturn 服務(wù)器完整的實(shí)現(xiàn)了STUN/TURN/ICE協(xié)議,支持P2P穿透防火墻。
?? ?????????STUN 服務(wù)器用于獲取設(shè)備的外部網(wǎng)絡(luò)地址。
?? ?????????TURN 服務(wù)器是在點(diǎn)對(duì)點(diǎn)失敗后用于通信中繼。
?? ?????????WebRTC 建立連接的步驟大概是這樣的:
?? ?????????客戶端(瀏覽器)直接嘗試直連;
?? ?????????如果如果直連則通過 STUN 服務(wù)器進(jìn)行穿透;
?? ?????????如果無(wú)法穿透則通過 TURN 服務(wù)器進(jìn)行中轉(zhuǎn)。
1. 安裝前準(zhǔn)備
http://libevent.org/ 下載 libevent-2.1.12-stable.tar.gz
wget https://github.com/coturn/coturn/archive/4.5.1.1.tar.gz 下載 conturn-4.5.1.1.tar.gz (穩(wěn)定版本)
(如果undefined reference to `SSL_CTX_up_ref'的錯(cuò)誤換用穩(wěn)定版本就好了。)
2. 安裝gcc
yum install gcc-c++
3. 安裝openssl-devel
yum -y install openssl-devel
4. 安裝libevent2
在http://libevent.org/下載libevent-2.1.8-stable.tar.gz
tar -zxvf libevent-2.1.8-stable.tar.gz
cd libevent-2.1.8-stable
./configure --prefix=/usr --libdir=/usr/lib64 (如果報(bào)錯(cuò)試試這個(gè)方式:./configure --prefix=/usr/local/coturn)
make
make install
成功沒有出現(xiàn)報(bào)錯(cuò)信息
5. 安裝conturn-4.5.1.1
tar -zxvf 4.5.1.1.tar.gz
cd coturn-4.5.1.1
./configure
make
make install
可以通過which turnserver驗(yàn)證。如果出現(xiàn)路徑即為成功
6. 配置文件和簽名,然后進(jìn)入文件夾:
cd /usr/local/etc/ 會(huì)看到一個(gè)叫做 turnserver.conf.default的配置文件。將它備份:
cp turnserver.conf.default turnserver.conf
7. 在當(dāng)前文件夾生成簽名(自行輸入):
openssl req -x509 -newkey rsa:2048 -keyout /usr/local/etc/turn_server_pkey.pem -out /usr/local/etc/turn_server_cert.pem -days 99999 -nodes
8. 修改配置文件
Vim turnserver.conf 參考如下
relay-device=eth0
listening-ip=#內(nèi)網(wǎng)IP
listening-port=3478
tls-listening-port=5349
relay-ip=#內(nèi)網(wǎng)IP
external-ip=#公網(wǎng)IP
relay-threads=50
lt-cred-mech
min-port=49152
max-port=65535
cert=/usr/local/etc/turn_server_cert.pem
pkey=/usr/local/etc/turn_server_pkey.pem
pidfile=”/var/run/turnserver.pid”
user=admin:123456
cli-password=123456
將配置文件更新如上。
請(qǐng)一定要設(shè)置cli-password這一項(xiàng),不設(shè)置會(huì)報(bào)錯(cuò)。
注意檢查cert和pkey的路徑和名稱。檢查內(nèi)網(wǎng)ip和公網(wǎng)ip是否填寫準(zhǔn)確。
注意文本格式準(zhǔn)確。
9. 啟動(dòng)turnserver
turnserver -o -a -f -user=admin:123456 -c /usr/local/etc/turnserver.conf -r xiamen
-o 是讓程序在后臺(tái)啟動(dòng)
-r 后面填個(gè)地區(qū)就行。
-user 一定要和配置文件中一樣。
ps -ef|grep turnserver 指令查看是否啟動(dòng)服務(wù),如果有
10. 驗(yàn)證
Trickle ICE:https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
1、stun:+公網(wǎng)IP+端口,測(cè)試出現(xiàn)公網(wǎng)IP則代表部署成功
2、turn:+公網(wǎng)IP+端口,測(cè)試出現(xiàn)公網(wǎng)IP則代表部署成功
? ? 可能出現(xiàn)的問題:
1、libevent configure: error: OpenSSL could not be found. You should add the directory解決辦法
????????直接在線安裝:yum -y install openssl-devel
2、yum 安裝軟件報(bào)錯(cuò) : There are no enabled repos.
????????可能是相關(guān)yum源被刪除了:
????????wget -O /etc/yum.repos.d/CentOS-Base.repo?http://mirrors.aliyun.com/repo/Centos-7.repo
????????yum clean all && yum makecache
?只需要做webrtc-streamer服務(wù)器的tcp:8000端口、coturn服務(wù)器的tcp/udp:3478端口的映射即可。
相機(jī)的地址不需要映射。文章來源:http://www.zghlxwxcb.cn/news/detail-421723.html
至此公網(wǎng)訪問視頻流完成!有問題請(qǐng)留言。文章來源地址http://www.zghlxwxcb.cn/news/detail-421723.html
到了這里,關(guān)于史上最詳細(xì)的webrtc-streamer訪問攝像機(jī)視頻流教程的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!