前言

这个问题的解决方案在官方文档中已经给出了

实现

准备工作

首先你需要有一台不能从外部发送 UDP 包的服务器(大部分私有服务器都是这样吧)

可以用官方推荐的工具进行测试

启动 SRS

1
2
# 换成服务器外网地址
CANDIDATE="127.0.0.1"
1
2
3
4
5
6
7
8
docker run --name srs -it \
--network="host" \
--env CANDIDATE=$CANDIDATE \
-v /app/srs/conf/:/usr/local/srs/conf/ \
-v /app/srs/objs/:/usr/local/srs/objs/ \
registry.cn-hangzhou.aliyuncs.com/ossrs/srs:5 \
./objs/srs \
-c conf/my.srs.conf

为什么 CANDIDATE 要换成服务器外网地址

通信过程

可以看到,除了上面的客户端请求服务器 url 和服务器回传 SDP 是经过 https 代理之外,其余数据传输过程都是根据 SDP 包含的 CANDIDATEudp 端口交互的。

如果服务器不给自己的外网地址,且不开放 udp 端口,那么客户端就没法传输或者获取流数据

为什么不用端口映射

我是笨蛋,我试了半天 --add-host=host.docker.internal:host-gateway 总是没法弄通

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
listen              1935;
max_connections 1000;
daemon off;
srs_log_tank console;

http_server {
enabled on;
listen 8080;
dir ./objs/nginx/html;
}

http_api {
enabled on;
listen 1985;
}
stats {
network 0;
}
rtc_server {
enabled on;
listen 26411;
tcp {
enabled on;
listen 26411;
}
protocol tcp;
candidate $CANDIDATE;
}

vhost __defaultVhost__ {
hls {
enabled on;
hls_fragment 6;
hls_key_url https://localhost:8080;
}
http_remux {
enabled on;
mount [vhost]/[app]/[stream].flv;
}
rtc {
enabled on;
rtmp_to_rtc off;
rtc_to_rtmp on;
}
dvr {
enabled on;
dvr_plan session;
dvr_duration 600; # 这个其实没有生效
dvr_path ./objs/nginx/html/dvrs/[app]/[stream].[timestamp].flv;
}
http_hooks{
enabled on;
on_dvr http://localhost:8085/api/v1/dvrs;
}
}

不使用 TCP 配置会有什么后果

webrtc 推拉流之后

docker logs srs -f 日志输出一切正常

除了输出 SDP 之后,日志会紧跟着一句 clinet finished

其实我们可以猜测,这里的 finished 可能就代表着,客户端传递给服务器的消息就已经完毕了

经排查,我们的服务器没法从外部使用 udp 访问服务器,所以我们只能使用 tcp 来进行 webrtc 传输了

猜你想知道怎么把这玩意部署到带服务器上且只暴露一个端口(其实是两个)

怎么把这么多的端口映射到一个路径下呢

我看官方 nginx 是不是必须监听两个端口 80 和 443

当然不是

两个 nginx 解决

直接对接用户的 nginxhttps 就行,我们 srs 这边还不需要

srs 服务器上面的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server{
listen 11004; # 换成老板让你监听的端口
server_name _;

# 将 api rtc 请求转发到容器 API 端口 1985
location ~ ^/(api|rtc)/ {
proxy_pass http://127.0.0.1:1985$reuqest_uri;
}

# 将其他请求转发到 HTTP 服务端口 8080
location ~ ^/(console|players)/ {
proxy_pass http://127.0.0.1:8080/$request_uri;
}

location ~ ^/.+/.*\.(flv|m3u8|ts|aac|mp3)$ {
proxy_pass http://127.0.0.1:8080/$request_uri;
}
}

要注意的是 11004 可以是只暴露给私网的端口

而上面 my.srs.conf 需要的 26411 必须暴露给公网