タイムラインはありません。非同期ですが、説明しようと思いますが、主な流れは、SDP でのオファーとアンサーの流れと、icecandidate の流れの 2 つです。
フロー 1 : SDP
ステップ 1 - オファーピア:
オファー側で、RTCPeerconnection を作成します (パラメーターとして stun、trun サーバーを使用)。
var STUN = {
url:'stun:stun.l.google.com:19302'
};
var TURN = {
url: 'turn:homeo@turn.bistri.com:80',
credential: 'homeo'
};
var iceServers = {
iceServers: [STUN, TURN]
};
var peer = new RTCPeerConnection(iceServers);
ステップ 2 - オファーピア:
制約を指定して getUserMedia を呼び出します。成功のコールバックで、addStream メソッドを使用してストリームを RTCPeerconnection に追加します。次に、Peerconnection オブジェクトで createOffer を呼び出してオファーを作成できます。
navigator.webkitGetUserMedia(
{
audio: false,
video: {
mandatory: {
maxWidth: screen.width,
maxHeight: screen.height,
minFrameRate: 1,
maxFrameRate: 25
}
}
},
gotStream, function(e){console.log("getUserMedia error: ", e);});
function gotStream(stream){
//If you want too see your own camera
vid.src = webkitURL.createObjectURL(stream);
peer.addStream(stream);
peer.createOffer(onSdpSuccess, onSdpError);
}
ステップ 3 - 提供ピア:
createOffer のコールバック メソッドで、パラメーター (sdp オファー) を RTCPeerConnection (ICE 候補の収集を開始する) の localDescription として設定します。次に、シグナリング サーバーを使用してオファーを他のピアに送信します。(シグナリングサーバーについては説明しません。データを別のサーバーに渡すだけです)。
function onSdpSuccess(sdp) {
console.log(sdp);
peer.setLocalDescription(sdp);
//I use socket.io for my signaling server
socket.emit('offer',sdp);
}
ステップ 5 - 応答ピア:
アンサー ピアは、オファーを受信するたびに、TURN、STUN サーバー、getUserMedia を使用して RTCPeerconnection を作成し、コールバックでストリームを RTCPeerConnection に追加します。SDP オファーでは、sdpOffer で setRemoteDescription を使用します。次に、createAnswer をトリガーします。createAnswer の成功コールバックで、setLocalDescription をパラメータとともに使用し、シグナリング サーバーを使用して応答 sdp をオファー ピアに送信します。
//Receive by a socket.io socket
//The callbacks are useless unless for tracking
socket.on('offer', function (sdp) {
peer.setRemoteDescription(new RTCSessionDescription(sdp), onSdpSuccess, onSdpError);
peer.createAnswer(function (sdp) {
peer.setLocalDescription(sdp);
socket.emit('answer',sdp);
}, onSdpError);
});
ステップ 7 : ピアを提供する
RTCPeerConnection で sdp 応答、setRemoteDescription を受信します。
socket.on('answer', function (sdp) {
peer.setRemoteDescription(new RTCSessionDescription(sdp), function(){console.log("Remote Description Success")}, function(){console.log("Remote Description Error")});
});
フロー 2 : ICECandidate
両方 :
RTCPeerConnection が oneicecandidate を起動するたびに、signalingserver を介して候補を他のピアに送信します。シグナリング サーバーからの icecandidate を受信したら、 addIceCandidate(New RTCIceCandidate(obj)) を使用して RTCPeerConnection に追加します。
peer.onicecandidate = function (event) {
console.log("New Candidate");
console.log(event.candidate);
socket.emit('candidate',event.candidate);
};
socket.on('candidate', function (candidate) {
console.log("New Remote Candidate");
console.log(candidate);
peer.addIceCandidate(new RTCIceCandidate({
sdpMLineIndex: candidate.sdpMLineIndex,
candidate: candidate.candidate
}));
});
ついに :
上記の 2 つのフローがうまく機能する場合は、各 RTCPeerConnection で onaddstream イベントを使用します。ICE候補が互いにペアリングし、ピアツーピアの最適な方法を見つけると、SDPとネゴシエートされ、ピアツーピア接続を通過するストリームが追加されます。したがって、このイベントでは、ストリームをビデオタグなどに追加するだけで十分です。
peer.onaddstream = function (event) {
vid.src = webkitURL.createObjectURL(event.stream);
console.log("New Stream");
console.log(event.stream);
};
明日、私が言っていることを理解するのに役立つと思ういくつかのコードで編集します。質問がある場合は、それを行ってください。
ここに私のシグナリングサーバーがあります:
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(3000);
app.get('/', function (req, res) {
res.send('The cake is a lie');
});
io.on('connection', function (socket) {
console.log('NEW CONNECTION');
socket.on('offer', function (data) {
console.log(data);
socket.broadcast.emit("offer",data);
});
socket.on('answer', function (data) {
console.log(data);
socket.broadcast.emit("answer",data);
});
socket.on('candidate', function (data) {
console.log(data);
socket.broadcast.emit("candidate",data);
});
});