mirror of
https://github.com/ianramzy/decentralized-video-chat.git
synced 2025-02-20 23:15:01 +08:00
commit
f392a13b56
@ -1,7 +1,6 @@
|
|||||||
// Vars
|
// Vars
|
||||||
var isMuted;
|
var isMuted;
|
||||||
var videoIsPaused;
|
var videoIsPaused;
|
||||||
var dataChanel = null;
|
|
||||||
const browserName = getBrowserName();
|
const browserName = getBrowserName();
|
||||||
const url = window.location.href;
|
const url = window.location.href;
|
||||||
const roomHash = url.substring(url.lastIndexOf("/") + 1).toLowerCase();
|
const roomHash = url.substring(url.lastIndexOf("/") + 1).toLowerCase();
|
||||||
@ -27,13 +26,18 @@ const captionButtontext = $("#caption-button-text");
|
|||||||
const entireChat = $("#entire-chat");
|
const entireChat = $("#entire-chat");
|
||||||
const chatZone = $("#chat-zone");
|
const chatZone = $("#chat-zone");
|
||||||
|
|
||||||
|
var dataChannel = new Map();
|
||||||
|
|
||||||
var VideoChat = {
|
var VideoChat = {
|
||||||
connected: [],
|
nickname: undefined,
|
||||||
|
videoEnabled: true,
|
||||||
|
audioEnabled: true,
|
||||||
|
connected: new Map(),
|
||||||
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: {},
|
peerConnections: new Map(),
|
||||||
recognition: undefined,
|
recognition: undefined,
|
||||||
|
|
||||||
// Call to getUserMedia (provided by adapter.js for cross browser compatibility)
|
// Call to getUserMedia (provided by adapter.js for cross browser compatibility)
|
||||||
@ -91,6 +95,16 @@ var VideoChat = {
|
|||||||
Snackbar.close();
|
Snackbar.close();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
VideoChat.nickname = prompt("Please enter a nickname", "");
|
||||||
|
|
||||||
|
while (VideoChat.nickname == null || VideoChat.nickname.trim() === "") {
|
||||||
|
VideoChat.nickname = prompt(
|
||||||
|
"Nickname cannot be empty. Please enter a nickname",
|
||||||
|
""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
@ -107,7 +121,6 @@ var VideoChat = {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
call: function (uuid, room) {
|
call: function (uuid, room) {
|
||||||
logIt("Initiating call with " + uuid);
|
logIt("Initiating call with " + uuid);
|
||||||
VideoChat.socket.on(
|
VideoChat.socket.on(
|
||||||
@ -127,29 +140,36 @@ var VideoChat = {
|
|||||||
console.log("establishing connection to", uuid);
|
console.log("establishing connection to", uuid);
|
||||||
// Initialise localICEcandidates for node uuid with empty array
|
// Initialise localICEcandidates for node uuid with empty array
|
||||||
VideoChat.localICECandidates[uuid] = [];
|
VideoChat.localICECandidates[uuid] = [];
|
||||||
VideoChat.connected[uuid] = false;
|
VideoChat.connected.set(uuid, false);
|
||||||
|
|
||||||
// Set up a new RTCPeerConnection using the token's iceServers.
|
// Set up a new RTCPeerConnection using the token's iceServers.
|
||||||
VideoChat.peerConnections[uuid] = new RTCPeerConnection({
|
VideoChat.peerConnections.set(
|
||||||
iceServers: token.iceServers,
|
uuid,
|
||||||
});
|
new RTCPeerConnection({
|
||||||
|
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.peerConnections[uuid].addTrack(track, VideoChat.localStream);
|
VideoChat.peerConnections
|
||||||
|
.get(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.peerConnections[uuid].createDataChannel("chat", {
|
dataChannel.set(
|
||||||
negotiated: true,
|
uuid,
|
||||||
// both peers must have same id
|
VideoChat.peerConnections.get(uuid).createDataChannel("chat", {
|
||||||
id: 0,
|
negotiated: true,
|
||||||
});
|
// both peers must have same id
|
||||||
|
id: 0,
|
||||||
|
})
|
||||||
|
);
|
||||||
// Called when dataChannel is successfully opened
|
// Called when dataChannel is successfully opened
|
||||||
dataChanel.onopen = function (event) {
|
dataChannel.get(uuid).onopen = function (event) {
|
||||||
logIt("dataChannel opened");
|
logIt("dataChannel opened");
|
||||||
};
|
};
|
||||||
// Handle different dataChannel types
|
// Handle different dataChannel types
|
||||||
dataChanel.onmessage = function (event) {
|
dataChannel.get(uuid).onmessage = function (event) {
|
||||||
const receivedData = event.data;
|
const receivedData = event.data;
|
||||||
// First 4 chars represent data type
|
// First 4 chars represent data type
|
||||||
const dataType = receivedData.substring(0, 4);
|
const dataType = receivedData.substring(0, 4);
|
||||||
@ -165,18 +185,18 @@ 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.peerConnections[uuid].onicecandidate = function (u) {
|
VideoChat.peerConnections.get(uuid).onicecandidate = function (u) {
|
||||||
VideoChat.onIceCandidate(u, uuid);
|
VideoChat.onIceCandidate(u, uuid);
|
||||||
};
|
};
|
||||||
VideoChat.peerConnections[uuid].onaddstream = function (u) {
|
VideoChat.peerConnections.get(uuid).onaddstream = function (u) {
|
||||||
VideoChat.onAddStream(u, uuid);
|
VideoChat.onAddStream(u, uuid);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Called when there is a change in connection state
|
// Called when there is a change in connection state
|
||||||
VideoChat.peerConnections[uuid].oniceconnectionstatechange = function (
|
VideoChat.peerConnections.get(
|
||||||
event
|
uuid
|
||||||
) {
|
).oniceconnectionstatechange = function (event) {
|
||||||
switch (VideoChat.peerConnections[uuid].iceConnectionState) {
|
switch (VideoChat.peerConnections.get(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
|
||||||
@ -206,7 +226,7 @@ var VideoChat = {
|
|||||||
logIt(
|
logIt(
|
||||||
`<<< Received local ICE candidate from STUN/TURN server (${event.candidate.address}) associated with UUID (${uuid})`
|
`<<< Received local ICE candidate from STUN/TURN server (${event.candidate.address}) associated with UUID (${uuid})`
|
||||||
);
|
);
|
||||||
if (VideoChat.connected[uuid]) {
|
if (VideoChat.connected.get(uuid)) {
|
||||||
logIt(`>>> Sending local ICE candidate (${event.candidate.address})`);
|
logIt(`>>> Sending local ICE candidate (${event.candidate.address})`);
|
||||||
VideoChat.socket.emit(
|
VideoChat.socket.emit(
|
||||||
"candidate",
|
"candidate",
|
||||||
@ -233,18 +253,18 @@ var VideoChat = {
|
|||||||
logIt(
|
logIt(
|
||||||
`onCandidate <<< Received remote ICE candidate (${rtcCandidate.address} - ${rtcCandidate.relatedAddress})`
|
`onCandidate <<< Received remote ICE candidate (${rtcCandidate.address} - ${rtcCandidate.relatedAddress})`
|
||||||
);
|
);
|
||||||
VideoChat.peerConnections[uuid].addIceCandidate(rtcCandidate);
|
VideoChat.peerConnections.get(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 (uuid) {
|
createOffer: function (uuid) {
|
||||||
logIt(`createOffer to ${uuid} >>> Creating offer...`);
|
logIt(`createOffer to ${uuid} >>> Creating offer...`);
|
||||||
VideoChat.peerConnections[uuid].createOffer(
|
VideoChat.peerConnections.get(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.peerConnections[uuid].setLocalDescription(offer);
|
VideoChat.peerConnections.get(uuid).setLocalDescription(offer);
|
||||||
VideoChat.socket.emit("offer", JSON.stringify(offer), roomHash, uuid);
|
VideoChat.socket.emit("offer", JSON.stringify(offer), roomHash, uuid);
|
||||||
},
|
},
|
||||||
function (err) {
|
function (err) {
|
||||||
@ -263,10 +283,10 @@ var VideoChat = {
|
|||||||
logIt("createAnswer");
|
logIt("createAnswer");
|
||||||
rtcOffer = new RTCSessionDescription(JSON.parse(offer));
|
rtcOffer = new RTCSessionDescription(JSON.parse(offer));
|
||||||
logIt(`>>> Creating answer to ${uuid}`);
|
logIt(`>>> Creating answer to ${uuid}`);
|
||||||
VideoChat.peerConnections[uuid].setRemoteDescription(rtcOffer);
|
VideoChat.peerConnections.get(uuid).setRemoteDescription(rtcOffer);
|
||||||
VideoChat.peerConnections[uuid].createAnswer(
|
VideoChat.peerConnections.get(uuid).createAnswer(
|
||||||
function (answer) {
|
function (answer) {
|
||||||
VideoChat.peerConnections[uuid].setLocalDescription(answer);
|
VideoChat.peerConnections.get(uuid).setLocalDescription(answer);
|
||||||
VideoChat.socket.emit("answer", JSON.stringify(answer), roomHash, uuid);
|
VideoChat.socket.emit("answer", JSON.stringify(answer), roomHash, uuid);
|
||||||
},
|
},
|
||||||
function (err) {
|
function (err) {
|
||||||
@ -295,7 +315,7 @@ var VideoChat = {
|
|||||||
logIt(`onAnswer <<< Received answer from ${uuid}`);
|
logIt(`onAnswer <<< Received answer from ${uuid}`);
|
||||||
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.peerConnections[uuid].setRemoteDescription(rtcAnswer);
|
VideoChat.peerConnections.get(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[uuid].forEach((candidate) => {
|
VideoChat.localICECandidates[uuid].forEach((candidate) => {
|
||||||
logIt(`>>> Sending local ICE candidate (${candidate.address})`);
|
logIt(`>>> Sending local ICE candidate (${candidate.address})`);
|
||||||
@ -311,8 +331,7 @@ 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, uuid) {
|
onAddStream: function (event, uuid) {
|
||||||
logIt(
|
logIt("onAddStream <<< Received new stream from remote. Adding it...");
|
||||||
"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
|
||||||
var node = document.createElement("video");
|
var node = document.createElement("video");
|
||||||
@ -327,7 +346,7 @@ var VideoChat = {
|
|||||||
// Remove the loading gif from video
|
// Remove the loading gif from video
|
||||||
VideoChat.remoteVideoWrapper.lastChild.style.background = "none";
|
VideoChat.remoteVideoWrapper.lastChild.style.background = "none";
|
||||||
// Update connection status
|
// Update connection status
|
||||||
VideoChat.connected[uuid] = true;
|
VideoChat.connected.set(uuid, true);
|
||||||
// Hide caption status text
|
// Hide caption status text
|
||||||
captionText.fadeOut();
|
captionText.fadeOut();
|
||||||
// Reposition local video after a second, as there is often a delay
|
// Reposition local video after a second, as there is often a delay
|
||||||
@ -411,6 +430,27 @@ function windowResized() {
|
|||||||
rePositionCaptions();
|
rePositionCaptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checks if connected to at least one peer
|
||||||
|
function isConnected() {
|
||||||
|
var connected = false;
|
||||||
|
|
||||||
|
// No way to 'break' forEach -> we go through all anyway
|
||||||
|
VideoChat.connected.forEach(function (value, key, map) {
|
||||||
|
if (value) {
|
||||||
|
connected = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendToAllDataChannels(message) {
|
||||||
|
// key is UUID, value is dataChannel object
|
||||||
|
dataChannel.forEach(function (value, key, map) {
|
||||||
|
value.send(message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Fullscreen
|
// Fullscreen
|
||||||
// function openFullscreen() {
|
// function openFullscreen() {
|
||||||
// try {
|
// try {
|
||||||
@ -458,21 +498,23 @@ function windowResized() {
|
|||||||
|
|
||||||
// Mute microphone
|
// Mute microphone
|
||||||
function muteMicrophone() {
|
function muteMicrophone() {
|
||||||
|
VideoChat.audioEnabled = !VideoChat.audioEnabled;
|
||||||
var audioTrack = null;
|
var audioTrack = null;
|
||||||
// Get audio track to mute
|
|
||||||
VideoChat.peerConnections.first.getSenders().find(function (s) {
|
VideoChat.peerConnections.forEach(function (value, key, map) {
|
||||||
if (s.track.kind === "audio") {
|
value.getSenders().find(function (s) {
|
||||||
audioTrack = s.track;
|
if (s.track.kind === "audio") {
|
||||||
}
|
audioTrack = s.track;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
audioTrack.enabled = VideoChat.audioEnabled;
|
||||||
});
|
});
|
||||||
isMuted = !audioTrack.enabled;
|
|
||||||
audioTrack.enabled = isMuted;
|
|
||||||
isMuted = !isMuted;
|
|
||||||
// select mic button and mic button text
|
// select mic button and mic button text
|
||||||
const micButtonIcon = document.getElementById("mic-icon");
|
const micButtonIcon = document.getElementById("mic-icon");
|
||||||
const micButtonText = document.getElementById("mic-text");
|
const micButtonText = document.getElementById("mic-text");
|
||||||
// Update mute button text and icon
|
// Update mute button text and icon
|
||||||
if (isMuted) {
|
if (!VideoChat.audioEnabled) {
|
||||||
micButtonIcon.classList.remove("fa-microphone");
|
micButtonIcon.classList.remove("fa-microphone");
|
||||||
micButtonIcon.classList.add("fa-microphone-slash");
|
micButtonIcon.classList.add("fa-microphone-slash");
|
||||||
micButtonText.innerText = "Unmute";
|
micButtonText.innerText = "Unmute";
|
||||||
@ -486,21 +528,25 @@ function muteMicrophone() {
|
|||||||
|
|
||||||
// Pause Video
|
// Pause Video
|
||||||
function pauseVideo() {
|
function pauseVideo() {
|
||||||
var videoTrack = null;
|
VideoChat.videoEnabled = !VideoChat.videoEnabled;
|
||||||
// Get video track to pause
|
|
||||||
VideoChat.peerConnection.getSenders().find(function (s) {
|
// Communicate pause to all the peers' video tracks
|
||||||
if (s.track.kind === "video") {
|
VideoChat.peerConnections.forEach(function (value, key, map) {
|
||||||
videoTrack = s.track;
|
console.log("pausing video for ", key);
|
||||||
}
|
value.getSenders().find(function (s) {
|
||||||
|
if (s.track.kind === "video") {
|
||||||
|
console.log("found video track");
|
||||||
|
videoTrack = s.track;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
videoTrack.enabled = VideoChat.videoEnabled;
|
||||||
});
|
});
|
||||||
videoIsPaused = !videoTrack.enabled;
|
|
||||||
videoTrack.enabled = videoIsPaused;
|
|
||||||
videoIsPaused = !videoIsPaused;
|
|
||||||
// select video button and video button text
|
// select video button and video button text
|
||||||
const videoButtonIcon = document.getElementById("video-icon");
|
const videoButtonIcon = document.getElementById("video-icon");
|
||||||
const videoButtonText = document.getElementById("video-text");
|
const videoButtonText = document.getElementById("video-text");
|
||||||
// update pause button icon and text
|
// update pause button icon and text
|
||||||
if (videoIsPaused) {
|
if (!VideoChat.videoEnabled) {
|
||||||
localVideoText.text("Video is paused");
|
localVideoText.text("Video is paused");
|
||||||
localVideoText.show();
|
localVideoText.show();
|
||||||
videoButtonIcon.classList.remove("fa-video");
|
videoButtonIcon.classList.remove("fa-video");
|
||||||
@ -518,11 +564,12 @@ function pauseVideo() {
|
|||||||
|
|
||||||
// Swap camera / screen share
|
// Swap camera / screen share
|
||||||
function swap() {
|
function swap() {
|
||||||
// Handle swap video before video call is connected
|
// Handle swap video before video call is connected by checking that there's at least one peer connected
|
||||||
if (!VideoChat.connected) {
|
if (!isConnected()) {
|
||||||
alert("You must join a call before you can share your screen.");
|
alert("You must join a call before you can share your screen.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store swap button icon and text
|
// Store swap button icon and text
|
||||||
const swapIcon = document.getElementById("swap-icon");
|
const swapIcon = document.getElementById("swap-icon");
|
||||||
const swapText = document.getElementById("swap-text");
|
const swapText = document.getElementById("swap-text");
|
||||||
@ -590,21 +637,27 @@ function switchStreamHelper(stream) {
|
|||||||
videoTrack.onended = function () {
|
videoTrack.onended = function () {
|
||||||
swap();
|
swap();
|
||||||
};
|
};
|
||||||
if (VideoChat.connected) {
|
|
||||||
// Find sender
|
// Swap video for every peer connection
|
||||||
const sender = VideoChat.peerConnection.getSenders().find(function (s) {
|
VideoChat.connected.forEach(function (value, key, map) {
|
||||||
// make sure tack types match
|
// Just to be safe, check if connected before swapping video channel
|
||||||
return s.track.kind === videoTrack.kind;
|
if (VideoChat.connected.get(key)) {
|
||||||
});
|
const sender = VideoChat.peerConnections
|
||||||
// Replace sender track
|
.get(key)
|
||||||
sender.replaceTrack(videoTrack);
|
.getSenders()
|
||||||
}
|
.find(function (s) {
|
||||||
|
return s.track.kind === videoTrack.kind;
|
||||||
|
});
|
||||||
|
sender.replaceTrack(videoTrack);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Update local video stream
|
// Update local video stream
|
||||||
VideoChat.localStream = videoTrack;
|
VideoChat.localStream = videoTrack;
|
||||||
// Update local video object
|
// Update local video object
|
||||||
VideoChat.localVideo.srcObject = stream;
|
VideoChat.localVideo.srcObject = stream;
|
||||||
// Unpause video on swap
|
// Unpause video on swap
|
||||||
if (videoIsPaused) {
|
if (!VideoChat.videoEnabled) {
|
||||||
pauseVideo();
|
pauseVideo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -614,7 +667,7 @@ function switchStreamHelper(stream) {
|
|||||||
// Request captions from other user, toggles state
|
// Request captions from other user, toggles state
|
||||||
function requestToggleCaptions() {
|
function requestToggleCaptions() {
|
||||||
// Handle requesting captions before connected
|
// Handle requesting captions before connected
|
||||||
if (!VideoChat.connected) {
|
if (!isConnected()) {
|
||||||
alert("You must be connected to a peer to use Live Caption");
|
alert("You must be connected to a peer to use Live Caption");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -635,7 +688,7 @@ function requestToggleCaptions() {
|
|||||||
receivingCaptions = true;
|
receivingCaptions = true;
|
||||||
}
|
}
|
||||||
// Send request to get captions over data channel
|
// Send request to get captions over data channel
|
||||||
dataChanel.send("tog:");
|
sendToAllDataChannels("tog:");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start/stop sending captions to other user
|
// Start/stop sending captions to other user
|
||||||
@ -661,7 +714,7 @@ function startSpeech() {
|
|||||||
logIt(e);
|
logIt(e);
|
||||||
logIt("error importing speech library");
|
logIt("error importing speech library");
|
||||||
// Alert other user that they cannon use live caption
|
// Alert other user that they cannon use live caption
|
||||||
dataChanel.send("cap:notusingchrome");
|
sendToAllDataChannels("cap:notusingchrome");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// recognition.maxAlternatives = 3;
|
// recognition.maxAlternatives = 3;
|
||||||
@ -673,6 +726,7 @@ function startSpeech() {
|
|||||||
let interimTranscript = "";
|
let interimTranscript = "";
|
||||||
for (let i = event.resultIndex, len = event.results.length; i < len; i++) {
|
for (let i = event.resultIndex, len = event.results.length; i < len; i++) {
|
||||||
var transcript = event.results[i][0].transcript;
|
var transcript = event.results[i][0].transcript;
|
||||||
|
console.log(transcript);
|
||||||
if (event.results[i].isFinal) {
|
if (event.results[i].isFinal) {
|
||||||
finalTranscript += transcript;
|
finalTranscript += transcript;
|
||||||
} else {
|
} else {
|
||||||
@ -680,7 +734,7 @@ function startSpeech() {
|
|||||||
var charsToKeep = interimTranscript.length % 100;
|
var charsToKeep = interimTranscript.length % 100;
|
||||||
// Send captions over data chanel,
|
// Send captions over data chanel,
|
||||||
// subtracting as many complete 100 char slices from start
|
// subtracting as many complete 100 char slices from start
|
||||||
dataChanel.send(
|
sendToAllDataChannels(
|
||||||
"cap:" +
|
"cap:" +
|
||||||
interimTranscript.substring(interimTranscript.length - charsToKeep)
|
interimTranscript.substring(interimTranscript.length - charsToKeep)
|
||||||
);
|
);
|
||||||
@ -757,6 +811,7 @@ function recieveCaptions(captions) {
|
|||||||
// Text Chat
|
// Text Chat
|
||||||
// Add text message to chat screen on page
|
// Add text message to chat screen on page
|
||||||
function addMessageToScreen(msg, isOwnMessage) {
|
function addMessageToScreen(msg, isOwnMessage) {
|
||||||
|
// If nickname is undefined or null, user didn't input a nickname
|
||||||
if (isOwnMessage) {
|
if (isOwnMessage) {
|
||||||
$(".chat-messages").append(
|
$(".chat-messages").append(
|
||||||
'<div class="message-item customer cssanimation fadeInBottom"><div class="message-bloc"><div class="message">' +
|
'<div class="message-item customer cssanimation fadeInBottom"><div class="message-bloc"><div class="message">' +
|
||||||
@ -783,7 +838,7 @@ chatInput.addEventListener("keypress", function (event) {
|
|||||||
// Make links clickable
|
// Make links clickable
|
||||||
msg = msg.autoLink();
|
msg = msg.autoLink();
|
||||||
// Send message over data channel
|
// Send message over data channel
|
||||||
dataChanel.send("mes:" + msg);
|
sendToAllDataChannels("mes:" + VideoChat.nickname + ": " + msg);
|
||||||
// Add message to screen
|
// Add message to screen
|
||||||
addMessageToScreen(msg, true);
|
addMessageToScreen(msg, true);
|
||||||
// Auto scroll chat down
|
// Auto scroll chat down
|
||||||
|
Loading…
x
Reference in New Issue
Block a user