博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Webrtc 多人视频会议系统 服务器 Licode 介绍
阅读量:2223 次
发布时间:2019-05-08

本文共 5647 字,大约阅读时间需要 18 分钟。

       WebRTC又称 web实时通信,主要是为了扩展浏览器的功能,使浏览器能够进行实时音视频通信,不同的浏览器对Webrtc的实现代码也许不同,但Google的浏览器将Webrtc的实现代码开源了,以至于很多人一听到Webrtc就联想到Google的开源实现,以至于误以为使用Webrtc就非常难,因为Webrtc的实现都是C/C++代码,让很多人望而生畏。其实我们只需要懂得浏览器端的Javascript,就能使用Webrtc,很多的时候不必关心Webrtc的核心实现。本文根据自己使用webrtc的经验撰写,错误之处难免,希望朋友不吝指正。

      在WebRTC中,有三个主要的概念,理解了这三个概念 ,也就理解了WebRTC的使用技术了。这三个概念是:

  • MediaStream:用于从采集设备,Canvas等获取音频和视频数据,进行音视频压缩。
  • RTCPeerConnection:端到端的通信连接器,主要用于音频和视频数据通信。
  • RTCDataChannel:连接建立后的数据通道,可以用于任意应用数据的通信。

MediaStream

主要是用于获取音频和视频流。其JavaScript调用也比较简单,样本代码如下:

'use strict';navigator.getUserMedia = navigator.getUserMedia                         || navigator.webkitGetUserMedia                         || navigator.mozGetUserMedia;var constraints = { // 音频、视频约束  audio: true, // 指定请求音频Track  video: {  // 指定请求视频Track      mandatory: { // 对视频Track的强制约束条件          width: {min: 320},          height: {min: 180}      },      optional: [ // 对视频Track的可选约束条件          {frameRate: 30}      ]  }};var video = document.querySelector('video');function successCallback(stream) {  if (window.URL) {    video.src = window.URL.createObjectURL(stream);  } else {    video.src = stream;  }}function errorCallback(error) {  console.log('navigator.getUserMedia error: ', error);}navigator.getUserMedia(constraints, successCallback, errorCallback);

通过调用浏览器的getUserMedia函数来操作音频和视频,该函数接收三个参数,分别是音视频的约束,成功的回调以及失败的回调。在底层,浏览器通过音频和视频引擎对捕获的原始音频和视频流加以处理,除了对画质和音质增强之外,还得保证音频和视频的同步。

RTCPeerConnection

在获取到音频和视频流后,下一步要做的就是将其发送出去。但这个跟client-server模式不同,这是client-client之间的传输,因此,在协议层面就必须解决NAT穿透问题,否则传输就无从谈起。另外,由于WebRTC主要是用来解决实时通信的问题,可靠性并不是很重要,因此,WebRTC使用UDP作为传输层协议:低延迟和及时性才是关键。

调用RTCPeerConnection的示例代码如下:

var signalingChannel = new SignalingChannel();var pc = null;var ice = {    "iceServers": [        { "url": "stun:stun.l.google.com:19302" }, //使用google公共测试服务器        { "url": "turn:user@turnserver.com", "credential": "pass" } // 如有turn服务器,可在此配置    ]};signalingChannel.onmessage = function (msg) {    if (msg.offer) { // 监听并处理通过发信通道交付的远程提议        pc = new RTCPeerConnection(ice);        pc.setRemoteDescription(msg.offer);        navigator.getUserMedia({ "audio": true, "video": true }, gotStream, logError);    } else if (msg.candidate) { // 注册远程ICE候选项以开始连接检查        pc.addIceCandidate(msg.candidate);    }}function gotStream(evt) {    pc.addstream(evt.stream);    var local_video = document.getElementById('local_video');    local_video.src = window.URL.createObjectURL(evt.stream);    pc.createAnswer(function (answer) { // 生成描述端连接的SDP应答并发送到对端        pc.setLocalDescription(answer);        signalingChannel.send(answer.sdp);    });}pc.onicecandidate = function (evt) {    if (evt.candidate) {        signalingChannel.send(evt.candidate);    }}pc.onaddstream = function (evt) {    var remote_video = document.getElementById('remote_video');    remote_video.src = window.URL.createObjectURL(evt.stream);}function logError() { ... }

DataChannel

DataChannel支持端到端的任意应用数据交换,就像WebSocket一样,但是是端到端的。

建立RTCPeerConnection连接之后,两端可以打开一或多个信道交换文本或二进制数据。

var ice = {    'iceServers': [        {'url': 'stun:stun.l.google.com:19302'},   // google公共测试服务器        // {"url": "turn:user@turnservera.com", "credential": "pass"}    ]};// var signalingChannel =  new SignalingChannel();var pc = new RTCPeerConnection(ice);navigator.getUserMedia({'audio': true}, gotStream, logError);function gotStream(stram) {    pc.addStream(stram);    pc.createOffer().then(function(offer){        pc.setLocalDescription(offer);    });}pc.onicecandidate = function(evt) {    // console.log(evt);    if(evt.target.iceGatheringState == 'complete') {        pc.createOffer().then(function(offer){            // console.log(offer.sdp);            // signalingChannel.send(sdp);        })    }}function handleChannel(chan) {    console.log(chan);    chan.onerror = function(err) {}    chan.onclose = function() {}    chan.onopen = function(evt) {        console.log('established');        chan.send('DataChannel connection established.');    }    chan.onmessage = function(msg){        // do something    }}// 以合适的交付语义初始化新的DataChannelvar dc = pc.createDataChannel('namedChannel', {reliable: false});handleChannel(dc);pc.onDataChannel = handleChannel;function logError(){    console.log('error');}

通过以上代码,即可在浏览器端使用Webrtc,但Webrtc远没有这么简单,Webrtc需要服务器端来支持,否则就单个浏览器孤掌难鸣。

Webrtc需要有一个服务器来实现浏览器端点互通与音视频数据转发,能够支持Webrtc的服务器端项目很多,这里选择Licode搭建开发环境,相比其他项目,Licode比较轻量级,便于初学者学习Licode扮演的角色如下:

Licode扮演着Router的角色,通过Licode,可以实现多对多通信。

Licode的安装

git clone https://github.com/lynckia/licode.git cd licode./scripts/installUbuntuDeps.sh./scripts/installNuve.sh./scripts/installErizo.sh./scripts/initLicode.sh             // 启动 licode ./scripts/initBasicExamples.sh      // 启动 example

Licode 依赖很多各种各样的库,并且和服务器平台强相关,所以这其中会出各种各样的莫名错误,需要手动安装好依赖,并且 libavutil 等库的编译要使用 ./configure --enable-shared --disable-asm,每次编译前最好 make clean。

配置 Licode (licode_config.js):

 
config.erizoController.iceServers = [{'url': 'stun:123.218.123.109:5600'}];config.erizoController.turnServer.url = 'turn:123.218.123.109:3478'; config.erizoController.publicIP = '123.218.123.109';config.erizoController.hostname = '123.218.123.109';config.erizo.stunserver = '123.218.123.109';config.erizoController.turnServer.username = 'username';config.erizoController.turnServer.password = 'password';

erizoController.js:

GLOBAL.config.erizoController.iceServers || [{'url': 'stun:123.218.123.109:3478'}];GLOBAL.config.erizoController.publicIP = '123.218.123.109';GLOBAL.config.erizoController.hostname = '123.218.123.109';GLOBAL.config.erizoController.turnServer.url = "turn:123.218.123.109?transport=udp";GLOBAL.config.erizoController.turnServer.username = "username";GLOBAL.config.erizoController.turnServer.password = "password";

你可能感兴趣的文章
AJAX 初次体验!推荐刚学看这个满好的!
查看>>
AJAX 设计制作 在公司弄的 非得要做出这个养的 真晕!
查看>>
Linux 查看文件大小
查看>>
Java并发编程:线程池的使用
查看>>
redis单机及其集群的搭建
查看>>
Java多线程学习
查看>>
检查Linux服务器性能
查看>>
Java 8新的时间日期库
查看>>
Chrome开发者工具
查看>>
【LEETCODE】102-Binary Tree Level Order Traversal
查看>>
【LEETCODE】106-Construct Binary Tree from Inorder and Postorder Traversal
查看>>
【LEETCODE】202-Happy Number
查看>>
和机器学习和计算机视觉相关的数学
查看>>
十个值得一试的开源深度学习框架
查看>>
【LEETCODE】240-Search a 2D Matrix II
查看>>
【LEETCODE】53-Maximum Subarray
查看>>
【LEETCODE】215-Kth Largest Element in an Array
查看>>
【LEETCODE】241-Different Ways to Add Parentheses
查看>>
【LEETCODE】312-Burst Balloons
查看>>
【LEETCODE】232-Implement Queue using Stacks
查看>>