webrtc (Web Real-Time Communications) 是一个实时通讯技术,也是实时音视频技术的标准和框架。

大白话讲,webrtc是一个集大成的实时音视频技术集,包含了各种客户端api、音视频编/解码lib、流媒体传输协议、回声消除、安全传输等。

对于开发者来说可以借助webrtc非常方便的实现低延时视频通话能力。

现在主流的直播系统、会议系统基本都是基于webrtc来实现。

一、webrtc 三种架构

我们先大概了解下webrtc的几种架构及各自适用场景。

【Mesh】

Mesh架构,需要所有参与连接的peer建立与所有其他peer的媒体连接。

该架构需要n-1个上下行,以此带来的带宽消耗(流量)、编/解码消耗(手机性能)成线性增长。

该架构只能适用3-4个人的小型会议场景。

【MCU】

所有本房间的peer将本地媒体流推到远程媒体服务器,由媒体服务器进行混流,然后再推到所有连接的peer端。

该架构的优点就是只需要1路上下行,随着peer人数不断增加,依然不会对用户造成带宽、手机性能影响。

该架构将压力转嫁到服务端,由专用媒体服务器来完成混流,转推等功能。

【SFU】

相对于MCU来说SFU只做转发,媒体服务器压力有限。与mesh架构相比,只需要n-1个下行,1个上行。

在大规模的场合该架构具有伸缩性。

二、实现 1v1 视频通话

废话不多说,动手实践下。

(麻雀虽小,五脏俱全。通过实现1v1的功能,来整体了解下webrtc协议的原理。)

github:https://github.com/Plen-wang/webrtc-demo-1v1

由于是私有证书问题,chrome会有安全提示。(demo地址暂时还能用 -_- )

有两个方法可以试下。

第一个方法,手动设置一个类似不安全白名单列表,然后重启浏览器。

chrome://flags/#unsafely-treat-insecure-origin-as-secure

如果不行,我们试下第二个方法肯定可以。

点击空白页输入 thisisunsafe 字符。

动手之前,我们先简单了解下webrtc的连接的大致流程和涉及的相关技术点。

【WebRTC P2P】

【NAT穿透】

peer基本都在内网,需要通过nat穿透技术来与peer建立连接。

根据nat的拓扑情况大致分为如下几种:完全锥形、IP锥形、端口锥形、对称形。

stun\turn协议:stun协议用来拿到peer公网ip,turn用来做relay数据转发。

【SDP】

sdp是会话描述协议。

是媒体协商时使用,用于将本地支持的媒体(编解码等)信息、candidate(连接候选者)信息打包发送到信令服务器。

sdp的交换是通过中间服务器(信令服务器)来完成的。

【ICE】

ICE是一个不断尝试连接的协议,不同的网络情况下ICE大概会尝试如下几种方式来建立通讯通道。

host(peers都在内网)、 srflx(nat穿透)、prflx(nat穿透-Full Cone)、relay(中继)

【服务端】

在整个连接生命周期中都是需要服务端参与。参与webrtc协作的服务端大概分为这几种类型。

stun/turn服务器(p2p穿透)、信令服务器、媒体服务器(媒体信息处理)、业务服务器(可选)

整体流程大致如下。

(上述技术点较多,感兴趣可以自行查询相关资料)

【部署STUN\TURN服务器】

为了支持1v1公网访问,我们需要搭建一个stun/turn服务器。

这里我们使用 Coturn 开源组件,coturn的镜像有很多,可自行选择。

(注意准备coturn配置文件时,记得设置用户名和密码。)

    docker run -d  --rm --name turn-server --network=host   \
-v ${pwd}/turnserver.conf:/etc/coturn/turnserver.conf \
instrumentisto/coturn

部署好之后可以通过ICE测试工具测试下

https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice

    stun:1.15.11.173:3478?transport=tcp
turn:1.15.11.173:3478?transport=tcp:user:pwd

如果正常返回了ICE尝试的连接类型,说明部署没有问题。

【实现信令服务器与客户端代码】

我们采用golang来实现一个简单的信令服务器,使用开源组件go-socket。

同时还需要实现一个web客户端。

demo代码就不贴到文章里了,放在github上。整体代码比较简单,感兴趣可以看下。

git@github.com:Plen-wang/webrtc-demo-1v1.git

【部署信令服务器】

当在本地debug的差不多了,我们把信令服务器打个镜像发到云主机上。

(如果部署本demo,可以直接使用此镜像。)

    docker push wangqingpei/rtc-signal-server:latest
docker run --name signal-server -d -p:8080:8080 wangqingpei/rtc-signal-server

【部署web服务器】

部署好信令服务器之后,我们把静态文件放到web服务器里,直接使用nginx镜像部署非常简单。

    docker run -d -p 80:80 -p 443:443  --rm --name webrtc-nginx   \
-v /data/rtc-nginx.conf:/etc/nginx/nginx.conf \
-v /data/pem/server.key:/etc/nginx/server.key \
-v /data/pem/server.pem:/etc/nginx/server.pem \
-v /data/rtc-static-file:/usr/share/nginx/html nginx

部署前,记得修改js里的stun服务器地址。

//创建RTCPeerConnection对象
function createRTCPeerConnection() {
try { const configuration = {'iceServers': [{'urls': 'stun:1.15.11.173:3478?transport=tcp'}]} rtcConnObject = new RTCPeerConnection(configuration);
rtcConnObject.onicecandidate = handleRtcICECandidate;//ice 交互
rtcConnObject.onaddstream = handleRtcAddStream;//远程stream加入
rtcConnObject.onremovestream = handleRtcRemoveStream;//远程stream移除
rtcConnObject.addStream(localStreamObject);//添加本地stream
console.log("create local RTCPeerConnection object ok.");
} catch (e) {
console.error("create RTCPeerConnection err.", e);
}
}

两边peer就可以借助stun服务器拿到公网ip实现nat穿透。

三、实现MCU/SFU 多人通话

MCU/SFU架构需要 专用媒体服务器 参与。

【媒体服务器选择】

专用媒体服务器有 OWT(open webrtc toolkit)、TWS(Kurento Media Server)等重量级的开源产品。

这两款开源框架都支持MCU、SFU架构功能。

我们选择OWT捣鼓下。

先看下部署起来的效果,默认MCU模式。

红框部分是服务端混流之后的效果。

【部署OWT】

注意,owt-server-4.3镜像与最新版chrome有兼容性问题,会报错 Empty candidate 错误。

我们直接使用5.0的镜像部署。

docker run -d --name owt-demo --network host lmshao/owt-server

由于该镜像是使用默认配置打的,启动后手动进入容器修改下相关配置,换成你云主机的公网ip,然后重启服务。

配置文件路径

vi dist/webrtc_agent/agent.toml

配置项,这里修改成你的公网ip

network_interfaces = [{name = "eth0", replaced_ip_address = "1.116.175.232"}]  # default: []

stun服务器可选

stunport = 3478 #default: 0
stunserver = "1.15.11.173" #default: ""

然后修改下portal.toml文件,文件路径。

vi dist/portal/portal.toml

修改成公网ip

ip_address = "1.116.175.232" #default: ""

重启下相关服务

./bin.restart-all.sh

注意启动日志里有一个id、key,这是用来进入管理页面用的。(没错,owt提供了后台管理页面 -_-)

superServiceId: xxx
superServiceKey: xxx sampleServiceId: xxx
sampleServiceKey: xxx

默认3004端口下是mcu模式,连线的人多了就会明显卡顿(看服务器配置)。

我们切到SFU模式试下流畅度和服务器负载情况。

通过 ?forward=true 参数控制

https://1.116.175.232:3004/?forward=true

OWT还配有管理后台用于控制媒体服务器的相关参数。



OWT还是比较强大的,有兴趣可以研究研究。

参考资料:

github.com/googollee/go-socket.io

《WebRTC技术详解:从0到1构建多人视频会议系统》

《WebRTC音视频实时互动技术:原理、实战与源码分析》

《FFmpeg 音视频开发基础与实战》

一文带你了解webrtc基本原理(动手实现1v1视频通话)的更多相关文章

  1. 一文带你了解elasticsearch

    一文带你了解elasticsearch cxf2102100人评论160人阅读2019-07-02 21:31:36   elasticsearch es基本概念 es术语介绍 文档Document ...

  2. Istio是啥?一文带你彻底了解!

    原标题:Istio是啥?一文带你彻底了解! " 如果你比较关注新兴技术的话,那么很可能在不同的地方听说过 Istio,并且知道它和 Service Mesh 有着牵扯. 这篇文章可以作为了解 ...

  3. 一文带您了解5G的价值与应用

    一文带您了解5G的价值与应用 5G最有趣的一点是:大多数产品都是先有明确应用场景而后千呼万唤始出来.而5G则不同,即将到来的5G不仅再一次印证了科学技术是第一生产力还给不少用户带来了迷茫——我们为什么 ...

  4. 【转帖】Istio是啥?一文带你彻底了解!

    Istio是啥?一文带你彻底了解! http://www.sohu.com/a/270131876_463994 原始位置来源: https://cizixs.com 如果你比较关注新兴技术的话,那么 ...

  5. 一文带你了解 C# DLR 的世界

    一文带你了解 C# DLR 的世界 在很久之前,我写了一片文章dynamic结合匿名类型 匿名对象传参,里面我以为DLR内部是用反射实现的.因为那时候是心中想当然的认为只有反射能够在运行时解析对象的成 ...

  6. 一文带你看清HTTP所有概念(转)

    一文带你看清HTTP所有概念   上一篇文章我们大致讲解了一下 HTTP 的基本特征和使用,大家反响很不错,那么本篇文章我们就来深究一下 HTTP 的特性.我们接着上篇文章没有说完的 HTTP 标头继 ...

  7. 一文带你了解js数据储存及深复制(深拷贝)与浅复制(浅拷贝)

    背景 在日常开发中,偶尔会遇到需要复制对象的情况,需要进行对象的复制. 由于现在流行标题党,所以,一文带你了解js数据储存及深复制(深拷贝)与浅复制(浅拷贝) 理解 首先就需要理解 js 中的数据类型 ...

  8. 【项目实践】一文带你搞定Spring Security + JWT

    以项目驱动学习,以实践检验真知 前言 关于认证和授权,R之前已经写了两篇文章: [项目实践]在用安全框架前,我想先让你手撸一个登陆认证 [项目实践]一文带你搞定页面权限.按钮权限以及数据权限 在这两篇 ...

  9. 一文带你看遍 JDK9~14 的重要新特性!

    Java9 发布于 2017 年 9 月 21 日 .作为 Java8 之后 3 年半才发布的新版本,Java 9 带 来了很多重大的变化其中最重要的改动是 Java 平台模块系统的引入,其他还有诸如 ...

随机推荐

  1. Spring-Batch处理MySQL数据后存到CSV文件

    1 介绍 用Spring Batch实现了个简单的需求,从MySQL中读取用户表数据,根据生日计算年龄,将结果输出到csv文件. 1.1 准备表及数据 user test; DROP TABLE IF ...

  2. 源码解读etcd heartbeat,election timeout之间的拉锯

    转一个我在知乎上回答的有关raft election timeout/ heartbeat interval 的回答吧. 答:准确来讲: election是timeout,而heartbeat 是in ...

  3. 用python解决打标签时将xml文件的标签名打错

    用python解决打标签时将xml文件的标签名打错 问题描述:再进行达标签时将magnetic_tile的标签名错误的打成了magnetic_title,又不想一张一张的修改 出现问题的xml文件 & ...

  4. Kubernetes client-go DeltaFIFO 源码分析

    概述Queue 接口DeltaFIFO元素增删改 - queueActionLocked()Pop()Replace() 概述 源码版本信息 Project: kubernetes Branch: m ...

  5. 花两万培训Java的三个同学,最后都怎么样了

    仙路尽头谁为峰,学完Java学Python. 前言 对于IT行业的培训,例如Java.大数据.H5等等,我一直保持着肯定的态度. 因为当年大学时期的我,也差点去参加Java培训.一是因为那时钱包空空, ...

  6. Google搜索为什么不能无限分页?

    这是一个很有意思却很少有人注意的问题. 当我用Google搜索MySQL这个关键词的时候,Google只提供了13页的搜索结果,我通过修改url的分页参数试图搜索第14页数据,结果出现了以下的错误提示 ...

  7. 快速 IO

    IO 的进化史 cin和cout 刚开始学的时候,老师叫我们用 cin 和 cout 大概是因为这最简单吧 cin>>x; cout<<x scanf和printf 学到函数了 ...

  8. easy-captcha生成验证码

    通常一些网页登陆时,都需要通过验证码去登录: 生成验证码的方法有很多,这次分享一个验证码即能是汉字的 又能是算术的. 首先maven坐标: <dependency> <groupId ...

  9. ElasticSearch6.4.2

    做一个简单的API记录 1.依赖为6.4.2  比较老的版本 2.指定ES集群,可接多个Put(); Setting setting=Setting.builder().put("clust ...

  10. SQL的语法

    SQL的语法 SQL通用语法 SQL语句可以单行或多行书写,以分号(";")结尾. SQL语句可以使用空格或缩进增强可读性. MySQL数据库的SQL语句不区分大小写(建议关键字大 ...