目录
https://github.com/mpromonet/webrtc-streamer/releases
前言
最近公司在搞流媒体,我推荐了webrtc-streamer进行搭建,使用了一段时间后,出现新的需求,需要将内网的摄像机进行公网访问,我查询了几乎所有的帖子和github的问题回复,都没有给我一个准确的答案,经过不断尝试和摸索,我终于成功了,我希望将我的过程记录下来,让更多的中国开发者可以少走弯路,我对于webrtc不是很了解,但是这并不影响我使用开源的webrtc-streamer进行开发。
一、webrtc-streamer的api
webrtc-streamer的服务地址: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"
]
关键api:
/api/getpeerconnectionlist
我使用它来判断当前的webrtc-streamer正在连接的通道
2个通道:
ice: 交互式连接建立(interactive connectivity establishment)
ice_state:交互式连接状态(2:已连接/5:断开连接)
pc_state:客户端连接状态(2:正常/3:断开)
- 已连接:
"ice_state": 2
"pc_state": 2
- 正在断开:
"ice_state": 5
"pc_state": 3
- 这种状态未知:
"ice_state": 0
"pc_state": 0
- 断开:
无任何json数据
正常连接的json如下(sdp内容过多已删除):
[
{
"0.07123060004985127": {
"ice_state": 2,
"pc_state": 2,
"sdp": "",
"signaling_state": 0,
"streams": {
"15661718658374446496": {
"15661718658374446496_video": {
"kind": "video",
"state": 1
}
}
}
}
}
]
二、webrtc-streamer的启动命令介绍
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服务器的线程数
-a passwd : 用于http服务器访问的密码文件
-d authdomain : http服务器访问的身份验证域(默认值:mydomain.com)
-s[stun_address] : 使用嵌入的stun服务器绑定到地址(默认值为0.0.0.0:3478)
-s[stun_address] : 使用外部的stun服务器绑定到地址(默认值为0.0.0.0:3478)
-t[username:password@]turn_address : 使用外部turn中继服务器(默认:禁用)
-t[username:password@]turn_address : 使用嵌入式turn中继服务器(默认:禁用)
-a[audio layer] : 指定要使用的音频捕获层(默认值:0)
-q[filter] : 指定发布筛选器(默认值:.*)
-o : 使用空编解码器(保持帧编码)
-c config.json : 从json配置文件加载url
-r [udp port range min:max] : 设置webrtc-udp端口范围(默认值为0:65535)
-n name -u videourl -u audiourl : 注册视频url和音频url的名称
[url] : 要在源列表中注册的url
举例:
指定绑定ip端口:./webrtc-streamer -h 192.168.1.8:8123
注意几个细节:
1、-o 这个命令务必要加上,不加的话你会发现你的cpu预览几路马上飙升到100%。
2、 -s/-s/-t/-t这几个命令后面不要有空格。
3、只支持h264的视频码流,h265不支持。
三、webrtc-streamer的安装部署
1.下载地址
https://github.com/mpromonet/webrtc-streamer/releases
目前最新版本0.7.2版本
红框内分别为windows版本和linux版本。
2.windows版本部署
下载windows版本压缩包,解压后如下图
在当前目录下输入命令webrtc-streamer.exe -h 192.168.1.227:8000 -o
再次强调 -o 为了不转码,进而降低cpu负荷。
3.linux版本部署
系统环境都正常的情况安装步骤如下:
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.进入webrtc-streamer-v0.7.2-linux-x86_64-release:cd webrtc-streamer-v0.7.2-linux-x86_64-release
4.执行 ./webrtc-streamer -h 192.168.1.10:8000 -o
linux大概率会报错缺少环境,这个自行搜索解决。如果实在解决不了,给我留言吧。
四、springboot整合webrtc-streamer
这部分我就快速贴代码了。
1、前端部分:
项目需要引入的js:webrtcstreamer.js、adapter.min.js、jquery-1.7.1.min.js
我这里配置了24个video用来测试,分别支持宇视、大华、海康的rtsp流。
<!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 () {
// 初始化内容
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;//获取当前点击事件的元素
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);
}
}
});
//预览海康相机
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);
}
//预览大华相机
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);
}
//预览宇视相机
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);
}
//页面退出时销毁
// window.onbeforeunload = function () {
// alert("页面关闭");
// webrtcserver.disconnect();
// }
//页面离开或者浏览器关闭的时候触发
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、后端部分
后端部分简单多了,初学者应该都会吧,直接配置个controller找这个html就行了。
@getmapping("/")
string index() {
return "view";
}
启动项目打开127.0.0.1:8080
至此,局域网内访问相机视频就完成了。
五、公网使用webrtc-streamer访问相机视频
通过上面的步骤局域网内访问相机视频流已经可以实现了,但是如果你想把项目部署到公网中进行访问就不行了。
公网部署步骤:
1、配置webrtc-streamer所在服务器的内网穿透地址,例如内网192.168.1.8:8000 映射到公网为110.154.21.14:18000
2、部署一个本地coturn服务器,配置conturn服务器配置文件,同时将conturn服务器的3478的tcp和udp端口进行公网映射。
3、前端js页面使用公网地址也就是110.154.21.14:18000配置webrtc-streamer
4、启动命令增加turn和stun服务器:webrtc-streamer.exe -o -h 192.168.1.8:8000 -s110.154.21.14:3478 -tadmin:123456@110.154.21.14:3478
正式开始:
第一步,使用路由器将webrtc内网映射到公网,这个我相信你玩这个肯定会,不同的交换机配置不同。
第二步,linux下webrtc搭建私有turn/stun服务,目前coturn只支持linux。
coturn是一个免费的开源的turn/stun服务器。coturn 服务器完整的实现了stun/turn/ice协议,支持p2p穿透防火墙。
stun 服务器用于获取设备的外部网络地址。
turn 服务器是在点对点失败后用于通信中继。
webrtc 建立连接的步骤大概是这样的:
客户端(浏览器)直接尝试直连;
如果如果直连则通过 stun 服务器进行穿透;
如果无法穿透则通过 turn 服务器进行中转。
1. 安装前准备
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 (稳定版本)
(如果undefined reference to `ssl_ctx_up_ref'的错误换用稳定版本就好了。)
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 (如果报错试试这个方式:./configure --prefix=/usr/local/coturn)
make
make install
成功没有出现报错信息
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验证。如果出现路径即为成功
6. 配置文件和签名,然后进入文件夹:
cd /usr/local/etc/ 会看到一个叫做 turnserver.conf.default的配置文件。将它备份:
cp turnserver.conf.default turnserver.conf
7. 在当前文件夹生成签名(自行输入):
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=#内网ip
listening-port=3478
tls-listening-port=5349
relay-ip=#内网ip
external-ip=#公网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
将配置文件更新如上。
请一定要设置cli-password这一项,不设置会报错。
注意检查cert和pkey的路径和名称。检查内网ip和公网ip是否填写准确。
注意文本格式准确。
9. 启动turnserver
turnserver -o -a -f -user=admin:123456 -c /usr/local/etc/turnserver.conf -r xiamen
-o 是让程序在后台启动
-r 后面填个地区就行。
-user 一定要和配置文件中一样。
ps -ef|grep turnserver 指令查看是否启动服务,如果有
10. 验证
trickle ice:https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
1、stun:+公网ip+端口,测试出现公网ip则代表部署成功
2、turn:+公网ip+端口,测试出现公网ip则代表部署成功
可能出现的问题:
只需要做webrtc-streamer服务器的tcp:8000端口、coturn服务器的tcp/udp:3478端口的映射即可。
相机的地址不需要映射。
至此公网访问视频流完成!有问题请留言。
发表评论