janus本身部署在公网时,其内部使用的libnice库已经实现了stun的功能,在配置文件janus.jcfg里面,nat_1_1_mapping配置成公网地址,其位于NAT后面的局域网客户端之间可以实现媒体流之间的分享,发布者将媒体流推到公网,而janus服务端将媒体流推给订阅者。

如下图所示:

这种情况下,根本不需要coturn,现在引入coturn,coturn是stun和turn的结合体,其中stun用于发现地址发现,turn用于流转发。
关于coturn,看到的博客都是用于地址发现,如下图这样一个场景,收集candidate。

而对于流转发,尚未找到合适的博客。
本篇博客,主要说明coturn的流转发功能。

首先,本人在公网上部署了coturn,关于部署的过程,本人参考了博客
coturn服务配置
其中在turnserver.conf的最后,本人添加了如下内容:

listening-port=19302
listening-ip=0.0.0.0
external-ip=xxx.xxx.251.92
min-port=20000
max-port=40000
user=li:li123
realm=stun.XX.cn
cli-password=qwerty
cert=/usr/local/turnserver/etc/turn_server_cert.pem
pkey=/usr/local/turnserver/etc/turn_server_pkey.pem

其中external-ip是公网地址,为了隐私,本人将ip段的前面部分用xxx.xxx代替。

然后用下面命令启动coturn服务

./bin/turnserver -v -r xxx.xxx.251.92 -a -o -c ./etc/turnserver.conf

启动服务后,发现19302既是tcp端口,又是udp端口。

下面我们将NAT内的客户端的流经过coturn转发,推给janus服务端,下面分别给出地址信息:
coturn:公网地址为xxx.xxx.251.92(中国 天津市),本地地址为10.0.0.143
janus:公网地址为xxx.xxx.251.90(中国 天津市),本地地址为10.0.0.122

客户端地址:本地地址10.0.0.2,所在NAT:60.12.13.106(中国 浙江省 杭州市 滨江区)

注意,客户端的本地地址和上面的coturn以及janus的本地地址不能互通。

此时媒体发布者的流走向如下:

媒体订阅端走向为:

下面我们讲解下媒体发布情况下,终端将流推经过coturn转发推给janus的过程。

首先,janus的配置文件中,nat_1_1_mapping注释掉,关于turn的配置开启,如下图所示:

其中公网地址的前部分做了马赛克处理,turn_user和turn_pwd按照配置coturn时设置的信息来,不要配错。

同时webrtc客户端也需要将coturn的地址加入进来,代码如下:

关于客户端为何需要将coturn的地址添加进去,后面再做解释。

然后启动客户端,加入会议,接着在客户端所在机器,coturn所在机器,janus所在机器,开启抓包,然后打开摄像头,向服务端推流,结果发现,流直接推给了janus,没有经过coturn。

我查看了在sdp交互时,janus回给客户端的answer sdp,如下所示:

o=- 2743266240368598531 2 IN IP4 10.0.0.122
s=VideoRoom 38584232
t=0 0
a=group:BUNDLE video
a=msid-semantic: WMS janus
m=video 9 UDP/TLS/RTP/SAVPF 127 120
c=IN IP4 10.0.0.122
b=AS:4096
a=recvonly
a=mid:video
a=rtcp-mux
a=ice-ufrag:/6At
a=ice-pwd:V0LKmCsUWBaXjcAFKkHmqK
a=ice-options:trickle
a=fingerprint:sha-256 D2:B9:31:8F:DF:24:D8:0E:ED:D2:EF:25:9E:AF:6F:B8:34:AE:53:9C:E6:F3:8F:F2:64:15:FA:E8:7F:53:2D:38
a=setup:active
a=rtpmap:127 H264/90000
a=fmtp:127 profile-level-id=42e01f;packetization-mode=1
a=rtcp-fb:127 ccm fir
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 transport-cc
a=extmap:3 urn:3gpp:video-orientation
a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=rtpmap:120 rtx/90000
a=fmtp:120 apt=127
a=ssrc-group:FID 3739256708 2784241827
a=candidate:1 1 udp 2015363327 10.0.0.122 32893 typ host
a=candidate:2 1 udp 1679819007 xxx.xxx.251.90 32893 typ srflx raddr 10.0.0.122 rport 32893
a=candidate:3 1 udp 505413887 xxx.xxx.251.92 27192 typ relay raddr 10.0.0.122 rport 32893
a=end-of-candidates

注意,公网地址处,本人用了xxx代替。

可见answer sdp的最后部分是3个candidate,其中第一个是janus的本地地址,第二个是janus的公网地址(srflx反射地址),第三个是janus的relay地址(coturn地址)。
而本人其实在janus上并没有配置janus的公网ip,janus通过函数nice_agent_set_relay_info设置了coturn信息,其通过与coturn的交互得知了自己的公网ip,如下图所示,janus在向coturn进行relay端口请求时,得到了自己的公网ip。

而candidate是有优先级的,srflx的优先级要高于relay,故此次推流,发现没有经过coturn,直接发给了janus。

由于answer sdp中的candidate是janus组装的,故可以修改janus的代码,将srflx的地址去掉,在ice.c的函数janus_ice_candidates_to_sdp里面,添加红色部分的代码,将srflx的candidate屏蔽掉。

重新编译并启动janus,启动客户端并发布媒体,janus回复的answer sdp如下:

o=- 2892261328926992312 2 IN IP4 10.0.0.122
s=VideoRoom 95364800
t=0 0
a=group:BUNDLE video
a=msid-semantic: WMS janus
m=video 9 UDP/TLS/RTP/SAVPF 127 120
c=IN IP4 10.0.0.122
b=AS:4096
a=recvonly
a=mid:video
a=rtcp-mux
a=ice-ufrag:3GO5
a=ice-pwd:mjai24kvf9SI1+fE3IXIg4
a=ice-options:trickle
a=fingerprint:sha-256 D2:B9:31:8F:DF:24:D8:0E:ED:D2:EF:25:9E:AF:6F:B8:34:AE:53:9C:E6:F3:8F:F2:64:15:FA:E8:7F:53:2D:38
a=setup:active
a=rtpmap:127 H264/90000
a=fmtp:127 profile-level-id=42e01f;packetization-mode=1
a=rtcp-fb:127 ccm fir
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 transport-cc
a=extmap:3 urn:3gpp:video-orientation
a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=rtpmap:120 rtx/90000
a=fmtp:120 apt=127
a=ssrc-group:FID 2148634348 4202343640
a=candidate:1 1 udp 2015363327 10.0.0.122 22349 typ host
a=candidate:3 1 udp 505413887 xxx.xxx.251.92 24104 typ relay raddr 10.0.0.122 rport 22349
a=end-of-candidates

看sdp最后部分的candidate,只剩下了两个,这次经过抓包分析,流确实由客户端推给coturn,然后由coturn推给janus。

下面我根据三个抓包分析下过程,先分析下客户端的流如何发给coturn,首先从sdp中看到xxx.xxx.251.92 24104,这个是coturn用于接收客户端流的地址端口,这个24104端口是由janus向coturn申请转发端口时,coturn主机上分配的。

客户端将流发给coturn时,在NAT上进行了打洞,打出的地址为(60.12.13.106:21003),下面是抓包的过程,本人直接用文本写出来,避免贴图模糊。

10.0.0.2(61888)--------Binding Request user:3G05:y04Z--------------> xxx.xxx.251.92(24104)
10.0.0.2(61888)<-Binding Success Response XOR-MAPPED-ADDRESS: 60.12.13.106:21003 user: 3GO5:yO4Z--xxx.xxx.251.92(24104)

下面抓包下janus向coturn申请转发端口(端口号:24104)的过程

10.0.0.122(22349)--------Allocate Request UDP----------->xxx.xxx.251.92(19302)
10.0.0.122(22349)<--------Allocate Error Response error-code: 401 (Unauthenticated) Unauthorized with nonce realm: xxx.xxx.251.92-----------xxx.xxx.251.92(19302)
10.0.0.122(22349)--------Allocate Request UDP realm: xxx.xxx.251.92 with nonce user: li----------->xxx.xxx.251.92(19302)
10.0.0.122(22349)<--------Allocate Success Response XOR-RELAYED-ADDRESS: xxx.xxx.251.92:24104 XOR-MAPPED-ADDRESS: xxx.xxx.251.90:22349 lifetime: 600-----------xxx.xxx.251.92(19302)

交互中,可以发现,向 coturn申请转发端口,需要用户名和密码,由交互过程中的第四步发现,coturn分配了24104的转发端口,在coturn的24104端口接收到了客户端的媒体流后,其用19302端口将媒体流发给了janus的22349端口(不是24104端口)。

10.0.0.143(19302)--------UDP媒体流----------->xxx.xxx.251.90(22349)

janus在申请转发端口时,就已经给出了其本身接收转发流的端口22349。

下面说下webrtc客户端为何需要将coturn的地址加入进来,若不将coturn的地址加入进来,发现,客户端在向coturn转发端口24104 打洞(Binding Request)的时候,此端口一直未能给以回复,导致打洞失败,具体原因未知。

经过抓包发现,客户端 打洞(Binding Request)的时候,必须先向coturn的配置端口19302进行Binding请求,然后才能向此转发端口(24104)进行Binding,交互如下:

10.0.0.2(61888)--------Binding Request--------------> xxx.xxx.251.92(19302)
10.0.0.2(61888)<-Binding Success Response XOR-MAPPED-ADDRESS: 60.12.13.106:21002 MAPPED-ADDRESS: 60.12.13.106:21002 RESPONSE-ORIGIN: xxx.xxx.251.92:19302--xxx.xxx.251.92(19302)
10.0.0.2(61888)--------Binding Request user:3G05:y04Z--------------> xxx.xxx.251.92(24104)
10.0.0.2(61888)<-Binding Success Response XOR-MAPPED-ADDRESS: 60.12.13.106:21003 user: 3GO5:yO4Z--xxx.xxx.251.92(24104)

客户端代码将coturn的地址加入进来,会触发向coturn的配置端口19302进行Binding请求,使得最后打洞成功。

webrtc janus服务器部署在公网,coturn转发媒体流相关推荐

  1. webrtc janus服务器调试工具 admin api 详解(一)

    引言: 最近在调试janus服务器, 在外网测试的时候出现一些问题, 但是一直不清楚到底是什么地方出现问题,就一直追日志, 突然偶然的机会了解到admin api, 使用之后确实能找到不少问题, 对j ...

  2. 家庭自建流媒体服务器,如何创建自己的“家庭媒体流服务器”使用Plex与FreeNAS - 第3部分...

    每个人都有自己的电影,歌曲,视频歌曲,图片等的收藏.他们很多都想知道我们如何流到我们所有的家庭设备. 这里是我们可以使用Plex Media Server通过LAN网络在我们的家中使用智能电视,iPa ...

  3. webrtc janus服务器调试工具 admin api 详解(二)调试janus看这一篇就够了!!

    在上一篇发布的时候离现在已经过去不少的时间, 这段时间也一直处理这个问题, 最终解决了它,因为自己内容的原因,自己也走不了少的弯路,比如增加一些配置问题, coturn在测试网站 是通的,但实际使用的 ...

  4. 推流拉流WebRtc+Janus+coturn+Nginx方案

    1.创建测试SSL,本地http可以拉起摄像头,服务器需要配置https拉起摄像头 在nginx中,可以用ssl模块配置同时支持http和https并存 创建服务器私钥,命令会让你输入一个口令 ope ...

  5. 自建服务器部署WEB网站可公网访问

    文章目录 自建服务器部署WEB网站可公网访问 一.公网IP端口映射到服务器主机或者内网穿透 二.Nginx 反向代理和负载均衡 2.1 windows 10 安装Nginx 2.2 ubuntu18. ...

  6. Webrtc服务器搭建(基于公网环境)

    webrtc服务器环境搭建 (基于公网环境) Last Modified Date: 2017/8/2 目录 1. 搭建平台 2. 软件安装 3. 搭建房间服务器(Room Server) 4. 搭建 ...

  7. 公司官网建站笔记(二):在云服务器部署PHP服务(公网访问首页)

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/124659175 各位读者,知识无穷而人力有穷,要么改需 ...

  8. 聊聊WebRTC网关服务器1:如何选择服务端端口方案?

    <聊聊WebRTC网关服务器>系列文章系由WebRTCon2018中网易云信音视频技术专家的分享内容<从零开始构建音视频网关服务器>整理而成,该系列文章将和大家分享网易NRTC ...

  9. 即构自研WebRTC网关服务器架构实践

    演讲 / 黄开宁 整理 / 小极狗 作为实时音视频领域最火的开源技术,WebRTC 点对点的架构模式,无法支持大规模并发.如何在架构中引入服务端,一直是开发者关注的热点.5月20日,在WebRTCon ...

最新文章

  1. 林元庆创办的AiBee科技完成新融资,要赋能B端生意
  2. python分析基金数据,[Python数据分析]numpy基金会,基础
  3. 动态规划(DP),压缩状态,插入字符构成回文字符串
  4. python电商项目源码_Python Django(WEB电商项目构建)
  5. 聚类算法(1):K-Means算法
  6. 电力负荷事件划分(有代码)
  7. Send data format set as XML
  8. 数学:莫比乌斯反演-约数个数和
  9. android 处理鼠标滚轮事件 【转】
  10. 剑指Offer:二进制中1的个数
  11. [总结]SqlServer中如何实现自动备份数据!
  12. python代码覆盖率工具_Python代码覆盖率分析工具Coverage
  13. BZOJ_1003_[ZJOI2006]_物流运输_(动态规划+最短路)
  14. php给留言分配id_php建立简单的用户留言系统
  15. Java实战之管家婆记账系统(19)——报告界面及功能实现
  16. 如何获得大学教材的PDF版本?
  17. python 微信小程序制作教程_微信小程序从零开始开发步骤(一)
  18. 计算机分屏显示知识,如何使用Windows的分屏显示功能
  19. win10升级助手_不用QQ也能电脑远程,win10这功能太良心了!真后悔晚发现
  20. linux 内核 禁止抢占,内核抢占实现(preempt)

热门文章

  1. ajax防止表单重复提交
  2. 《视频解密》中文版(第四版) 第五章 模拟视频接口
  3. 从抄书到开源之巅:章亦春的程序人生
  4. 开发、运维、业务都说好的全栈云原生长这样
  5. 编程中的英语单词大全
  6. Spring Security 记住我功能原理以及实现
  7. 信号幅值归一化(Python)
  8. php fflush失败,php fflush 函数_PHP教程
  9. 轮询,长连接,长轮询原理及实现方式,优缺点
  10. PCIe TLP包内容 全