文章链接
https://gitee.com/fakerlove/web-rtc
WebRTC是一个用于音视频处理和即时通讯的开源库,支持跨平台,于2010年Google将其开源,
众所周知,浏览器本身不支持相互之间直接建立信道进行通信,都是通过服务器进行中转。比如现在有两个客户端,甲和乙,他们俩想要通信,首先需要甲和服务器、乙和服务器之间建立信道。甲给乙发送消息时,甲先将消息发送到服务器上,服务器对甲的消息进行中转,发送到乙处,反过来也是一样。这样甲与乙之间的一次消息要通过两段信道,通信的效率同时受制于这两段信道的带宽。同时这样的信道并不适合数据流的传输,如何建立浏览器之间的点对点传输,一直困扰着开发者。WebRTC应运而生
WebRTC是一个开源项目,旨在使得浏览器能为实时通信(RTC)提供简单的JavaScript接口。说的简单明了一点就是让浏览器提供JS的即时通信接口。这个接口所创立的信道并不是像WebSocket一样,打通一个浏览器与WebSocket服务器之间的通信,而是通过一系列的信令,建立一个浏览器与浏览器之间(peer-to-peer)的信道,这个信道可以发送任何数据,而不需要经过服务器。并且WebRTC通过实现MediaStream,通过浏览器调用设备的摄像头、话筒,使得浏览器之间可以传递音频和视频
商用的直播平台一般会包括信令服务器、流媒体服务器、客户端(共享端和接收端)三部分, 而我们的实验环境可以再简化,只包括流媒体服务器和端户端两部分。
这个是音视频核心技术
webrtc api 指导
(1)紫色部分是Web应用开发者API层
(2)蓝色实线部分是面向浏览器厂商的API层
(3)蓝色虚线部分浏览器厂商可以自定义实现
传输/会话层:会话层组件采用了libjingle库的部分组件实现,无须使用xmpp/jingle协议。
音频引擎是包含一系列音频多媒体处理的框架,包括从视频采集卡到网络传输端等整个解决方案。
VoiceEngine是WebRTC极具价值的技术之一,是Google收购GIPS公司后开源的。在VoIP上,技术业界领先。
iSAC Internet Speech Audio Codec:针对VoIP和音频流的宽带和超宽带音频编解码器,是WebRTC音频引擎的默认的编解码器。
iLBC Internet Low Bitrate Codec:VoIP音频流的窄带语音编解码器。标准由IETF RFC3951和RFC3952定义。
Acoustic Echo Canceler (AEC) 回声消除器是一个基于软件的信号处理元件,能实时的去除mic采集到的回声。
Noise Reduction (NR) 噪声抑制也是一个基于软件的信号处理元件,用于消除与相关VoIP的某些类型的背景噪声(嘶嘶声,风扇噪音等等… …)
WebRTC视频处理引擎:VideoEngine是包含一系列视频处理的整体框架,从摄像头采集视频到视频信息网络传输再到视频显示整个完整过程的解决方案。
测试网址
https://appr.tc/
测试网址
https://www.webrtc-experiment.com/
官方英文文档
https://www.w3.org/TR/webrtc/
官方中文文档
https://developer.mozilla.org/zh-CN/docs/Web/API/WebRTC_API
案例介绍
https://github.com/muaz-khan/WebRTC-Experiment
中文社区
https://webrtc.org.cn/
通过MediaStream的API能够通过设备的摄像头及话筒获得视频、音频的同步流
RTCPeerConnection是WebRTC用于构建点对点之间稳定、高效的流传输的组件
RTCDataChannel使得浏览器之间(点对点)建立一个高吞吐量、低延时的信道,用于传输任意数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="jquery.js"></script>
</head>
<body>
<div>
<label>输入设备</label>
<select id="audioSource"></select>
</div>
<div>
<label>输出设备</label>
<select id="audioOutput"></select>
</div>
<div>
<label>视屏输入设备</label>
<select id="videoSource"></select>
</div>
<script>
(async function () {
// 获取元素
let audioSource = document.querySelector("#audioSource");
let audioOutput = document.querySelector("#audioOutput");
let videoSource = document.querySelector("#videoSource");
// 获取媒体信息
let devices = navigator.mediaDevices.enumerateDevices();
console.log(devices)
if (devices == null) {
alert("对不起媒体信息不支持")
} else {
devices.then(gotDevices)
.catch(handleError);
}
function gotDevices(devicesInfo) {
// 对于所有设备开始获取遍历
devicesInfo.forEach(function (deviceInfo) {
console.log(deviceInfo.kind +
": 名称 = " + deviceInfo.label +
": 设备id = " + deviceInfo.deviceId +
": 设备groupid = " + deviceInfo.groupId);
var option = document.createElement('option');
option.html = deviceInfo.label;
option.value = deviceInfo.deviceId;
if (deviceInfo.kind == 'audioinput') {
audioSource.appendChild(option);
} else if (deviceInfo.kind == 'audiooutput') {
audioOutput.appendChild(option);
} else if (deviceInfo.kind == 'videoinput') {
videoSource.appendChild(option);
}
})
}
})();
// 错误的时候发生的信息
function handleError(err) {
console.log(err.name + "--" + err.message);
}
</script>
</body>
</html>
同门可以通过调用navigator.getUserMedia(),这个方法接受三个参数:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="jquery.js"></script>
<style>
.red {
border: 1px red solid;
height: 300px;
width: 400px;
}
.blue {
border: 1px blue solid;
height: 50px;
width: 200px;
}
</style>
</head>
<body>
<video id="video" autoplay playsinline class="red"></video>
<button onclick="video()">开始视屏</button>
<audio id="audio" controls autoplay class="blue" >
</audio><button onclick="audio()">开始声音</button>
</body>
<script type="text/javascript">
let stream=null;
async function video(){
let constraints = {
video: true,
audio: false
};
stream = await navigator.mediaDevices.getUserMedia(constraints);
document.getElementById("video").srcObject=stream;
}
async function audio(){
stream=null;
let constraints = {
video: false,
audio: true
};
stream = await navigator.mediaDevices.getUserMedia(constraints);
document.getElementById("audio").srcObject=stream;
}
</script>
</html>
为了实现兼容性,所以需要js 来实现这样子的兼容性
NAT全称network adress translation,即网络地址转换。其存在的意义是将私有的IP地址转化为公有IP地址。
告诉我你的公网IP地址+端口是什么。搭建STUN服务器很简单
STUN服务器:用户数据报协议UDP简单穿越网络地址转换器NAT,它允许所有的NAT客户终端(如防火墙后边的计算机)与位于局区域网以外的VOIP服务商实现电话通话。
NAT给设备提供了一个IP地址以使用专用局域网,但是这个地址不能在外部使用。由于没有公用地址,WebRTC对等端就无法进行通信。而WebRTC使用 STUN来解决这个问题。
STUN服务器位于公共网络上,并且有一个简单的任务:检查传入请求的IP地址(来自运行在NAT后面的应用程序),并将该地址作为响应发送回去。换句话说,应用程序使用 STUN服务器从公共角度发现其IP:端口。这个过程使得WebRTC对等端为自己活得一个可公开访问的地址,然后通过信令机制将其传递给另一个对等端以建立直接链接。(实际上不同NAT工作方式都有所不同,可能有多个NAT层,但是原理是一样的)。
因为 STUN服务器不需要做太多的工作或者记特别多的东西,所以相对低规格的 STUN服务器就可以处理大量的请求。
根据webrtcstats.com的统计(2013年),大多数WebRTC通话都成功地使用 STUN进行连接,有86%。尽管对于防火墙之后的对等端之间的呼叫以及复杂的NAT配置,成功通话量会更少一些。
RTCPeerConnection尝试通过UDP建立对等端之间的直接通信。如果失败的话,RTCPeerConnection就会使用TCP进行连接。如果使用TCP还失败的话,可以用 TURN服务器作为后备,在终端之间转发数据。
重申: TURN用于中继对等端之间的音频/视频/数据流,而不是信令数据。
TURN服务器具有公共地址,因此即使对等端位于防火墙或代理之后也可以与其他人联系。 TURN服务器有一个概念上来讲简单的任务—中继数据流—但是与 STUN服务器不同的是,他们会消耗大量的带宽。换句话说, TURN服务器需要更加的强大。
上图显示了 TURN的作用:单纯的 STUN没有成功建立连接,所以每个对等端还需要使用 TURN服务器。
信令是协调通信的过程。为了使WebRTC应用程序能够建立一个“通话”,其客户需要交换以下信息:
RTCPeerConnection是WebRTC应用程序用来创建对等端连接并传输音视频的API。
初始化这个过程RTCPeerConnection有两个工作要做:
一旦确定了本地数据,就必须通过信令机制与远端对等端进行交换。
让我们假设一个场景:Alice正在尝试呼叫Eve。下面是完整的提供/应答机制:
Alice和Eve也需要交换网络信息。“查找候选项”这个表达是指使用ICE框架查找网络接口和端口的过程。
1. Alice使用onicecandidate处理器创建一个RTCPeerConnection对象。
2. 处理器在网络候选变得可用时被调用。
3. 在处理器中,Alice通过其信令通道将字符串化的候选数据发送给Eve。
4. 当Eve从Alice那里获得候选消息时,她调用addIceCandidate(),将候选项添加到远端对等描述中。
JSEP支持ICE Candidate Trickling,它允许主叫方在最初的提供之后递增地向被叫方提供候选项,并使被叫方开始在通话中进行操作并建立连接而不用等所有候选项到达。
Janus 是由Meetecho设计和开发的开源、通用的基于SFU架构的WebRTC流媒体服务器,它支持在Linux的服务器或MacOS上的机器进行编译和安装。由于Janus 是使用C语言进行编写的,因此它的性能十分优秀。Janus 的整体架构图如下图所示。
Janus整体架构图.png
Janus 主要由三个部分组成,分别是Core、Plugin和Transport,下面是相关模块的介绍:
从整体架构上看,Janus支持众多传输协议,并且采用业务插件架构设计模式。因此,Janus流媒体服务器十分适合多种业务模型或业务经常变化的公司或项目使用。
文档
https://janus.conf.meetecho.com/docs/
教程文档
https://doc-kurento.readthedocs.io/en/latest/user/tutorials.html#webrtc-one-to-many-broadcast
Kurento是欧洲的技术团队创建的开源项目(详解访问官方网站),是马德里一所大学的研究机构创建的项目
openvidu 项目,第二次封装,基于kurento
https://openvidu.io/
项目演示-java 版本
git clone https://github.com/Kurento/kurento-tutorial-java.git
Kurento模块分为三类:
主要模块 与Kurento Media Server开箱即用合并:
kms-core:Kurento Media Server的主要组件。 kms-elements:Kurento Media Elements的实现(WebRtcEndpoint,PlayerEndpoint等) kms-filters:Kurento过滤器的实现(FaceOverlayFilter,ZBarFilter等) 内置模块 Kurento团队开发的额外模块,用于增强Kurento Media Server的基本功能。到目前为止,有四个内置模块,分别是:
kms-pointerdetector:基于颜色跟踪检测视频流中指针的过滤器。 kms-chroma:过滤器,它在顶层使用颜色范围并使之透明,从而在后面显示另一个图像。 kms-crowddetector:用于检测视频流中人聚集的过滤器。 kms-platedetector:用于检测视频流中的车牌的过滤器。 定制模块 Kurento Media Server的扩展,提供了新的媒体功能。
参照文章
https://blog.csdn.net/huahao1989/article/details/106321369
docker pull kurento/kurento-media-server:6.16
docker run -itd --name kms --network host --restart always -p 8888:8888 kurento/kurento-media-server:6.16
要检查KMS是否已启动并正在侦听连接,请使用以下命令:
curl \
--include \
--header "Connection: Upgrade" \
--header "Upgrade: websocket" \
--header "Host: 127.0.0.1:8888" \
--header "Origin: 127.0.0.1" \
http://127.0.0.1:8888/kurento
您应该得到类似于以下内容的响应:
HTTP/1.1 500 Internal Server Error
Server: WebSocket++/0.7.0
忽略“ Server Error ”消息:这是预期的,它实际上证明KMS已启动并正在侦听连接。
git clone https://github.com/konoui/kurento-coturn-docker.git
cd kurento-coturn-docker/coturn/
sudo docker build --tag coturn .
sudo docker run --name coturn -p 3478:3478 -p 3478:3478/udp coturn
上面的测试,但是好像因为是3年前的,ubuntun 不支持了
所以换了
coturn 源
http://turnserver.open-sys.org/downloads/
可能出现的问题
WARNING: IPv4 forwarding is disabled. Networking will not work.
#需要做如下配置
解决办法:
vi /etc/sysctl.conf
net.ipv4.ip_forward=1 #添加这段代码
#重启network服务
systemctl restart network && systemctl restart docker
#查看是否修改成功 (备注:返回1,就是成功)
[root@docker-node2 ~]# sysctl net.ipv4.ip_forward net.ipv4.ip_forward = 1
下面的我自己配置stun 和turn
centos8
yum install -y make gcc gcc-c++ wget openssl-devel libevent libevent-devel
wget http://turnserver.open-sys.org/downloads/v4.5.2/turnserver-4.5.2.tar.gz
tar -zxvf turnserver-4.5.2.tar.gz
cd turnserver-4.5.2
./configure --prefix=/usr/local/turnserver # 指定安装的目录
make && make install
echo turnserver_home=/usr/local/turnserver >> ~/.bashrc
echo "PATH=\$PATH:\$turnserver_home/bin" >> ~/.bashrc
source ~/.bashrc
echo listening-port=3478 >> /usr/local/turnserver/share/examples/turnserver/etc/turnserver.conf # 监听的端口
echo listening-ip=10.206.0.5 >> /usr/local/turnserver/share/examples/turnserver/etc/turnserver.conf # 监听的内网IP
echo external-ip=119.45.206.16 >> /usr/local/turnserver/share/examples/turnserver/etc/turnserver.conf # 监听的外网IP
echo user=user:123456 >> /usr/local/turnserver/share/examples/turnserver/etc/turnserver.conf # 设置账号密码
cp /usr/local/turnserver/etc/turnserver.conf.default /etc/turnserver.conf
turnserver -v -r 119.45.206.16 -a -o -c /usr/local/turnserver/share/examples/turnserver/etc/turnserver.conf #指定配置文件启动服务
https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/
测试stun有效性(出现两个地址加”done“才为有效):
测试turn有效性(出现三个地址加"done"才为有效):
docker exec -it kms /bin/bash #进入镜像
apt-get update #安装vim
apt-get install vim -y
cd /etc/kurento/modules/kurento/ #进入配置文件夹
vim WebRtcEndpoint.conf.ini #编辑配置文件
若要配置打洞服务器,配置文件应该改成这样的: 修改WebRtcEndpoint.conf.ini
stunServerAddress=xx.xx.xx.xx
stunServerPort=pp
turnURL=username:userpwd@xx.xx.xx.xx:pp?transport=tcp
我的就是
stunServerAddress=119.45.206.16
stunServerPort=3478
turnURL=user:123456@119.45.206.16:3478?transport=tcp
docker restart kms
在kurento-hello-wrold项目文件夹中,执行以下操作:
cd /src/main/resources/static/js/
vim index.js
在函数function uiStart()里,增加一个叫iceservers的变量,格式如下:
var iceservers={
"iceServers":[
{
urls:"stun:139.198.123.138:3478"
},
{
urls:["turn:139.198.123.138:3478"],
username:"kurento",
credential: "kurento"
}
]
}
再修改底下的options变量:
const options = {
localVideo: uiLocalVideo,
remoteVideo: uiRemoteVideo,
mediaConstraints: { audio: true, video: true },
onicecandidate: (candidate) => sendMessage({
id: 'ADD_ICE_CANDIDATE',
candidate: candidate,
}),
configuration: iceservers //修改在这里,增加了一个configuration的key
};
SRS是一个采用MIT协议授权的国产的简单的RTMP/HLS 直播服务器。最新版还支持FLV模式,同时具备了RTMP的实时性,以及HLS中属于HTTP协议对各种网络环境高度适应性,并且支持更多播放器。它的功能与nginx-rtmp-module类似, 可以实现RTMP/HLS的分发。
Github地址:github.com/ossrs/srs
centos 8
yum install -y autoconf automake cmake freetype-devel gcc gcc-c++ git libtool make mercurial nasm pkgconfig zlib-devel
git clone https://github.com/ossrs/srs
cd srs/trunk
./configure && make
Jitsi是开源的视频会议系统,可以实现在线视频会议,文档共享和即时消息的分享。它支持网络视频会议,使用SFU模式实现视频路由器功能。开发语言是Java。它支持SIP帐号注册电话呼叫。不仅支持单机本地安装方式,还支持云平台安装。
官网地址:jitsi.org/
声网提供了从编解码到端到端传输的全套服务,开发者可以接入上文所述的音视频前后处理的开源项目,配合使用声网SDK可以建立高质量的实时音视频应用。在Web端,Agora Web SDK可以帮助WebRTC开发者解决服务端传输中会遇到的卡顿、延时、回声、多人视频不稳定等问题。同时,声网SDK还对多个系统平台的应用提供实时音视频通讯服务。
声网在Github上有许多可供开发者参考、实践的demo源码,覆盖了从网页端、iOS到Android平台,以及音视频直播、游戏连麦、企业会议、AR、直播答题、小程序等多种实时互动应用场景。
Github地址:github.com/AgoraIO-Com…
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。