在學習WebRTC時,網上的示例大多代碼較多,以下是參考那些代碼簡化的一個WebRTC一對一的示例,在chrome 37下測試通過。其中iceServer可省略,沒有iceServer時在同一個局域網下仍可通訊。
客戶端代碼:
<html>
<body>
Local: <br>
<video id="localVideo" autoplay></video><br>
Remote: <br>
<video id="remoteVideo" autoplay></video>
<script>
// 僅僅用于控制哪一端的瀏覽器發起offer,#號后面有值的一方發起
var isCaller = window.location.href.split('#')[1];
// 與信令服務器的WebSocket連接
var socket = new WebSocket("ws://127.0.0.1:3000");
// stun和turn服務器
var iceServer = {
"iceServers": [{
"url": "stun:stun.l.google.com:19302"
}, {
"url": "turn:numb.viagenie.ca",
"username": "webrtc@live.com",
"credential": "muazkh"
}]
};
// 創建PeerConnection實例 (參數為null則沒有iceserver,即使沒有stunserver和turnserver,仍可在局域網下通訊)
var pc = new webkitRTCPeerConnection(iceServer);
// 發送ICE候選到其他客戶端
pc.onicecandidate = function(event){
if (event.candidate !== null) {
socket.send(JSON.stringify({
"event": "_ice_candidate",
"data": {
"candidate": event.candidate
}
}));
}
};
// 如果檢測到媒體流連接到本地,將其綁定到一個video標簽上輸出
pc.onaddstream = function(event){
document.getElementById('remoteVideo').src = URL.createObjectURL(event.stream);
};
// 發送offer和answer的函數,發送本地session描述
var sendOfferFn = function(desc){
pc.setLocalDescription(desc);
socket.send(JSON.stringify({
"event": "_offer",
"data": {
"sdp": desc
}
}));
},
sendAnswerFn = function(desc){
pc.setLocalDescription(desc);
socket.send(JSON.stringify({
"event": "_answer",
"data": {
"sdp": desc
}
}));
};
// 獲取本地音頻和視頻流
navigator.webkitGetUserMedia({
"audio": true,
"video": true
}, function(stream){
//綁定本地媒體流到video標簽用于輸出
document.getElementById('localVideo').src = URL.createObjectURL(stream);
//向PeerConnection中加入需要發送的流
pc.addStream(stream);
//如果是發起方則發送一個offer信令
if(isCaller){
pc.createOffer(sendOfferFn, function (error) {
console.log('Failure callback: ' + error);
});
}
}, function(error){
//處理媒體流創建失敗錯誤
console.log('getUserMedia error: ' + error);
});
//處理到來的信令
socket.onmessage = function(event){
var json = JSON.parse(event.data);
console.log('onmessage: ', json);
//如果是一個ICE的候選,則將其加入到PeerConnection中,否則設定對方的session描述為傳遞過來的描述
if( json.event === "_ice_candidate" ){
pc.addIceCandidate(new RTCIceCandidate(json.data.candidate));
} else {
pc.setRemoteDescription(new RTCSessionDescription(json.data.sdp));
// 如果是一個offer,那么需要回復一個answer
if(json.event === "_offer") {
pc.createAnswer(sendAnswerFn, function (error) {
console.log('Failure callback: ' + error);
});
}
}
};
</script>
</body>
</html>
實現WebRTC時,信令服務器是必須的,它幫助客戶端之間進行溝通。
這里使用Node.js的ws模塊來實現一個WebSocket服務作為信令服務器。另外使用express模塊讓它提供html頁面的訪問。
server.js代碼如下:
var express = require('express'),
app = express(),
server = require('http').createServer(app);
server.listen(3000);
app.get('/', function(req, res) {
res.sendfile(__dirname + '/webrtc.html');
});
var WebSocketServer = require('ws').Server,
wss = new WebSocketServer({server: server});
// 存儲socket的數組,這里只能有2個socket,每次測試需要重啟,否則會出錯
var wsc = [],
index = 1;
// 有socket連入
wss.on('connection', function(ws) {
console.log('connection');
// 將socket存入數組
wsc.push(ws);
// 記下對方socket在數組中的下標,因為這個測試程序只允許2個socket
// 所以第一個連入的socket存入0,第二個連入的就是存入1
// otherIndex就反著來,第一個socket的otherIndex下標為1,第二個socket的otherIndex下標為0
var otherIndex = index--,
desc = null;
if (otherIndex == 1) {
desc = 'first socket';
} else {
desc = 'second socket';
}
// 轉發收到的消息
ws.on('message', function(message) {
var json = JSON.parse(message);
console.log('received (' + desc + '): ', json);
wsc[otherIndex].send(message, function (error) {
if (error) {
console.log('Send message error (' + desc + '): ', error);
}
});
});
});
使用npm安裝需要的模塊后使用node server.js啟動服務。
測試時使用Chrome瀏覽器:
第一個瀏覽器窗口訪問頁面:http://127.0.0.1:3000,在彈出的提示中允許使用攝像頭和麥克風。
第二個瀏覽器窗口訪問頁面:http://127.0.0.1:3000#true,#true表示它是一個發起方,在彈出的提示中同樣允許使用攝像頭和麥克風。
這時頁面中應當可以看到2個畫面,一個是本地的,一個是遠端的。
將代碼中的IP稍做調整后部署到外網,即可在2個不同的地點訪問這個頁面進行實時通訊。
微信訂閱號:
源文地址:http://blog.gopersist.com/2014/10/21/webrtc-simple/