外网访问内网海康威视监控视频的方案:WebRTC + Coturn
需求背景
在仓库中有海康威视的监控摄像头,内网中是可以直接访问到监控摄像的画面,由于项目的需求,需要在外网中也能看到监控画面。
实现这个功能的意义在于远程操控设备的时候可以看到监控画面,方便查看远程操作的效果。
解决方案
海康威视监控摄像头提供的是RTSP视频流,在网上查阅了资料,可以通过WebRTC协议在web页面上显示RTSP视频流。
WebRTC协议实现的最好的开源项目是webrtc-streamer,地址在:https://github.com/mpromonet/webrtc-streamer
由于WebRTC会使用对等连接,所以从外网访问内网的海康威视监控视频的时候就需要中继服务,也就是需要一个 STUN 或 TURN 服务器,其作用是为每个客户端提供 ICE 候选,然后将其转移到远程对等方。
大多数 WebRTC 应用都需要服务器来中继对等方之间的流量,因为客户端之间通常无法建立直接套接字(除非它们位于同一本地网络中)。常见的解决方法是使用 TURN 服务器。该术语代表"Traversal Using Relays around NAT",是一种用于中继网络流量的协议。
目前,网上有多个 TURN 服务器选项,既有自托管应用(例如开源 COTURN 项目),也有云端提供的服务。
本项目最终采用自托管的COTURN项目,地址在:https://github.com/coturn/coturn
方案示例图如下:

上图中的Relay server即为turn中继服务器,而STUN server的作用是通过收集NAT背后peer端(即:躲在路由器或交换机后的电脑)对外暴露出来的ip和端口,找到一条可穿透路由器的链路,俗称"打洞"。stun/turn服务器通常要部署在公网上,能被所有peer端访问到,coturn开源项目同时实现了stun和turn服务的功能,是webrtc应用的必备首选。
方案确定了,接下来就是动手实际搭建了。
实际搭建
基于Coturn搭建stun/turn服务器
参考github中readme文档,在云服务器中直接使用apt安装:
step1 更新软件源
bash
$ sudo apt update
step2 安装coturn
bash
$ sudo apt install coturn
step3 修改配置文件
主要修改下面几项关键的配置:
lt-cred-mech
user=<用户名>:<密码>
注意:要把用户名和密码替换成实际的字符串。
step4 停止掉coturn服务
由于安装coturn服务后,默认是会运行该服务的,所以这儿要先停止掉
bash
$ sudo systemctl stop coturn
step5 前台运行turnserver服务器
第一次运行,最好是使用前端运行的方式,如果没有问题的话,再使用后端服务的运行方式。
bash
$ sudo turnserver -r chengdu --log-file stdout
step6 后端服务的方式运行turnserver
在启动之前要在配置文件中增加realm=chengdu
配置项。
bash
$ sudo systemctl start coturn
可以使用journalctl -xeu coturn.service
查看后台服务coturn的日志。
step7 验证stun和turn服务正常运行。
找一台可以访问Coturn服务所在ip的机器,然后执行下面的命令:
bash
$ turnutils_uclient -v -u <用户名> -w <密码> <云服务器地址>
注意:turnutils_uclient命令要在安装了coturn服务的机器上才有。
还可以在下面这个网址上验证stun/turn服务是否运行正常。
https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
参考下图,把stun和turn地址设置好,然后点击最下面的"Gather candidates"(收集候选链路)

云服务器要开放的端口
云服务器需要开发tcp 3478 和 udp 3478端口,方便客户端连接stun和turn服务器。
并且要开放中继端口范围udp 49152-65535。
启动webrtc-streamer
step1 下载webrtc-streamer
从https://github.com/mpromonet/webrtc-streamer/releases/latest下载软件包。
step2 启动webrtc-streamer服务
进入到软件目录,然后执行下面的命令:
bash
./webrtc-streamer -v debug -H 8800 -s<云主机ip>:3478 -t<用户名>:<密码>@<云主机>:3478
注意:将云主机地址替换成安装coturn服务的云主机公网IP,用户名和密码就是在turnserver.conf中设置的用户名和密码,直接替换就行。
step3 将webrtc-streamer做成开机启动。
这个步骤可以参考Linux添加systemd服务,使用systemctl start xxx启动服务。
前端页面示例代码
index.html文件内容如下:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
<script src="js/webrtcstreamer.js"></script>
<title>视频监控-测试</title>
<style>
.content{
width: 100%;
height: 100%;
position: absolute;
background-color: aliceblue;
}
.item{
width: 49.5%;
height: 49.5%;
float: left;
margin: 3px;
}
video {
width: 100%;
height: 100%;
object-fit: fill;
}
</style>
</head>
<body>
<div class="content">
<div class="item"><video id="video1" muted autoplay loop></video></div>
<div class="item"><video id="video2" muted autoplay loop></video></div>
<div class="item"><video id="video3" muted autoplay loop></video></div>
<div class="item"><video id="video4" muted autoplay loop></video></div>
</div>
</body>
<script>
// let webRtcServer = null;
function init() {
var videourl1 = "<替换为实际的海康威视RTSP地址1>";
let ID1 = "video1";
realViewHik(ID1, videourl1)
var videourl2 = "<替换为实际的海康威视RTSP地址2>";
let ID2 = "video2";
realViewHik(ID2, videourl2)
var videourl3 = "替换为实际的海康威视RTSP地址3";
let ID3 = "video3";
realViewHik( ID3, videourl3)
var videourl4 = "替换为实际的海康威视RTSP地址4";
let ID4 = "video4";
realViewHik(ID4, videourl4)
}
function realViewHik(elem, rtspUrl) {
let webRtcServer = new WebRtcStreamer(elem, "http://<webrtc-streamer的ip地址>:8800");
let option = "rtptransport=tcp";
webRtcServer.connect(rtspUrl, null, option, null)
}
window.onload = function () {
init();
}
</script>
</html>
其中<script src="js/webrtcstreamer.js"></script>
是引用的webrtc-streamer中的webrtcstreamer.js文件,该文件在软件包的webrtc-streamer-v0.8.5-Linux-x86_64-Release/html
路径下,可以直接拷贝到js
目录下使用。
原理解读
WebRTC协议
WebRTC(Web Real-Time Communication)是一种开源技术,旨在通过简单的应用程序接口(API)实现浏览器和移动应用之间的实时音视频通信和数据共享,而无需安装插件或第三方软件。它由Google主导开发,现已成为W3C和IETF的标准。
核心功能
- 实时音视频通信
- 支持浏览器之间直接传输高清视频和音频,延迟低(通常 < 500ms)。
- 点对点(P2P)传输
- 数据直接在用户设备间传输,减少服务器中转,提升效率。
- 数据通道(Data Channel)
- 支持传输任意数据(如文件、游戏指令、文本),类似WebSocket但延迟更低。
- 加密传输
- 默认使用DTLS-SRTP加密,确保通信安全。
关键技术组件
- MediaStream(getUserMedia)
访问摄像头和麦克风,获取音视频流。 - RTCPeerConnection
建立P2P连接,处理编解码、网络穿透(NAT)和流量控制。 - RTCDataChannel
提供双向数据传输,适合低延迟场景(如游戏、文件共享)。 - ICE/STUN/TURN
- ICE(Interactive Connectivity Establishment):协调最佳连接路径。
- STUN:获取公网IP,解决NAT穿透问题。
- TURN:在中继服务器转发数据,用于严格的防火墙环境。
WebRTC-Streamer建立连接的时序图如下

WebRTC建立点对点通信的过程如下图所示
设备A 信令服务器 设备B STUN 发送 SDP Offer 转发 Offer 发送 SDP Answer 转发 Answer 获取 ICE Candidate 获取 ICE Candidate 发送 ICE Candidate 发送 ICE Candidate 转发 B的Candidate 转发 A的Candidate 直接建立 P2P 连接 设备A 信令服务器 设备B STUN