mirror of
https://github.com/ianramzy/decentralized-video-chat.git
synced 2025-02-21 23:45:06 +08:00
fixed onAnswer being called twice by using callbacks
This commit is contained in:
parent
7eb2aab2b5
commit
d272cbc360
@ -37,8 +37,8 @@ var VideoChat = {
|
|||||||
localVideo: document.getElementById("local-video"),
|
localVideo: document.getElementById("local-video"),
|
||||||
peerConnections: {},
|
peerConnections: {},
|
||||||
recognition: undefined,
|
recognition: undefined,
|
||||||
uuid: undefined,
|
answerCreatedUUIDs: [], // HACKY workaround: currently, onAnswer seems to be triggering twice and we don't know why
|
||||||
token: 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
|
||||||
// accepted callback to the onMediaStream function, otherwise callback to the
|
// accepted callback to the onMediaStream function, otherwise callback to the
|
||||||
@ -99,12 +99,18 @@ var VideoChat = {
|
|||||||
VideoChat.socket.emit("join", roomHash);
|
VideoChat.socket.emit("join", roomHash);
|
||||||
// Receive its own uuid
|
// Receive its own uuid
|
||||||
VideoChat.socket.on("uuid", (uuid) => (VideoChat.uuid = uuid));
|
VideoChat.socket.on("uuid", (uuid) => (VideoChat.uuid = uuid));
|
||||||
VideoChat.socket.on("token", (token) => (VideoChat.token = token));
|
|
||||||
// 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("willInitiateCall", VideoChat.call)
|
VideoChat.socket.on("willInitiateCall", VideoChat.call);
|
||||||
|
// Set up listeners on the socket
|
||||||
|
VideoChat.socket.on("candidate", VideoChat.onCandidate);
|
||||||
|
VideoChat.socket.on("answer", VideoChat.onAnswer);
|
||||||
|
VideoChat.socket.on("requestToggleCaptions", () => toggleSendCaptions());
|
||||||
|
VideoChat.socket.on("recieveCaptions", (captions) =>
|
||||||
|
recieveCaptions(captions)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
// When we are ready to call, enable the Call button.
|
// When we are ready to call, enable the Call button.
|
||||||
@ -118,15 +124,20 @@ var VideoChat = {
|
|||||||
|
|
||||||
// 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 (uuid) {
|
startCall: function (uuid) {
|
||||||
VideoChat.establishConnection(uuid);
|
VideoChat.socket.on("token", VideoChat.establishConnection(uuid, function(a) {VideoChat.createOffer(a);}));
|
||||||
VideoChat.createOffer(uuid);
|
VideoChat.socket.emit("token", roomHash, uuid);
|
||||||
|
|
||||||
},
|
},
|
||||||
establishConnection: function (uuid) {
|
|
||||||
|
establishConnection: function (correctUuid, callback) {
|
||||||
|
return function(token, uuid) {
|
||||||
|
if (correctUuid != uuid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
console.log("establishing connection to", uuid);
|
console.log("establishing connection to", uuid);
|
||||||
// Set up a new RTCPeerConnection using the token's iceServers.
|
// Set up a new RTCPeerConnection using the token's iceServers.
|
||||||
|
console.log(VideoChat.peerConnections)
|
||||||
VideoChat.peerConnections[uuid] = new RTCPeerConnection({
|
VideoChat.peerConnections[uuid] = new RTCPeerConnection({
|
||||||
iceServers: VideoChat.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) {
|
||||||
@ -164,13 +175,6 @@ var VideoChat = {
|
|||||||
VideoChat.peerConnections[uuid].onicecandidate = VideoChat.onIceCandidate;
|
VideoChat.peerConnections[uuid].onicecandidate = VideoChat.onIceCandidate;
|
||||||
VideoChat.peerConnections[uuid].onaddstream = VideoChat.onAddStream;
|
VideoChat.peerConnections[uuid].onaddstream = VideoChat.onAddStream;
|
||||||
|
|
||||||
// Set up listeners on the socket
|
|
||||||
VideoChat.socket.on("candidate", VideoChat.onCandidate);
|
|
||||||
VideoChat.socket.on("answer", VideoChat.onAnswer);
|
|
||||||
VideoChat.socket.on("requestToggleCaptions", () => toggleSendCaptions());
|
|
||||||
VideoChat.socket.on("recieveCaptions", (captions) =>
|
|
||||||
recieveCaptions(captions)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Called when there is a change in connection state
|
// Called when there is a change in connection state
|
||||||
VideoChat.peerConnections[uuid].oniceconnectionstatechange = function (event) {
|
VideoChat.peerConnections[uuid].oniceconnectionstatechange = function (event) {
|
||||||
@ -195,85 +199,10 @@ var VideoChat = {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
callback(uuid);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// When we receive the ephemeral token back from the server.
|
|
||||||
// onToken: function (callback) {
|
|
||||||
// logIt("onToken");
|
|
||||||
// return function (token, uuid) {
|
|
||||||
// logIt("<<< Received token");
|
|
||||||
// console.log(token, uuid);
|
|
||||||
// // Set up a new RTCPeerConnection using the token's iceServers.
|
|
||||||
// VideoChat.peerConnections[uuid] = new RTCPeerConnection({
|
|
||||||
// iceServers: token.iceServers,
|
|
||||||
// });
|
|
||||||
// // Add the local video stream to the peerConnection.
|
|
||||||
// VideoChat.localStream.getTracks().forEach(function (track) {
|
|
||||||
// VideoChat.peerConnections[uuid].addTrack(track, VideoChat.localStream);
|
|
||||||
// });
|
|
||||||
// // Add general purpose data channel to peer connection,
|
|
||||||
// // used for text chats, captions, and toggling sending captions
|
|
||||||
// dataChanel = VideoChat.peerConnections[uuid].createDataChannel("chat", {
|
|
||||||
// negotiated: true,
|
|
||||||
// // both peers must have same id
|
|
||||||
// id: 0,
|
|
||||||
// });
|
|
||||||
// // Called when dataChannel is successfully opened
|
|
||||||
// dataChanel.onopen = function (event) {
|
|
||||||
// logIt("dataChannel opened");
|
|
||||||
// };
|
|
||||||
// // Handle different dataChannel types
|
|
||||||
// dataChanel.onmessage = function (event) {
|
|
||||||
// const receivedData = event.data;
|
|
||||||
// // First 4 chars represent data type
|
|
||||||
// const dataType = receivedData.substring(0, 4);
|
|
||||||
// const cleanedMessage = receivedData.slice(4);
|
|
||||||
// if (dataType === "mes:") {
|
|
||||||
// handleRecieveMessage(cleanedMessage);
|
|
||||||
// } else if (dataType === "cap:") {
|
|
||||||
// recieveCaptions(cleanedMessage);
|
|
||||||
// } else if (dataType === "tog:") {
|
|
||||||
// toggleSendCaptions();
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// // Set up callbacks for the connection generating iceCandidates or
|
|
||||||
// // receiving the remote media stream.
|
|
||||||
// VideoChat.peerConnections[uuid].onicecandidate = VideoChat.onIceCandidate;
|
|
||||||
// VideoChat.peerConnections[uuid].onaddstream = VideoChat.onAddStream;
|
|
||||||
// // Set up listeners on the socket
|
|
||||||
// VideoChat.socket.on("candidate", VideoChat.onCandidate);
|
|
||||||
// VideoChat.socket.on("answer", VideoChat.onAnswer);
|
|
||||||
// VideoChat.socket.on("requestToggleCaptions", () => toggleSendCaptions());
|
|
||||||
// VideoChat.socket.on("recieveCaptions", (captions) =>
|
|
||||||
// recieveCaptions(captions)
|
|
||||||
// );
|
|
||||||
// // Called when there is a change in connection state
|
|
||||||
// VideoChat.peerConnections[uuid].oniceconnectionstatechange = function (event) {
|
|
||||||
// switch (VideoChat.peerConnections[uuid].iceConnectionState) {
|
|
||||||
// case "connected":
|
|
||||||
// logIt("connected");
|
|
||||||
// // Once connected we no longer have a need for the signaling server, so disconnect
|
|
||||||
// VideoChat.socket.off("token");
|
|
||||||
// VideoChat.socket.off("offer");
|
|
||||||
// break;
|
|
||||||
// case "disconnected":
|
|
||||||
// logIt("disconnected");
|
|
||||||
// case "failed":
|
|
||||||
// logIt("failed");
|
|
||||||
// // VideoChat.socket.connect
|
|
||||||
// // VideoChat.createOffer();
|
|
||||||
// // Refresh page if connection has failed
|
|
||||||
// location.reload();
|
|
||||||
// break;
|
|
||||||
// case "closed":
|
|
||||||
// logIt("closed");
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// callback();
|
|
||||||
// };
|
|
||||||
// },
|
|
||||||
|
|
||||||
// When the peerConnection generates an ice candidate, send it over the socket to the peer.
|
// When the peerConnection generates an ice candidate, send it over the socket to the peer.
|
||||||
onIceCandidate: function (event) {
|
onIceCandidate: function (event) {
|
||||||
logIt("onIceCandidate");
|
logIt("onIceCandidate");
|
||||||
@ -336,6 +265,7 @@ var VideoChat = {
|
|||||||
createAnswer: function (offer, uuid) {
|
createAnswer: function (offer, uuid) {
|
||||||
logIt("createAnswer");
|
logIt("createAnswer");
|
||||||
rtcOffer = new RTCSessionDescription(JSON.parse(offer));
|
rtcOffer = new RTCSessionDescription(JSON.parse(offer));
|
||||||
|
console.log("createAnswer: setting remote description of " + uuid + " on " + VideoChat.socket.id);
|
||||||
VideoChat.peerConnections[uuid].setRemoteDescription(rtcOffer);
|
VideoChat.peerConnections[uuid].setRemoteDescription(rtcOffer);
|
||||||
VideoChat.peerConnections[uuid].createAnswer(
|
VideoChat.peerConnections[uuid].createAnswer(
|
||||||
function (answer) {
|
function (answer) {
|
||||||
@ -354,16 +284,21 @@ var VideoChat = {
|
|||||||
// ephemeral token is returned from Twilio.
|
// ephemeral token is returned from Twilio.
|
||||||
onOffer: function (offer, uuid) {
|
onOffer: function (offer, uuid) {
|
||||||
logIt("onOffer <<< Received offer");
|
logIt("onOffer <<< Received offer");
|
||||||
VideoChat.establishConnection(uuid);
|
// VideoChat.socket.on("token", VideoChat.establishConnection(uuid, function(a) {VideoChat.createOffer(a);}));
|
||||||
VideoChat.createAnswer(offer, uuid);
|
VideoChat.socket.on("token", VideoChat.establishConnection(uuid, function(a) {VideoChat.createAnswer(offer, a);}));
|
||||||
|
VideoChat.socket.emit("token", roomHash, uuid);
|
||||||
},
|
},
|
||||||
|
|
||||||
// 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, uuid) {
|
onAnswer: function (answer, uuid) {
|
||||||
console.log("onAnswer <<< Received answer", uuid, ". my UUID is", VideoChat.socket.id);
|
console.log("onAnswer <<< Received answer", uuid, ". my UUID is", VideoChat.socket.id);
|
||||||
|
|
||||||
|
// if (!VideoChat.answerCreatedUUIDs.includes(uuid)) {
|
||||||
|
VideoChat.answerCreatedUUIDs.push(uuid);
|
||||||
// logIt("onAnswer <<< Received answer" + "");
|
// 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
|
||||||
|
console.log("onAnswer: setting remote description of " + uuid + " on " + VideoChat.socket.id);
|
||||||
VideoChat.peerConnections[uuid].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) => {
|
||||||
@ -373,6 +308,11 @@ var VideoChat = {
|
|||||||
});
|
});
|
||||||
// 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 = [];
|
||||||
|
// } else {
|
||||||
|
// console.log("attemped to run onAnswer on UUID ", uuid, " which already happened");
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Called when a stream is added to the peer connection
|
// Called when a stream is added to the peer connection
|
||||||
|
14
server.js
14
server.js
@ -96,17 +96,7 @@ io.on("connection", function (socket) {
|
|||||||
|
|
||||||
// When the client is not the first to join the room, all clients are ready.
|
// 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);
|
||||||
|
|
||||||
twilio.tokens.create(function (err, response) {
|
|
||||||
if (err) {
|
|
||||||
logIt(err, room);
|
|
||||||
} else {
|
|
||||||
logIt("Token generated. Returning it to the browser client", room);
|
|
||||||
socket.emit("token", response);
|
|
||||||
// Existing callers initiates call with user
|
|
||||||
socket.broadcast.to(room).emit("willInitiateCall", socket.id, room);
|
socket.broadcast.to(room).emit("willInitiateCall", socket.id, room);
|
||||||
}
|
|
||||||
});
|
|
||||||
// socket.emit("uuid", socket.id);
|
// 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);
|
||||||
@ -118,14 +108,14 @@ io.on("connection", function (socket) {
|
|||||||
|
|
||||||
// When receiving the token message, use the Twilio REST API to request an
|
// When receiving the token message, use the Twilio REST API to request an
|
||||||
// token to get ephemeral credentials to use the TURN server.
|
// token to get ephemeral credentials to use the TURN server.
|
||||||
socket.on("token", function (room) {
|
socket.on("token", function (room, uuid) {
|
||||||
logIt("Received token request", room);
|
logIt("Received token request", room);
|
||||||
twilio.tokens.create(function (err, response) {
|
twilio.tokens.create(function (err, response) {
|
||||||
if (err) {
|
if (err) {
|
||||||
logIt(err, room);
|
logIt(err, room);
|
||||||
} else {
|
} else {
|
||||||
logIt("Token generated. Returning it to the browser client", room);
|
logIt("Token generated. Returning it to the browser client", room);
|
||||||
socket.emit("token", response);
|
socket.emit("token", response, uuid);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user