mirror of
https://github.com/ianramzy/decentralized-video-chat.git
synced 2025-02-20 23:15:01 +08:00
working with peerconnection dict for 2 ppl
This commit is contained in:
parent
79e6a860cd
commit
da732735ae
@ -29,12 +29,15 @@ const chatZone = $("#chat-zone");
|
|||||||
|
|
||||||
var VideoChat = {
|
var VideoChat = {
|
||||||
connected: false,
|
connected: false,
|
||||||
|
counter: 0,
|
||||||
willInitiateCall: false,
|
willInitiateCall: false,
|
||||||
localICECandidates: [],
|
localICECandidates: [],
|
||||||
socket: io(),
|
socket: io(),
|
||||||
remoteVideoWrapper: document.getElementById("wrapper"),
|
remoteVideoWrapper: document.getElementById("wrapper"),
|
||||||
localVideo: document.getElementById("local-video"),
|
localVideo: document.getElementById("local-video"),
|
||||||
|
peerConnections: {},
|
||||||
recognition: undefined,
|
recognition: undefined,
|
||||||
|
uuid: undefined,
|
||||||
|
|
||||||
// Call to getUserMedia (provided by adapter.js for cross browser compatibility)
|
// Call to getUserMedia (provided by adapter.js for cross browser compatibility)
|
||||||
// asking for access to both the video and audio streams. If the request is
|
// asking for access to both the video and audio streams. If the request is
|
||||||
@ -94,49 +97,47 @@ var VideoChat = {
|
|||||||
VideoChat.localVideo.srcObject = stream;
|
VideoChat.localVideo.srcObject = stream;
|
||||||
// Now we're ready to join the chat room.
|
// Now we're ready to join the chat room.
|
||||||
VideoChat.socket.emit("join", roomHash);
|
VideoChat.socket.emit("join", roomHash);
|
||||||
|
// Receive its own uuid
|
||||||
|
VideoChat.socket.on("uuid", (uuid) => (VideoChat.uuid = uuid));
|
||||||
// Add listeners to the websocket
|
// Add listeners to the websocket
|
||||||
VideoChat.socket.on("full", chatRoomFull);
|
VideoChat.socket.on("full", chatRoomFull);
|
||||||
VideoChat.socket.on("offer", VideoChat.onOffer);
|
VideoChat.socket.on("offer", VideoChat.onOffer);
|
||||||
VideoChat.socket.on("ready", VideoChat.readyToCall);
|
VideoChat.socket.on("ready", VideoChat.readyToCall);
|
||||||
VideoChat.socket.on(
|
VideoChat.socket.on("willInitiateCall", VideoChat.call)
|
||||||
"willInitiateCall",
|
|
||||||
() => (VideoChat.willInitiateCall = true)
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// When we are ready to call, enable the Call button.
|
// When we are ready to call, enable the Call button.
|
||||||
readyToCall: function (event) {
|
readyToCall: function (event) {
|
||||||
logIt("readyToCall");
|
logIt("readyToCall");
|
||||||
// First to join call will most likely initiate call
|
},
|
||||||
if (VideoChat.willInitiateCall) {
|
call: function (uuid, room) {
|
||||||
logIt("Initiating call");
|
logIt("Initiating call");
|
||||||
VideoChat.startCall();
|
VideoChat.startCall(uuid);
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set up a callback to run when we have the ephemeral token to use Twilio's TURN server.
|
// Set up a callback to run when we have the ephemeral token to use Twilio's TURN server.
|
||||||
startCall: function (event) {
|
startCall: function (uuid) {
|
||||||
logIt("startCall >>> Sending token request...");
|
logIt("startCall >>> Sending token request...");
|
||||||
VideoChat.socket.on("token", VideoChat.onToken(VideoChat.createOffer));
|
VideoChat.socket.on("token", VideoChat.onToken(function() {VideoChat.createOffer(uuid)}, uuid));
|
||||||
VideoChat.socket.emit("token", roomHash);
|
VideoChat.socket.emit("token", roomHash);
|
||||||
},
|
},
|
||||||
|
|
||||||
// When we receive the ephemeral token back from the server.
|
// When we receive the ephemeral token back from the server.
|
||||||
onToken: function (callback) {
|
onToken: function (callback, uuid) {
|
||||||
logIt("onToken");
|
logIt("onToken");
|
||||||
return function (token) {
|
return function (token) {
|
||||||
logIt("<<< Received token");
|
logIt("<<< Received token");
|
||||||
// Set up a new RTCPeerConnection using the token's iceServers.
|
// Set up a new RTCPeerConnection using the token's iceServers.
|
||||||
VideoChat.peerConnection = new RTCPeerConnection({
|
VideoChat.peerConnections[uuid] = new RTCPeerConnection({
|
||||||
iceServers: token.iceServers,
|
iceServers: token.iceServers,
|
||||||
});
|
});
|
||||||
// Add the local video stream to the peerConnection.
|
// Add the local video stream to the peerConnection.
|
||||||
VideoChat.localStream.getTracks().forEach(function (track) {
|
VideoChat.localStream.getTracks().forEach(function (track) {
|
||||||
VideoChat.peerConnection.addTrack(track, VideoChat.localStream);
|
VideoChat.peerConnections[uuid].addTrack(track, VideoChat.localStream);
|
||||||
});
|
});
|
||||||
// Add general purpose data channel to peer connection,
|
// Add general purpose data channel to peer connection,
|
||||||
// used for text chats, captions, and toggling sending captions
|
// used for text chats, captions, and toggling sending captions
|
||||||
dataChanel = VideoChat.peerConnection.createDataChannel("chat", {
|
dataChanel = VideoChat.peerConnections[uuid].createDataChannel("chat", {
|
||||||
negotiated: true,
|
negotiated: true,
|
||||||
// both peers must have same id
|
// both peers must have same id
|
||||||
id: 0,
|
id: 0,
|
||||||
@ -161,8 +162,8 @@ var VideoChat = {
|
|||||||
};
|
};
|
||||||
// Set up callbacks for the connection generating iceCandidates or
|
// Set up callbacks for the connection generating iceCandidates or
|
||||||
// receiving the remote media stream.
|
// receiving the remote media stream.
|
||||||
VideoChat.peerConnection.onicecandidate = VideoChat.onIceCandidate;
|
VideoChat.peerConnections[uuid].onicecandidate = VideoChat.onIceCandidate;
|
||||||
VideoChat.peerConnection.onaddstream = VideoChat.onAddStream;
|
VideoChat.peerConnections[uuid].onaddstream = VideoChat.onAddStream;
|
||||||
// Set up listeners on the socket
|
// Set up listeners on the socket
|
||||||
VideoChat.socket.on("candidate", VideoChat.onCandidate);
|
VideoChat.socket.on("candidate", VideoChat.onCandidate);
|
||||||
VideoChat.socket.on("answer", VideoChat.onAnswer);
|
VideoChat.socket.on("answer", VideoChat.onAnswer);
|
||||||
@ -171,12 +172,12 @@ var VideoChat = {
|
|||||||
recieveCaptions(captions)
|
recieveCaptions(captions)
|
||||||
);
|
);
|
||||||
// Called when there is a change in connection state
|
// Called when there is a change in connection state
|
||||||
VideoChat.peerConnection.oniceconnectionstatechange = function (event) {
|
VideoChat.peerConnections[uuid].oniceconnectionstatechange = function (event) {
|
||||||
switch (VideoChat.peerConnection.iceConnectionState) {
|
switch (VideoChat.peerConnections[uuid].iceConnectionState) {
|
||||||
case "connected":
|
case "connected":
|
||||||
logIt("connected");
|
logIt("connected");
|
||||||
// Once connected we no longer have a need for the signaling server, so disconnect
|
// Once connected we no longer have a need for the signaling server, so disconnect
|
||||||
VideoChat.socket.disconnect();
|
// VideoChat.socket.disconnect();
|
||||||
break;
|
break;
|
||||||
case "disconnected":
|
case "disconnected":
|
||||||
logIt("disconnected");
|
logIt("disconnected");
|
||||||
@ -222,26 +223,26 @@ var VideoChat = {
|
|||||||
|
|
||||||
// When receiving a candidate over the socket, turn it back into a real
|
// When receiving a candidate over the socket, turn it back into a real
|
||||||
// RTCIceCandidate and add it to the peerConnection.
|
// RTCIceCandidate and add it to the peerConnection.
|
||||||
onCandidate: function (candidate) {
|
onCandidate: function (candidate, uuid) {
|
||||||
// Update caption text
|
// Update caption text
|
||||||
captionText.text("Found other user... connecting");
|
captionText.text("Found other user... connecting");
|
||||||
rtcCandidate = new RTCIceCandidate(JSON.parse(candidate));
|
rtcCandidate = new RTCIceCandidate(JSON.parse(candidate));
|
||||||
logIt(
|
logIt(
|
||||||
`onCandidate <<< Received remote ICE candidate (${rtcCandidate.address} - ${rtcCandidate.relatedAddress})`
|
`onCandidate <<< Received remote ICE candidate (${rtcCandidate.address} - ${rtcCandidate.relatedAddress})`
|
||||||
);
|
);
|
||||||
VideoChat.peerConnection.addIceCandidate(rtcCandidate);
|
VideoChat.peerConnections[uuid].addIceCandidate(rtcCandidate);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Create an offer that contains the media capabilities of the browser.
|
// Create an offer that contains the media capabilities of the browser.
|
||||||
createOffer: function () {
|
createOffer: function (uuid) {
|
||||||
logIt("createOffer >>> Creating offer...");
|
console.log(">>> Creating offer to UUID: ", uuid, ". my UUID is", VideoChat.socket.id);
|
||||||
VideoChat.peerConnection.createOffer(
|
VideoChat.peerConnections[uuid].createOffer(
|
||||||
function (offer) {
|
function (offer) {
|
||||||
// If the offer is created successfully, set it as the local description
|
// If the offer is created successfully, set it as the local description
|
||||||
// and send it over the socket connection to initiate the peerConnection
|
// and send it over the socket connection to initiate the peerConnection
|
||||||
// on the other side.
|
// on the other side.
|
||||||
VideoChat.peerConnection.setLocalDescription(offer);
|
VideoChat.peerConnections[uuid].setLocalDescription(offer);
|
||||||
VideoChat.socket.emit("offer", JSON.stringify(offer), roomHash);
|
VideoChat.socket.emit("offer", JSON.stringify(offer), roomHash, uuid);
|
||||||
},
|
},
|
||||||
function (err) {
|
function (err) {
|
||||||
logIt("failed offer creation");
|
logIt("failed offer creation");
|
||||||
@ -255,16 +256,16 @@ var VideoChat = {
|
|||||||
// needs to be parsed into an RTCSessionDescription and added as the remote
|
// needs to be parsed into an RTCSessionDescription and added as the remote
|
||||||
// description to the peerConnection object. Then the answer is created in the
|
// description to the peerConnection object. Then the answer is created in the
|
||||||
// same manner as the offer and sent over the socket.
|
// same manner as the offer and sent over the socket.
|
||||||
createAnswer: function (offer) {
|
createAnswer: function (offer, uuid) {
|
||||||
logIt("createAnswer");
|
logIt("createAnswer");
|
||||||
return function () {
|
return function () {
|
||||||
logIt(">>> Creating answer...");
|
|
||||||
rtcOffer = new RTCSessionDescription(JSON.parse(offer));
|
rtcOffer = new RTCSessionDescription(JSON.parse(offer));
|
||||||
VideoChat.peerConnection.setRemoteDescription(rtcOffer);
|
VideoChat.peerConnections[uuid].setRemoteDescription(rtcOffer);
|
||||||
VideoChat.peerConnection.createAnswer(
|
VideoChat.peerConnections[uuid].createAnswer(
|
||||||
function (answer) {
|
function (answer) {
|
||||||
VideoChat.peerConnection.setLocalDescription(answer);
|
VideoChat.peerConnections[uuid].setLocalDescription(answer);
|
||||||
VideoChat.socket.emit("answer", JSON.stringify(answer), roomHash);
|
console.log(">>> Creating answer to UUID: ", uuid, ". my UUID is", VideoChat.socket.id);
|
||||||
|
VideoChat.socket.emit("answer", JSON.stringify(answer), roomHash, uuid);
|
||||||
},
|
},
|
||||||
function (err) {
|
function (err) {
|
||||||
logIt("Failed answer creation.");
|
logIt("Failed answer creation.");
|
||||||
@ -276,26 +277,27 @@ var VideoChat = {
|
|||||||
|
|
||||||
// When a browser receives an offer, set up a callback to be run when the
|
// When a browser receives an offer, set up a callback to be run when the
|
||||||
// ephemeral token is returned from Twilio.
|
// ephemeral token is returned from Twilio.
|
||||||
onOffer: function (offer) {
|
onOffer: function (offer, uuid) {
|
||||||
logIt("onOffer <<< Received offer");
|
logIt("onOffer <<< Received offer");
|
||||||
VideoChat.socket.on(
|
VideoChat.socket.on(
|
||||||
"token",
|
"token",
|
||||||
VideoChat.onToken(VideoChat.createAnswer(offer))
|
VideoChat.onToken(VideoChat.createAnswer(offer, uuid), uuid)
|
||||||
);
|
);
|
||||||
VideoChat.socket.emit("token", roomHash);
|
VideoChat.socket.emit("token", roomHash);
|
||||||
},
|
},
|
||||||
|
|
||||||
// When an answer is received, add it to the peerConnection as the remote description.
|
// When an answer is received, add it to the peerConnection as the remote description.
|
||||||
onAnswer: function (answer) {
|
onAnswer: function (answer, uuid) {
|
||||||
logIt("onAnswer <<< Received answer");
|
console.log("onAnswer <<< Received answer", uuid, ". my UUID is", VideoChat.socket.id);
|
||||||
|
// logIt("onAnswer <<< Received answer" + "");
|
||||||
var rtcAnswer = new RTCSessionDescription(JSON.parse(answer));
|
var rtcAnswer = new RTCSessionDescription(JSON.parse(answer));
|
||||||
// Set remote description of RTCSession
|
// Set remote description of RTCSession
|
||||||
VideoChat.peerConnection.setRemoteDescription(rtcAnswer);
|
VideoChat.peerConnections[uuid].setRemoteDescription(rtcAnswer);
|
||||||
// The caller now knows that the callee is ready to accept new ICE candidates, so sending the buffer over
|
// The caller now knows that the callee is ready to accept new ICE candidates, so sending the buffer over
|
||||||
VideoChat.localICECandidates.forEach((candidate) => {
|
VideoChat.localICECandidates.forEach((candidate) => {
|
||||||
logIt(`>>> Sending local ICE candidate (${candidate.address})`);
|
logIt(`>>> Sending local ICE candidate (${candidate.address})`);
|
||||||
// Send ice candidate over websocket
|
// Send ice candidate over websocket
|
||||||
VideoChat.socket.emit("candidate", JSON.stringify(candidate), roomHash);
|
VideoChat.socket.emit("candidate", JSON.stringify(candidate), roomHash, uuid);
|
||||||
});
|
});
|
||||||
// Reset the buffer of local ICE candidates. This is not really needed, but it's good practice
|
// Reset the buffer of local ICE candidates. This is not really needed, but it's good practice
|
||||||
VideoChat.localICECandidates = [];
|
VideoChat.localICECandidates = [];
|
||||||
@ -303,6 +305,11 @@ var VideoChat = {
|
|||||||
|
|
||||||
// Called when a stream is added to the peer connection
|
// Called when a stream is added to the peer connection
|
||||||
onAddStream: function (event) {
|
onAddStream: function (event) {
|
||||||
|
if(VideoChat.counter > 4) {
|
||||||
|
VideoChat.socket.disconnect();
|
||||||
|
}else{
|
||||||
|
VideoChat.counter++;
|
||||||
|
}
|
||||||
logIt("onAddStream <<< Received new stream from remote. Adding it...");
|
logIt("onAddStream <<< Received new stream from remote. Adding it...");
|
||||||
// Create new remote video source in wrapper
|
// Create new remote video source in wrapper
|
||||||
// Create a <video> node
|
// Create a <video> node
|
||||||
@ -451,7 +458,7 @@ function windowResized() {
|
|||||||
function muteMicrophone() {
|
function muteMicrophone() {
|
||||||
var audioTrack = null;
|
var audioTrack = null;
|
||||||
// Get audio track to mute
|
// Get audio track to mute
|
||||||
VideoChat.peerConnection.getSenders().find(function (s) {
|
VideoChat.peerConnections.first.getSenders().find(function (s) {
|
||||||
if (s.track.kind === "audio") {
|
if (s.track.kind === "audio") {
|
||||||
audioTrack = s.track;
|
audioTrack = s.track;
|
||||||
}
|
}
|
||||||
|
34
server.js
34
server.js
@ -78,16 +78,24 @@ io.on("connection", function (socket) {
|
|||||||
var numClients = typeof clients !== "undefined" ? clients.length : 0;
|
var numClients = typeof clients !== "undefined" ? clients.length : 0;
|
||||||
if (numClients === 0) {
|
if (numClients === 0) {
|
||||||
socket.join(room);
|
socket.join(room);
|
||||||
} else if (numClients === 1) {
|
} else if (numClients < 3) {
|
||||||
socket.join(room);
|
socket.join(room);
|
||||||
// When the client is second to join the room, both clients are ready.
|
logIt("Connected clients", room)
|
||||||
|
for (var clientId in clients.sockets) {
|
||||||
|
logIt('ID: ' + clientId, room);
|
||||||
|
}
|
||||||
|
|
||||||
|
// When the client is not the first to join the room, all clients are ready.
|
||||||
logIt("Broadcasting ready message", room);
|
logIt("Broadcasting ready message", room);
|
||||||
// First to join call initiates call
|
// Existing callers initiates call with user
|
||||||
socket.broadcast.to(room).emit("willInitiateCall", room);
|
socket.broadcast.to(room).emit("willInitiateCall", socket.id, room);
|
||||||
|
|
||||||
|
// Send its uui
|
||||||
|
// socket.emit("uuid", socket.id);
|
||||||
socket.emit("ready", room).to(room);
|
socket.emit("ready", room).to(room);
|
||||||
socket.broadcast.to(room).emit("ready", room);
|
socket.broadcast.to(room).emit("ready", room);
|
||||||
} else {
|
} else {
|
||||||
logIt("room already full", room);
|
logIt("room already full with " + numClients + " people in the room.", room);
|
||||||
socket.emit("full", room);
|
socket.emit("full", room);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -107,21 +115,21 @@ io.on("connection", function (socket) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Relay candidate messages
|
// Relay candidate messages
|
||||||
socket.on("candidate", function (candidate, room) {
|
socket.on("candidate", function (candidate, room, uuid) {
|
||||||
logIt("Received candidate. Broadcasting...", room);
|
logIt("Received candidate. Broadcasting...", room);
|
||||||
socket.broadcast.to(room).emit("candidate", candidate);
|
io.to(uuid).emit("candidate", candidate, socket.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Relay offers
|
// Relay offers
|
||||||
socket.on("offer", function (offer, room) {
|
socket.on("offer", function (offer, room, uuid) {
|
||||||
logIt("Received offer. Broadcasting...", room);
|
logIt("Received offer from " + socket.id + " and emitting to " + uuid, room);
|
||||||
socket.broadcast.to(room).emit("offer", offer);
|
io.to(uuid).emit("offer", offer, socket.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Relay answers
|
// Relay answers
|
||||||
socket.on("answer", function (answer, room) {
|
socket.on("answer", function (answer, room, uuid) {
|
||||||
logIt("Received answer. Broadcasting...", room);
|
logIt("Received answer from " + socket.id + " and emitting to " + uuid, room);
|
||||||
socket.broadcast.to(room).emit("answer", answer);
|
io.to(uuid).emit("answer", answer, socket.id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user