Webrtc 多人视频会议系统 服务器 Licode 介绍
? ? ? ?WebRTC又稱 web實(shí)時(shí)通信,主要是為了擴(kuò)展瀏覽器的功能,使瀏覽器能夠進(jìn)行實(shí)時(shí)音視頻通信,不同的瀏覽器對(duì)Webrtc的實(shí)現(xiàn)代碼也許不同,但Google的瀏覽器將Webrtc的實(shí)現(xiàn)代碼開源了,以至于很多人一聽到Webrtc就聯(lián)想到Google的開源實(shí)現(xiàn),以至于誤以為使用Webrtc就非常難,因?yàn)閃ebrtc的實(shí)現(xiàn)都是C/C++代碼,讓很多人望而生畏。其實(shí)我們只需要懂得瀏覽器端的Javascript,就能使用Webrtc,很多的時(shí)候不必關(guān)心Webrtc的核心實(shí)現(xiàn)。本文根據(jù)自己使用webrtc的經(jīng)驗(yàn)撰寫,錯(cuò)誤之處難免,希望朋友不吝指正。
? ? ? 在WebRTC中,有三個(gè)主要的概念,理解了這三個(gè)概念 ,也就理解了WebRTC的使用技術(shù)了。這三個(gè)概念是:
- MediaStream:用于從采集設(shè)備,Canvas等獲取音頻和視頻數(shù)據(jù),進(jìn)行音視頻壓縮。
- RTCPeerConnection:端到端的通信連接器,主要用于音頻和視頻數(shù)據(jù)通信。
- RTCDataChannel:連接建立后的數(shù)據(jù)通道,可以用于任意應(yīng)用數(shù)據(jù)的通信。
MediaStream
主要是用于獲取音頻和視頻流。其JavaScript調(diào)用也比較簡單,樣本代碼如下:
'use strict';navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;var constraints = { // 音頻、視頻約束audio: true, // 指定請(qǐng)求音頻Trackvideo: { // 指定請(qǐng)求視頻Trackmandatory: { // 對(duì)視頻Track的強(qiáng)制約束條件width: {min: 320},height: {min: 180}},optional: [ // 對(duì)視頻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);通過調(diào)用瀏覽器的getUserMedia函數(shù)來操作音頻和視頻,該函數(shù)接收三個(gè)參數(shù),分別是音視頻的約束,成功的回調(diào)以及失敗的回調(diào)。在底層,瀏覽器通過音頻和視頻引擎對(duì)捕獲的原始音頻和視頻流加以處理,除了對(duì)畫質(zhì)和音質(zhì)增強(qiáng)之外,還得保證音頻和視頻的同步。
RTCPeerConnection
在獲取到音頻和視頻流后,下一步要做的就是將其發(fā)送出去。但這個(gè)跟client-server模式不同,這是client-client之間的傳輸,因此,在協(xié)議層面就必須解決NAT穿透問題,否則傳輸就無從談起。另外,由于WebRTC主要是用來解決實(shí)時(shí)通信的問題,可靠性并不是很重要,因此,WebRTC使用UDP作為傳輸層協(xié)議:低延遲和及時(shí)性才是關(guān)鍵。
調(diào)用RTCPeerConnection的示例代碼如下:
var signalingChannel = new SignalingChannel(); var pc = null; var ice = {"iceServers": [{ "url": "stun:stun.l.google.com:19302" }, //使用google公共測(cè)試服務(wù)器{ "url": "turn:user@turnserver.com", "credential": "pass" } // 如有turn服務(wù)器,可在此配置] }; signalingChannel.onmessage = function (msg) {if (msg.offer) { // 監(jiān)聽并處理通過發(fā)信通道交付的遠(yuǎn)程提議pc = new RTCPeerConnection(ice);pc.setRemoteDescription(msg.offer);navigator.getUserMedia({ "audio": true, "video": true }, gotStream, logError);} else if (msg.candidate) { // 注冊(cè)遠(yuǎn)程ICE候選項(xiàng)以開始連接檢查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應(yīng)答并發(fā)送到對(duì)端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支持端到端的任意應(yīng)用數(shù)據(jù)交換,就像WebSocket一樣,但是是端到端的。
建立RTCPeerConnection連接之后,兩端可以打開一或多個(gè)信道交換文本或二進(jìn)制數(shù)據(jù)。
var ice = {'iceServers': [{'url': 'stun:stun.l.google.com:19302'}, // google公共測(cè)試服務(wù)器// {"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} }// 以合適的交付語義初始化新的DataChannel var dc = pc.createDataChannel('namedChannel', {reliable: false});handleChannel(dc); pc.onDataChannel = handleChannel;function logError(){console.log('error'); }通過以上代碼,即可在瀏覽器端使用Webrtc,但Webrtc遠(yuǎn)沒有這么簡單,Webrtc需要服務(wù)器端來支持,否則就單個(gè)瀏覽器孤掌難鳴。
Webrtc需要有一個(gè)服務(wù)器來實(shí)現(xiàn)瀏覽器端點(diǎn)互通與音視頻數(shù)據(jù)轉(zhuǎn)發(fā),能夠支持Webrtc的服務(wù)器端項(xiàng)目很多,這里選擇Licode搭建開發(fā)環(huán)境,相比其他項(xiàng)目,Licode比較輕量級(jí),便于初學(xué)者學(xué)習(xí)。Licode扮演的角色如下:
Licode扮演著Router的角色,通過Licode,可以實(shí)現(xiàn)多對(duì)多通信。
Licode的安裝
Licode 依賴很多各種各樣的庫,并且和服務(wù)器平臺(tái)強(qiáng)相關(guān),所以這其中會(huì)出各種各樣的莫名錯(cuò)誤,需要手動(dòng)安裝好依賴,并且 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";總結(jié)
以上是生活随笔為你收集整理的Webrtc 多人视频会议系统 服务器 Licode 介绍的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 二叉树的中序遍历,前序遍历,后序遍历
- 下一篇: [含论文+源码等]微信小程序电影购票+后