Merge pull request #7 from questo-ai/fixes

Downscaling send resolution when number of nodes in call is >3
This commit is contained in:
Arya Vohra 2020-06-02 11:38:08 +08:00 committed by GitHub
commit fc1b1dc460
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 72 additions and 27 deletions

2
public/css/chat.css vendored
View File

@ -145,7 +145,7 @@ a {
padding: 10px;
}
#remote-video:first-child:nth-last-child(1) {
/* -or- li:only-child { */
/* -or- li:only-child { */
max-height: 80vh;
}

View File

@ -204,7 +204,9 @@ var VideoChat = {
break;
case "disconnected":
logIt("disconnected - UUID " + uuid);
VideoChat.remoteVideoWrapper.removeChild(document.querySelectorAll(`[uuid="${uuid}"]`)[0]);
VideoChat.remoteVideoWrapper.removeChild(
document.querySelectorAll(`[uuid="${uuid}"]`)[0]
);
VideoChat.connected.delete(uuid);
VideoChat.peerConnections.delete(uuid);
dataChannel.delete(uuid);
@ -361,6 +363,12 @@ var VideoChat = {
VideoChat.connected.set(uuid, true);
// Hide caption status text
captionText.fadeOut();
// Downscale send resolution and bitrate if num in room > 4
if (VideoChat.peerConnections.size > 3) {
VideoChat.peerConnections.forEach(function (value, key, map) {
downscaleStream(value);
});
}
// Reposition local video after a second, as there is often a delay
// between adding a stream and the height of the video div changing
setTimeout(() => rePositionLocalVideo(), 500);
@ -499,6 +507,32 @@ function sendToAllDataChannels(message) {
// }
// End Fullscreen
// Downscale single stream
async function downscaleStream(pc, applying = false) {
height = 240;
rate = 800000;
if (applying) return;
try {
applying = true;
do {
h = height;
const sender = pc.getSenders().find(function (s) {
return s.track.kind === "video";
});
const ratio = sender.track.getSettings().height / height;
const params = sender.getParameters();
if (!params.encodings) params.encodings = [{}]; // Firefox workaround!
params.encodings[0].scaleResolutionDownBy = Math.max(ratio, 1);
params.encodings[0].maxBitrate = rate;
await sender.setParameters(params);
} while (h != height);
} catch (e) {
logIt(e);
} finally {
applying = false;
}
}
// Mute microphone
function muteMicrophone() {
var audioTrack = null;
@ -511,7 +545,7 @@ function muteMicrophone() {
});
audioTrack.enabled = VideoChat.audioEnabled;
});
// select mic button and mic button text
const micButtonIcon = document.getElementById("mic-icon");
const micButtonText = document.getElementById("mic-text");
@ -863,15 +897,16 @@ function uuidToColor(uuid) {
// Using uuid to generate random. unique pastel color
var hash = 0;
for (var i = 0; i < uuid.length; i++) {
hash = uuid.charCodeAt(i) + ((hash << 5) - hash);
hash = hash & hash;
hash = uuid.charCodeAt(i) + ((hash << 5) - hash);
hash = hash & hash;
}
var hue = Math.abs(hash % 360);
console.log(hue);
// Ensure color is not similar to other colors
var availColors = Array.from({length: 18}, (x,i) => i*20);
VideoChat.peerColors.forEach(function(value, key, map) {availColors[Math.floor(value/20)] = null});
if (availColors[Math.floor(hue/20)] == null) {
var availColors = Array.from({ length: 18 }, (x, i) => i * 20);
VideoChat.peerColors.forEach(function (value, key, map) {
availColors[Math.floor(value / 20)] = null;
});
if (availColors[Math.floor(hue / 20)] == null) {
for (var i = 0; i < availColors.length; i++) {
if (availColors[i] != null) {
hue = (hue % 20) + availColors[i];
@ -886,7 +921,9 @@ function uuidToColor(uuid) {
// Sets the border color of uuid's stream
function setStreamColor(uuid) {
const color = uuidToColor(uuid);
document.querySelectorAll(`[uuid="${uuid}"]`)[0].style.border = `3px solid ${color}`;
document.querySelectorAll(
`[uuid="${uuid}"]`
)[0].style.border = `3px solid ${color}`;
VideoChat.peerColors[uuid] = color;
}
@ -921,18 +958,27 @@ function togglePictureInPicture() {
logIt("Error exiting pip.");
logIt(error);
});
} else if (VideoChat.remoteVideoWrapper.lastChild.webkitPresentationMode === "inline") {
VideoChat.remoteVideoWrapper.lastChild.webkitSetPresentationMode("picture-in-picture");
} else if (
VideoChat.remoteVideoWrapper.lastChild.webkitPresentationMode === "picture-in-picture"
VideoChat.remoteVideoWrapper.lastChild.webkitPresentationMode === "inline"
) {
VideoChat.remoteVideoWrapper.lastChild.webkitSetPresentationMode("inline");
VideoChat.remoteVideoWrapper.lastChild.webkitSetPresentationMode(
"picture-in-picture"
);
} else if (
VideoChat.remoteVideoWrapper.lastChild.webkitPresentationMode ===
"picture-in-picture"
) {
VideoChat.remoteVideoWrapper.lastChild.webkitSetPresentationMode(
"inline"
);
} else {
VideoChat.remoteVideoWrapper.lastChild.requestPictureInPicture().catch((error) => {
alert(
"You must be connected to another person to enter picture in picture."
);
});
VideoChat.remoteVideoWrapper.lastChild
.requestPictureInPicture()
.catch((error) => {
alert(
"You must be connected to another person to enter picture in picture."
);
});
}
} else {
alert(

15
public/landing.html vendored
View File

@ -67,9 +67,9 @@
class="mt-0 mb-32 reveal-from-bottom"
data-reveal-delay="300"
>
Simple, Secure, and Fast. Peer to peer group video
calling provides quality and latency simply not
available with traditional technology.
Simple, Secure, and Fast. Peer to peer group video calling
provides quality and latency simply not available with
traditional technology.
</p>
<div class="reveal-from-bottom" data-reveal-delay="450">
<a
@ -201,9 +201,8 @@
<div class="features-tiles-item-content">
<h4 class="mt-0 mb-8">Decentralized group calls</h4>
<p class="m-0 text-sm">
Zipcall lets you talk to up to four friends by
directly connecting to them, completely
decentralized.
Zipcall lets you talk to up to four friends by directly
connecting to them, completely decentralized.
</p>
</div>
</div>
@ -248,8 +247,8 @@
<h4 class="mt-0 mb-8">Total Privacy and Security</h4>
<p class="m-0 text-sm">
Zipcall is built privacy first. Each chat is single use,
and end to end state of the art encryption means your calls
are exactly that. Your calls.
and end to end state of the art encryption means your
calls are exactly that. Your calls.
</p>
</div>
</div>