mirror of
https://github.com/eliasstepanik/vdo.ninja.git
synced 2026-01-25 20:38:28 +00:00
nearing v20
lots of small features/improvements
This commit is contained in:
parent
3793bd6e4f
commit
8168911488
26
index.html
26
index.html
@ -54,7 +54,7 @@
|
||||
transition: opacity .1s linear;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="./main.css?ver=142" />
|
||||
<link rel="stylesheet" href="./main.css?ver=145" />
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/adapter.min.js"></script>
|
||||
<style id="lightbox-animations" type="text/css"></style>
|
||||
</head>
|
||||
@ -67,7 +67,7 @@
|
||||
<link itemprop="url" href="./media/vdoNinja_logo_full.png" />
|
||||
</span>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/CodecsHandler.js?ver=34"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./webrtc.js?ver=328"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./webrtc.js?ver=334"></script>
|
||||
<input id="zoomSlider" type="range" style="display: none;" />
|
||||
<div id="header">
|
||||
|
||||
@ -375,7 +375,7 @@
|
||||
<li>
|
||||
<input type="checkbox" id="multiselect1" name="multiselect1" style="display: none;" checked value="ZZZ" />
|
||||
<label for="multiselect1">
|
||||
<span data-translate="no-audio">No Audio</span>
|
||||
<span data-translate="no-audio"> No Audio</span>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
@ -751,7 +751,7 @@
|
||||
<font style="color:#daad09;">Welcome to VDO Ninja! We've rebranded! Nothing else is changing and we're staying 100% free.</font>
|
||||
</h4>
|
||||
<br />
|
||||
🎁 Site updated October 19th (v19.4). The <a href="https://docs.vdo.ninja/release-notes/v19">v19 release notes are here</a>. If new issues occur, the older v18 can be <a href="https://vdo.ninja/v183/">found here</a>.
|
||||
🎁 Site updated November 4th (v19.5). The <a href="https://docs.vdo.ninja/release-notes/v19">v19 release notes are here</a>. If new issues occur, the older v18 can be <a href="https://vdo.ninja/v183/">found here</a>.
|
||||
|
||||
<br />
|
||||
<br />
|
||||
@ -896,7 +896,12 @@
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span data-translate="show-active-speaker">Show active speakers</span>
|
||||
|
||||
<Br />
|
||||
<label class="switch" title="Show a custom welcome message to the joining guest of this invite link">
|
||||
<input type="checkbox" data-param="&welcome" onchange="updateLinkWelcome(1,this);">
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
<span data-translate="show-welcome-message">Show welcome message</span>
|
||||
|
||||
</div>
|
||||
<div style="display:inline-block;margin-top: 12px; position: relative; margin-right:10px;">
|
||||
@ -1606,7 +1611,7 @@
|
||||
<div id="chatModule" style="display:none;text-align:right">
|
||||
<a target="popup" id="popOutChat" style="cursor:pointer;text-align:right;color:#B3C7F9;" onclick="createPopoutChat();"><i class="las la-external-link-alt"></i></a>
|
||||
<div id="chatBody">
|
||||
<div class="inMessage" data-translate='welcome-to-obs-ninja-chat'>
|
||||
<div class="inMessage" id="welcomeMsg" data-translate='welcome-to-obs-ninja-chat'>
|
||||
Welcome to VDO.Ninja! You can send text messages directly to connected peers from here.
|
||||
</div>
|
||||
</div>
|
||||
@ -1713,7 +1718,10 @@
|
||||
<div id="userList">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="signalMeterTemplate" class="signal-meter" data-cpu="0" data-level="0">
|
||||
<i class="las la-signal"></i>
|
||||
<i class="las la-fire-alt"></i>
|
||||
</div>
|
||||
<div id="voiceMeterTemplate" class="video-meter">
|
||||
</div>
|
||||
<div id="voiceMeterTemplate2" class="video-meter2">
|
||||
@ -1867,11 +1875,11 @@
|
||||
// session.introOnClean = true; // this will load the page with the webcam selection screen if &push or &room is in the URL; no need to use &webcam.
|
||||
</script>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/aes.js"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="lib-js" src="./lib.js?ver=206"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="lib-js" src="./lib.js?ver=228"></script>
|
||||
<!--
|
||||
// If you wish to change branding, blank offers a good clean start.
|
||||
<script type="text/javascript" id="main-js" src="./main.js" data-translation="blank"></script>
|
||||
-->
|
||||
<script type="text/javascript" crossorigin="anonymous" id="main-js" src="./main.js?ver=278"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="main-js" src="./main.js?ver=281"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
444
lib.js
444
lib.js
@ -72,7 +72,8 @@ var miscTranslations = {
|
||||
"confirm-disconnect-users": "Are you sure you wish to disconnect these users?",
|
||||
"confirm-disconnect-user": "Are you sure you wish to disconnect this user?",
|
||||
"enter-new-codirector-password": "Enter a co-director password to use",
|
||||
"control-room-co-director": "Control Room: Co-Director"
|
||||
"control-room-co-director": "Control Room: Co-Director",
|
||||
"signal-meter": "Video packet loss indicator of video preview; green is good, red is bad. Flame implies CPU is overloaded. May not reflect the packet loss seen by scenes or other guests."
|
||||
};
|
||||
|
||||
// function log(msg){ // uncomment to enable logging.
|
||||
@ -2224,7 +2225,7 @@ function updateMixerRun(e=false){ // this is the main auto-mixing code. It's a
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var sscount = false
|
||||
var mpl = mediaPool.length;
|
||||
if (mpl>1){
|
||||
var BB = 0;
|
||||
@ -2248,13 +2249,57 @@ function updateMixerRun(e=false){ // this is the main auto-mixing code. It's a
|
||||
rw = NW;
|
||||
rh = NH;
|
||||
}
|
||||
|
||||
|
||||
if (("screenshare" in mediaPool[NW-1]) && (mediaPool[NW-1].screenshare)){
|
||||
sscount = mediaPool[NW-1].dataset.sid;
|
||||
}
|
||||
}
|
||||
} else { var rw=1; var rh=1;}
|
||||
|
||||
var playarea = getById("gridlayout");
|
||||
|
||||
} catch(e){
|
||||
errorlog(e);
|
||||
sscount = false
|
||||
}
|
||||
var playarea = getById("gridlayout");
|
||||
|
||||
var customLayout=false;
|
||||
if (sscount && !session.layout){
|
||||
customLayout = {};
|
||||
console.log(sscount);
|
||||
if (mediaPool.length>=5){
|
||||
customLayout[sscount] = {"x":0,"y":33.333,"w":66.667,"h":66.667, "c": session.cover};
|
||||
} else {
|
||||
customLayout[sscount] = {"x":0,"y":0,"w":66.667,"h":100, "c": session.cover};
|
||||
}
|
||||
var posCount = 0;
|
||||
for (var i = 0; i<mediaPool.length; i++){
|
||||
if (mediaPool[i].dataset.sid === sscount){continue;}
|
||||
if (mediaPool.length==2){
|
||||
customLayout[mediaPool[i].dataset.sid] = {"x":66.667,"y":33.333,"w":33.333,"h":33.333, "c":true};
|
||||
} else if (mediaPool.length==3){
|
||||
customLayout[mediaPool[i].dataset.sid] = {"x":66.667,"y":posCount*33.333+16.667,"w":33.333,"h":33.333, "c":true};
|
||||
} else if (mediaPool.length==4){
|
||||
customLayout[mediaPool[i].dataset.sid] = {"x":66.667,"y":posCount*33.333,"w":33.333,"h":33.333, "c":true};
|
||||
} else if (mediaPool.length==5){
|
||||
if (posCount==0){
|
||||
customLayout[mediaPool[i].dataset.sid] = {"x":33.333,"y":0,"w":33.333,"h":33.333, "c":true};
|
||||
} else {
|
||||
customLayout[mediaPool[i].dataset.sid] = {"x":66.667,"y":(posCount-1)*33.333,"w":33.333,"h":33.333, "c":true};
|
||||
}
|
||||
} else if (mediaPool.length>=6){
|
||||
if (posCount==0){
|
||||
customLayout[mediaPool[i].dataset.sid] = {"x":0,"y":0,"w":33.333,"h":33.333, "c":true};
|
||||
} else if (posCount==1){
|
||||
customLayout[mediaPool[i].dataset.sid] = {"x":33.333,"y":0,"w":33.333,"h":33.333, "c":true};
|
||||
} else {
|
||||
customLayout[mediaPool[i].dataset.sid] = {"x":66.667,"y":(posCount-2)*33.333,"w":33.333,"h":33.333, "c":true};
|
||||
}
|
||||
} else {
|
||||
customLayout[mediaPool[i].dataset.sid] = {"x":66.667,"y":posCount*33.333,"w":33.333,"h":33.333, "c":true};
|
||||
}
|
||||
posCount+=1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2495,9 +2540,45 @@ function updateMixerRun(e=false){ // this is the main auto-mixing code. It's a
|
||||
} else {
|
||||
vid.style.objectFit = "contain";
|
||||
}
|
||||
container.style.width="0";
|
||||
container.style.height="0";
|
||||
//container.style.width="0";
|
||||
//container.style.height="0";
|
||||
session.requestRateLimit(session.hiddenSceneViewBitrate, i, false); // it's added already, so we know it needs sound. But lets d
|
||||
vid.style.width = "0px";
|
||||
vid.style.height = "0px";
|
||||
vid.style.top = "0px";
|
||||
vid.style.left = "0px";
|
||||
vid.isInvisible = true;
|
||||
vid.alreadyAdded=false;
|
||||
return;
|
||||
}
|
||||
} else if (typeof customLayout === "object"){
|
||||
if (vid.dataset.sid in customLayout){
|
||||
var left = (window.innerWidth/100*customLayout[vid.dataset.sid].x) || 0;
|
||||
var top = (window.innerHeight/100*customLayout[vid.dataset.sid].y) || 0;
|
||||
var width = (window.innerWidth/100*customLayout[vid.dataset.sid].w) || 0;
|
||||
var height = (window.innerHeight/100*customLayout[vid.dataset.sid].h) || 0;
|
||||
container.style.zIndex = customLayout[vid.dataset.sid].z || 0;
|
||||
if (customLayout[vid.dataset.sid].c){
|
||||
vid.style.objectFit = "cover";
|
||||
} else {
|
||||
vid.style.objectFit = "contain";
|
||||
}
|
||||
} else {
|
||||
container.style.zIndex = 0;
|
||||
if (session.cover){
|
||||
vid.style.objectFit = "cover";
|
||||
} else {
|
||||
vid.style.objectFit = "contain";
|
||||
}
|
||||
//container.style.width="0";
|
||||
//container.style.height="0";
|
||||
session.requestRateLimit(session.hiddenSceneViewBitrate, i, false); // it's added already, so we know it needs sound. But lets d
|
||||
vid.style.width = "0px";
|
||||
vid.style.height = "0px";
|
||||
vid.style.top = "0px";
|
||||
vid.style.left = "0px";
|
||||
vid.isInvisible = true;
|
||||
vid.alreadyAdded=false;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@ -2507,14 +2588,14 @@ function updateMixerRun(e=false){ // this is the main auto-mixing code. It's a
|
||||
var width = Math.ceil(w/rw);
|
||||
var height = Math.ceil(h/rh);
|
||||
|
||||
if (session.layout===null){ // if using layouts, layouts should never be false, but NULL to indicate auto mixing.
|
||||
//if (session.layout===null){ // if using layouts, layouts should never be false, but NULL to indicate auto mixing.
|
||||
container.style.zIndex = 0;
|
||||
if (session.cover){
|
||||
vid.style.objectFit = "cover";
|
||||
} else {
|
||||
vid.style.objectFit = "contain";
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
@ -2621,8 +2702,6 @@ function updateMixerRun(e=false){ // this is the main auto-mixing code. It's a
|
||||
container.style.display = "flex";
|
||||
container.style.alignItems = "center";
|
||||
|
||||
|
||||
|
||||
var left = (window.innerWidth/100*session.layout[vid.dataset.sid].x) || 0;
|
||||
var top = (window.innerHeight/100*session.layout[vid.dataset.sid].y) || 0;
|
||||
var width = (window.innerWidth/100*session.layout[vid.dataset.sid].w) || 0;
|
||||
@ -2648,6 +2727,39 @@ function updateMixerRun(e=false){ // this is the main auto-mixing code. It's a
|
||||
session.requestRateLimit(session.hiddenSceneViewBitrate, i, false); // it's added already, so we know it needs sound. But lets d
|
||||
return;
|
||||
}
|
||||
} else if (typeof customLayout === "object"){
|
||||
if (vid.dataset.sid in customLayout){
|
||||
|
||||
var container = document.createElement("div");
|
||||
container.style.position = "absolute";
|
||||
container.style.display = "flex";
|
||||
container.style.alignItems = "center";
|
||||
|
||||
var left = (window.innerWidth/100*customLayout[vid.dataset.sid].x) || 0;
|
||||
var top = (window.innerHeight/100*customLayout[vid.dataset.sid].y) || 0;
|
||||
var width = (window.innerWidth/100*customLayout[vid.dataset.sid].w) || 0;
|
||||
var height = (window.innerHeight/100*customLayout[vid.dataset.sid].h) || 0;
|
||||
|
||||
container.style.left = left+"px";
|
||||
container.style.top = top+"px";
|
||||
container.style.width = width+"px";
|
||||
container.style.height = height+"px";
|
||||
|
||||
container.style.zIndex = customLayout[vid.dataset.sid].z || 0;
|
||||
if (customLayout[vid.dataset.sid].c){
|
||||
vid.style.objectFit = "cover";
|
||||
} else {
|
||||
vid.style.objectFit = "contain";
|
||||
}
|
||||
} else {
|
||||
if (session.cover){
|
||||
vid.style.objectFit = "cover";
|
||||
} else {
|
||||
vid.style.objectFit = "contain";
|
||||
}
|
||||
session.requestRateLimit(session.hiddenSceneViewBitrate, i, false); // it's added already, so we know it needs sound. But lets d
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
var container = document.createElement("div");
|
||||
container.style.position = "absolute";
|
||||
@ -2659,14 +2771,14 @@ function updateMixerRun(e=false){ // this is the main auto-mixing code. It's a
|
||||
container.style.width = Math.ceil(w/rw)+"px";
|
||||
container.style.height = Math.ceil(h/rh)+"px";
|
||||
|
||||
if (session.layout===null){
|
||||
//if (session.layout===null){
|
||||
container.style.zIndex = 0;
|
||||
if (session.cover){
|
||||
vid.style.objectFit = "cover";
|
||||
} else {
|
||||
vid.style.objectFit = "contain";
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
try {
|
||||
@ -2853,9 +2965,6 @@ function updateMixerRun(e=false){ // this is the main auto-mixing code. It's a
|
||||
holder.style.top = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (vid.dataset.UUID && session.rpcs[vid.dataset.UUID] && ("label" in session.rpcs[vid.dataset.UUID]) && (session.rpcs[vid.dataset.UUID].label !== false) && (session.showlabels===true)){ // remote source
|
||||
var CCC = vid.parentNode;
|
||||
|
||||
@ -2938,6 +3047,19 @@ function updateMixerRun(e=false){ // this is the main auto-mixing code. It's a
|
||||
}
|
||||
}
|
||||
|
||||
if (session.signalMeter){
|
||||
if (vid.dataset.UUID && !session.rpcs[vid.dataset.UUID].signalMeter){
|
||||
session.rpcs[vid.dataset.UUID].signalMeter = getById("signalMeterTemplate").cloneNode(true);
|
||||
session.rpcs[vid.dataset.UUID].signalMeter.style.display = "block";
|
||||
session.rpcs[vid.dataset.UUID].signalMeter.id = "signalMeter_" + vid.dataset.UUID;
|
||||
session.rpcs[vid.dataset.UUID].signalMeter.dataset.level = 0;
|
||||
session.rpcs[vid.dataset.UUID].signalMeter.title = miscTranslations["signal-meter"];
|
||||
holder.appendChild(session.rpcs[vid.dataset.UUID].signalMeter);
|
||||
} else if (vid.dataset.UUID && session.rpcs[vid.dataset.UUID].signalMeter){
|
||||
holder.appendChild(session.rpcs[vid.dataset.UUID].signalMeter);
|
||||
}
|
||||
}
|
||||
|
||||
if (session.ruleOfThirds){
|
||||
if (vid.id == "videosource"){
|
||||
var svg = document.createElement("div");
|
||||
@ -3273,6 +3395,7 @@ eventer(messageEvent, function(e) { // this listens for child IFRAMES.
|
||||
} else if (e.data.action == "video-loaded") {
|
||||
// TODO: if (e.source == session...iframeEle.contentWindow) {
|
||||
warnlog(e);
|
||||
toggleSpeakerMute(true);
|
||||
updateMixer(); // harmless to let run.
|
||||
}
|
||||
}
|
||||
@ -3336,7 +3459,7 @@ async function jumptoroom(event = null) {
|
||||
|
||||
var passStr = "";
|
||||
window.focus();
|
||||
var pass = await promptAlt("Enter a password if provided, otherwise just click cancel", false); //sanitizePassword(session.password);
|
||||
var pass = await promptAlt("Enter a password if provided, otherwise just click cancel", false, true); //sanitizePassword(session.password);
|
||||
if (pass && pass.length) {
|
||||
session.password = sanitizePassword(pass);
|
||||
passStr = "&password=" + session.password;
|
||||
@ -5696,7 +5819,7 @@ async function directPageReload(ele, event) {
|
||||
reloadURL = previousURL;
|
||||
} else {
|
||||
window.focus();
|
||||
var reloadURL = await promptAlt(miscTranslations["transfer-guest-to-url"], false, value=previousURL);
|
||||
var reloadURL = await promptAlt(miscTranslations["transfer-guest-to-url"], false, false, previousURL);
|
||||
stillNeedURL = true;
|
||||
if (reloadURL === null) { // user cancelled
|
||||
ele.innerHTML = '<i class="las la-sync"></i> <span data-translate="change-url">change URL</span>';
|
||||
@ -5733,7 +5856,7 @@ async function directTimer(ele, event=false) { // A directing room only is cont
|
||||
var msg = {};
|
||||
if (!event || (!((event.ctrlKey) || (event.metaKey)))) {
|
||||
if (ele.dataset.value == 0 || ele.dataset.value == 2) {
|
||||
var getTime = await promptAlt("Time in seconds to count down", false, value=parseInt(getById("overlayClockContainer").dataset.initial));
|
||||
var getTime = await promptAlt("Time in seconds to count down", false, false, parseInt(getById("overlayClockContainer").dataset.initial));
|
||||
if (!getTime){return;}
|
||||
getById("overlayClockContainer").dataset.initial = parseInt(getTime) || 600;
|
||||
ele.dataset.value = 1;
|
||||
@ -6693,7 +6816,6 @@ session.publishIFrame = function(iframeURL){
|
||||
container.style.backgroundColor = "#666";
|
||||
}
|
||||
|
||||
getById("mainmenu").parentElement.removeChild(getById("mainmenu"));
|
||||
|
||||
getById("gridlayout").innerHTML = "";
|
||||
container.appendChild(iframe);
|
||||
@ -6701,10 +6823,10 @@ session.publishIFrame = function(iframeURL){
|
||||
|
||||
|
||||
session.seeding=true;
|
||||
|
||||
|
||||
|
||||
getById("reshare").href = "https://"+location.host+location.pathname+"?view="+session.streamID;
|
||||
getById("reshare").text = "https://"+location.host+location.pathname+"?view="+session.streamID;
|
||||
getById("reshare").style.width = ((getById("reshare").text.length + 1)*1.15 * 8) + 'px';
|
||||
updateReshareLink();
|
||||
pokeIframeAPI('started-iframe-share');
|
||||
|
||||
session.seedStream();
|
||||
@ -6721,7 +6843,7 @@ function outboundAudioPipeline(stream) {
|
||||
});
|
||||
return newStream;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
log("Web Audio");
|
||||
var tracks = stream.getAudioTracks();
|
||||
@ -7217,7 +7339,7 @@ function activeSpeaker(border=false) {
|
||||
lastActiveSpeaker = UUID;
|
||||
}
|
||||
}
|
||||
if ((session.rpcs[UUID].stats.Audio_Loudness > 15) || ((session.rpcs[UUID].stats.Audio_Loudness > 5) && (session.rpcs[UUID].stats._Audio_Loudness_average>5)) || (session.rpcs[UUID].stats._Audio_Loudness_average>30)){
|
||||
if ((session.rpcs[UUID].stats.Audio_Loudness > 13) || ((session.rpcs[UUID].stats.Audio_Loudness > 5) && (session.rpcs[UUID].stats._Audio_Loudness_average>3)) || (session.rpcs[UUID].stats._Audio_Loudness_average>6)){
|
||||
someoneElseIfSpeaking = true;
|
||||
}
|
||||
|
||||
@ -7697,6 +7819,13 @@ function createRoomCallback(passAdd, passAdd2) {
|
||||
session.director = true;
|
||||
screensharesupport = false;
|
||||
|
||||
if (session.meterStyle ===false){
|
||||
session.meterStyle = 1;
|
||||
}
|
||||
if (session.signalMeter===null){
|
||||
session.signalMeter = true;
|
||||
}
|
||||
|
||||
if (session.directorPassword){
|
||||
getById("coDirectorEnable").checked = true;
|
||||
getById("coDirectorEnableSpan").style.display = "none";
|
||||
@ -8069,7 +8198,7 @@ async function createDirectorOnlyBox() {
|
||||
oldlabel = "";
|
||||
}
|
||||
window.focus();
|
||||
var newlabel = await promptAlt(miscTranslations["enter-new-display-name"], false, value=oldlabel);
|
||||
var newlabel = await promptAlt(miscTranslations["enter-new-display-name"], false, false, oldlabel);
|
||||
if (newlabel!==null){
|
||||
if (newlabel == ""){
|
||||
newlabel = false;
|
||||
@ -8190,6 +8319,39 @@ function createControlBox(UUID, soloLink, streamID) {
|
||||
|
||||
container.innerHTML = buttons;
|
||||
container.appendChild(videoContainer);
|
||||
|
||||
if (session.signalMeter){
|
||||
if (!session.rpcs[UUID].signalMeter){
|
||||
session.rpcs[UUID].signalMeter = getById("signalMeterTemplate").cloneNode(true);
|
||||
session.rpcs[UUID].signalMeter.id = "signalMeter_" + UUID;
|
||||
session.rpcs[UUID].signalMeter.dataset.level = 0;
|
||||
session.rpcs[UUID].signalMeter.style.display = "block";
|
||||
session.rpcs[UUID].signalMeter.dataset.UUID = UUID;
|
||||
session.rpcs[UUID].signalMeter.title = miscTranslations["signal-meter"];
|
||||
session.rpcs[UUID].signalMeter.addEventListener('click', function(e) { // show stats of video if double clicked
|
||||
log("clicked signal meter");
|
||||
try {
|
||||
e.preventDefault();
|
||||
var uid = e.currentTarget.dataset.UUID;
|
||||
if ("stats" in session.rpcs[uid]){
|
||||
|
||||
var [menu, innerMenu] = statsMenuCreator();
|
||||
|
||||
printViewStats(innerMenu, uid );
|
||||
|
||||
menu.interval = setInterval(printViewStats,3000, innerMenu, uid);
|
||||
|
||||
}
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
|
||||
} catch(e){errorlog(e);}
|
||||
});
|
||||
}
|
||||
|
||||
videoContainer.appendChild(session.rpcs[UUID].signalMeter);
|
||||
}
|
||||
|
||||
videoContainer.appendChild(session.rpcs[UUID].voiceMeter);
|
||||
videoContainer.appendChild(session.rpcs[UUID].remoteMuteElement);
|
||||
videoContainer.appendChild(session.rpcs[UUID].remoteVideoMuteElement);
|
||||
@ -8557,7 +8719,7 @@ function gotDevices(deviceInfos) { // https://github.com/webrtc/samples/blob/gh-
|
||||
|
||||
var label = document.createElement('label');
|
||||
label.for = option.name;
|
||||
label.innerHTML = '<span data-translate="no-audio">No Audio</span>';
|
||||
label.innerHTML = '<span data-translate="no-audio"> No Audio</span>';
|
||||
|
||||
var listele = document.createElement('li');
|
||||
listele.appendChild(option);
|
||||
@ -8723,6 +8885,8 @@ function gotDevices(deviceInfos) { // https://github.com/webrtc/samples/blob/gh-
|
||||
option.value = deviceInfo.deviceId || "default";
|
||||
option.name = "multiselect" + counter;
|
||||
option.id = "multiselect" + counter;
|
||||
option.label = deviceInfo.label;
|
||||
|
||||
label = document.createElement('label');
|
||||
label.for = option.name;
|
||||
|
||||
@ -8749,6 +8913,9 @@ function gotDevices(deviceInfos) { // https://github.com/webrtc/samples/blob/gh-
|
||||
if (SelectedAudioInputDevices.indexOf(event.currentTarget.value) > -1) {} else {
|
||||
SelectedAudioInputDevices.push(event.currentTarget.value);
|
||||
}
|
||||
if (session.mobile && (!(iOS || iPad)) && (event.currentTarget.label === "USB audio") && !session.cleanOutput){
|
||||
warnUser("Notice: USB audio devices may not work on all mobile devices.\n\nConsider using FireFox mobile instead, as it tends to work with USB audio devices more often.");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -9046,7 +9213,7 @@ function addScreenDevices(device) {
|
||||
}
|
||||
|
||||
activatedPreview = false;
|
||||
grabAudio("videosource", "#audioSource3"); // exclude item.id
|
||||
grabAudio("#audioSource3"); // exclude item.id
|
||||
|
||||
} else {
|
||||
if (SelectedAudioInputDevices.indexOf(item.value) > -1) {} else {
|
||||
@ -9055,7 +9222,7 @@ function addScreenDevices(device) {
|
||||
|
||||
item.checked = true;
|
||||
activatedPreview = false;
|
||||
grabAudio("videosource", "#audioSource3", item.value); // exclude item.id. we will reconnect, even if already connected, as a way to 'reset' a device if it isn't working.
|
||||
grabAudio("#audioSource3", item.value); // exclude item.id. we will reconnect, even if already connected, as a way to 'reset' a device if it isn't working.
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -9302,7 +9469,7 @@ function gotDevices2(deviceInfos) {
|
||||
}
|
||||
}
|
||||
activatedPreview = false;
|
||||
grabAudio("videosource", "#audioSource3", trackid); // exclude item.id.
|
||||
grabAudio("#audioSource3", trackid); // exclude item.id.
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
};
|
||||
@ -9455,7 +9622,7 @@ function gotDevices2(deviceInfos) {
|
||||
log("Audio OPTION HAS CHANGED? 2");
|
||||
activatedPreview = false;
|
||||
setTimeout(function(){
|
||||
grabAudio("videosource", "#audioSource3");
|
||||
grabAudio("#audioSource3");
|
||||
},10)
|
||||
};
|
||||
|
||||
@ -10008,7 +10175,7 @@ function reconnectDevices(event) { /// TODO: Perhaps change this to only if the
|
||||
// }
|
||||
|
||||
activatedPreview = false;
|
||||
grabAudio("videosource", "#audioSource3");
|
||||
grabAudio("#audioSource3");
|
||||
setTimeout(function() {
|
||||
enumerateDevices().then(gotDevices2).then(function() {});
|
||||
}, 1000);
|
||||
@ -10446,24 +10613,42 @@ if (navigator.userAgent.toLowerCase().indexOf(' electron/') > -1) { // this ena
|
||||
const sources = await desktopCapturer.getSources({ types: ['screen', 'window'] });
|
||||
const selectionElem = document.createElement('div');
|
||||
selectionElem.classList = 'desktop-capturer-selection';
|
||||
selectionElem.innerHTML = `
|
||||
<div class="desktop-capturer-selection__scroller">
|
||||
<ul class="desktop-capturer-selection__list">
|
||||
${sources.map(({id, name, thumbnail, display_id, appIcon}) => `
|
||||
<li class="desktop-capturer-selection__item">
|
||||
<button class="desktop-capturer-click desktop-capturer-selection__btn" data-id="${id}" title="${name}">
|
||||
<img class="desktop-capturer-selection__thumbnail" src="${thumbnail.toDataURL()}" />
|
||||
<span class="desktop-capturer-selection__name">${name}</span>
|
||||
</button>
|
||||
</li>
|
||||
`).join('')}
|
||||
<div style="text-align: center;margin: auto 5px;font-size: 120%;"><i class="las la-music" style="font-size:40px;"></i><br />Include Desktop Audio<br /><input id="alsoCaptureAudio" style="width:20px;height:20px;margin-top: 10px;" type="checkbox" checked></div>
|
||||
<button id="captureDesktopAudio" class="desktop-capturer-click" style="margin: 10px;"><i class="las la-music" style="font-size:40px;"></i><br />Capture ONLY<br />Desktop Audio</button>
|
||||
<button id="cancelscreenshare" style="margin: 10px; background-color: #F88; width: 100px;"><i class="las la-window-close" style="font-size:40px;"></i><br />Cancel</button>
|
||||
</ul>
|
||||
</div>
|
||||
`;
|
||||
|
||||
if (session.screenshareVideoOnly){
|
||||
selectionElem.innerHTML = `
|
||||
<div class="desktop-capturer-selection__scroller">
|
||||
<ul class="desktop-capturer-selection__list">
|
||||
${sources.map(({id, name, thumbnail, display_id, appIcon}) => `
|
||||
<li class="desktop-capturer-selection__item">
|
||||
<button class="desktop-capturer-click desktop-capturer-selection__btn" data-id="${id}" title="${name}">
|
||||
<img class="desktop-capturer-selection__thumbnail" src="${thumbnail.toDataURL()}" />
|
||||
<span class="desktop-capturer-selection__name">${name}</span>
|
||||
</button>
|
||||
</li>
|
||||
`).join('')}
|
||||
<button id="cancelscreenshare" style="margin: 10px; background-color: #F88; width: 100px;"><i class="las la-window-close" style="font-size:40px;"></i><br />Cancel</button>
|
||||
</ul>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
selectionElem.innerHTML = `
|
||||
<div class="desktop-capturer-selection__scroller">
|
||||
<ul class="desktop-capturer-selection__list">
|
||||
${sources.map(({id, name, thumbnail, display_id, appIcon}) => `
|
||||
<li class="desktop-capturer-selection__item">
|
||||
<button class="desktop-capturer-click desktop-capturer-selection__btn" data-id="${id}" title="${name}">
|
||||
<img class="desktop-capturer-selection__thumbnail" src="${thumbnail.toDataURL()}" />
|
||||
<span class="desktop-capturer-selection__name">${name}</span>
|
||||
</button>
|
||||
</li>
|
||||
`).join('')}
|
||||
<div style="text-align: center;margin: auto 5px;font-size: 120%;"><i class="las la-music" style="font-size:40px;"></i><br />Include Desktop Audio<br /><input id="alsoCaptureAudio" style="width:20px;height:20px;margin-top: 10px;" type="checkbox" checked></div>
|
||||
<button id="captureDesktopAudio" class="desktop-capturer-click" style="margin: 10px;"><i class="las la-music" style="font-size:40px;"></i><br />Capture ONLY<br />Desktop Audio</button>
|
||||
<button id="cancelscreenshare" style="margin: 10px; background-color: #F88; width: 100px;"><i class="las la-window-close" style="font-size:40px;"></i><br />Cancel</button>
|
||||
</ul>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
document.body.appendChild(selectionElem);
|
||||
|
||||
document.getElementById('cancelscreenshare').addEventListener('click', async () => {
|
||||
@ -10686,6 +10871,10 @@ async function grabScreen(quality = 0, audio = true, videoOnEnd = false) {
|
||||
max: session.maxframerate
|
||||
};
|
||||
}
|
||||
|
||||
if (session.screenshareVideoOnly){
|
||||
constraints.audio = false;
|
||||
}
|
||||
|
||||
return navigator.mediaDevices.getDisplayMedia(constraints).then(function(stream) {
|
||||
log("adding video tracks 2245");
|
||||
@ -10863,7 +11052,7 @@ function changeAudioDevice(index){
|
||||
audioSelect[i].checked = false;
|
||||
}
|
||||
audioSelect[index-1].checked = true;
|
||||
grabAudio("videosource", "#audioSource3");
|
||||
grabAudio("#audioSource3");
|
||||
});
|
||||
}
|
||||
|
||||
@ -10918,7 +11107,7 @@ function changeAudioDeviceById(deviceID, UUID=false){
|
||||
}
|
||||
}
|
||||
activatedPreview=false;
|
||||
grabAudio("videosource", "#audioSource3", callback=UUID);
|
||||
grabAudio("#audioSource3", callback=UUID);
|
||||
});
|
||||
} else {
|
||||
try {
|
||||
@ -10940,7 +11129,7 @@ function changeAudioDeviceById(deviceID, UUID=false){
|
||||
}
|
||||
}
|
||||
activatedPreview=false;
|
||||
grabAudio("videosource", "#audioSource3", callback=UUID);
|
||||
grabAudio("#audioSource3", callback=UUID);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -11489,7 +11678,7 @@ function updateRenderOutpipe(){ // video only.
|
||||
}
|
||||
|
||||
|
||||
async function grabAudio(eleName = "previewWebcam", selector = "#audioSource", trackid = null, override = false, callback = false) { // trackid is the excluded track
|
||||
async function grabAudio(selector = "#audioSource", trackid = null, override = false, callback = false) { // trackid is the excluded track
|
||||
if (activatedPreview == true) {
|
||||
log("activated preview return 2");
|
||||
return;
|
||||
@ -11501,6 +11690,7 @@ async function grabAudio(eleName = "previewWebcam", selector = "#audioSource", t
|
||||
try {
|
||||
if (session.videoElement.srcObject) {
|
||||
var audioSelect = document.querySelector(selector).querySelectorAll("input");
|
||||
|
||||
var audioExcludeList = [];
|
||||
for (var i = 0; i < audioSelect.length; i++) {
|
||||
try {
|
||||
@ -12309,28 +12499,11 @@ session.publishStream = function(v){ // stream is used to generated an SDP
|
||||
|
||||
});
|
||||
|
||||
try{
|
||||
var m = getById("mainmenu");
|
||||
m.remove();
|
||||
} catch (e){}
|
||||
|
||||
var added = "";
|
||||
if (session.defaultPassword===false){
|
||||
if (session.password){
|
||||
added="&pw="+session.password;
|
||||
}
|
||||
if (session.welcomeMessage){
|
||||
getChatMessage(session.welcomeMessage, false, true, true);
|
||||
}
|
||||
|
||||
var pie = "";
|
||||
if (session.customWSS){
|
||||
if (session.customWSS!==true){
|
||||
pie = "&pie="+session.customWSS;
|
||||
}
|
||||
}
|
||||
|
||||
getById("reshare").href = "https://"+location.host+location.pathname+"?view="+session.streamID+added+pie;
|
||||
getById("reshare").text = "https://"+location.host+location.pathname+"?view="+session.streamID+added+pie;
|
||||
getById("reshare").style.width = ((getById("reshare").text.length + 1)*1.15 * 8) + 'px';
|
||||
updateReshareLink();
|
||||
pokeIframeAPI('started-camera');
|
||||
|
||||
if (session.videoMutedFlag){
|
||||
@ -12407,6 +12580,10 @@ async function publishScreen2(constraints, audioList=[], audio=true){ // webcam
|
||||
constraints.audio = false;
|
||||
}
|
||||
|
||||
if (session.screenshareVideoOnly){
|
||||
constraints.audio = false;
|
||||
}
|
||||
|
||||
log(constraints);
|
||||
getUserMediaRequestID+=1;
|
||||
var gumID = getUserMediaRequestID;
|
||||
@ -12659,22 +12836,9 @@ async function publishScreen2(constraints, audioList=[], audio=true){ // webcam
|
||||
} catch(e){errorlog(e);}
|
||||
});
|
||||
|
||||
try{
|
||||
var m = getById("mainmenu");
|
||||
m.remove();
|
||||
} catch (e){}
|
||||
|
||||
var pie = "";
|
||||
if (session.customWSS){
|
||||
if (session.customWSS!==true){
|
||||
pie = "&pie="+session.customWSS;
|
||||
}
|
||||
}
|
||||
|
||||
getById("reshare").href = "https://"+location.host+location.pathname+"?view="+session.streamID+pie;
|
||||
getById("reshare").text = "https://"+location.host+location.pathname+"?view="+session.streamID+pie;
|
||||
getById("reshare").style.width = ((getById("reshare").text.length + 1)*1.15 * 8) + 'px';
|
||||
|
||||
|
||||
updateReshareLink();
|
||||
|
||||
if (session.videoMutedFlag){
|
||||
session.videoMuted = true;
|
||||
@ -12956,11 +13120,35 @@ session.hostFile = function(ele, event){ // webcam stream is used to generated a
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
updateReshareLink();
|
||||
|
||||
pokeIframeAPI('started-fileshare');
|
||||
|
||||
clearInterval(session.updateLocalStatsInterval);
|
||||
session.updateLocalStatsInterval = setInterval(function(){updateLocalStats();},3000);
|
||||
|
||||
session.seeding=true;
|
||||
session.seedStream();
|
||||
}
|
||||
|
||||
function updateReshareLink(){
|
||||
try{
|
||||
var m = getById("mainmenu");
|
||||
m.remove();
|
||||
} catch (e){}
|
||||
|
||||
var added = "";
|
||||
if (session.defaultPassword===false){
|
||||
if (session.password!==false){
|
||||
added="&pw="+session.password;
|
||||
} else {
|
||||
added="&pw=false";
|
||||
}
|
||||
}
|
||||
|
||||
var pie = "";
|
||||
if (session.customWSS){
|
||||
if (session.customWSS!==true){
|
||||
@ -12968,16 +13156,9 @@ session.hostFile = function(ele, event){ // webcam stream is used to generated a
|
||||
}
|
||||
}
|
||||
|
||||
getById("reshare").href = "https://"+location.host+location.pathname+"?view="+session.streamID+pie;
|
||||
getById("reshare").text = "https://"+location.host+location.pathname+"?view="+session.streamID+pie;
|
||||
getById("reshare").href = "https://"+location.host+location.pathname+"?view="+session.streamID+added+pie;
|
||||
getById("reshare").text = "https://"+location.host+location.pathname+"?view="+session.streamID+added+pie;
|
||||
getById("reshare").style.width = ((getById("reshare").text.length + 1)*1.15 * 8) + 'px';
|
||||
pokeIframeAPI('started-fileshare');
|
||||
|
||||
clearInterval(session.updateLocalStatsInterval);
|
||||
session.updateLocalStatsInterval = setInterval(function(){updateLocalStats();},3000);
|
||||
|
||||
session.seeding=true;
|
||||
session.seedStream();
|
||||
}
|
||||
|
||||
session.publishFile = function(ele, event){ // webcam stream is used to generated an SDP
|
||||
@ -13287,21 +13468,9 @@ session.publishFile = function(ele, event){ // webcam stream is used to generate
|
||||
|
||||
});
|
||||
|
||||
try{
|
||||
var m = getById("mainmenu");
|
||||
m.remove();
|
||||
} catch (e){}
|
||||
|
||||
var pie = "";
|
||||
if (session.customWSS){
|
||||
if (session.customWSS!==true){
|
||||
pie = "&pie="+session.customWSS;
|
||||
}
|
||||
}
|
||||
|
||||
getById("reshare").href = "https://"+location.host+location.pathname+"?view="+session.streamID+pie;
|
||||
getById("reshare").text = "https://"+location.host+location.pathname+"?view="+session.streamID+pie;
|
||||
getById("reshare").style.width = ((getById("reshare").text.length + 1)*1.15 * 8) + 'px';
|
||||
updateReshareLink();
|
||||
pokeIframeAPI('started-fileshare');
|
||||
|
||||
clearInterval(session.updateLocalStatsInterval);
|
||||
@ -13945,7 +14114,7 @@ async function requestVideoRecord(ele) {
|
||||
msg.requestVideoRecord = true;
|
||||
msg.UUID = UUID;
|
||||
window.focus();
|
||||
var bitrate = await promptAlt(miscTranslations["what-bitrate"], false, value=6000);
|
||||
var bitrate = await promptAlt(miscTranslations["what-bitrate"], false, false, 6000);
|
||||
if (bitrate) {
|
||||
msg.value = bitrate;
|
||||
session.sendRequest(msg, msg.UUID);
|
||||
@ -15169,7 +15338,7 @@ function applyAudioHack(constraint, value = null, deviceid="default") {
|
||||
log(new_constraints);
|
||||
activatedPreview = false;
|
||||
enumerateDevices().then(gotDevices2).then(function() {
|
||||
grabAudio("videosource", "#audioSource3", null, new_constraints);
|
||||
grabAudio("#audioSource3", null, new_constraints);
|
||||
});
|
||||
|
||||
}
|
||||
@ -15340,7 +15509,6 @@ function listCameraSettings() {
|
||||
label.style = "display:inline-block; padding:0;margin: 15px 0px 29px;";
|
||||
label.dataset.keyname = i;
|
||||
var input = document.createElement("select");
|
||||
var c = document.createElement("option");
|
||||
|
||||
if (session.cameraConstraints[i].length > 1) {
|
||||
var included = false;
|
||||
@ -15363,10 +15531,16 @@ function listCameraSettings() {
|
||||
}
|
||||
}
|
||||
} else if (i.toLowerCase == "torch") {
|
||||
warnlog("TORCH");
|
||||
var opt = new Option("Off", false);
|
||||
input.options.add(opt);
|
||||
opt = new Option("On", true);
|
||||
input.options.add(opt);
|
||||
try{
|
||||
if (session.currentCameraConstraints[i]){
|
||||
opt.selected = "selected";
|
||||
}
|
||||
} catch(e){}
|
||||
} else if (session.cameraConstraints[i].length && ("continuous" == session.cameraConstraints[i][0])){
|
||||
var opt = new Option("continuous", "continuous");
|
||||
input.options.add(opt);
|
||||
@ -15456,13 +15630,16 @@ function listCameraSettings() {
|
||||
label.style = "display:inline-block; padding:0;margin: 15px 0px 29px;";
|
||||
label.dataset.keyname = i;
|
||||
var input = document.createElement("select");
|
||||
var c = document.createElement("option");
|
||||
|
||||
var opt = new Option("Off", false);
|
||||
var opt = new Option("Off", "false");
|
||||
input.options.add(opt);
|
||||
opt = new Option("On", true);
|
||||
|
||||
opt = new Option("On", "true");
|
||||
input.options.add(opt);
|
||||
|
||||
if (session.currentCameraConstraints[i]){
|
||||
opt.selected = "true";
|
||||
}
|
||||
|
||||
if (getById("popupSelector_constraints_video").style.display == "none") {
|
||||
getById("advancedOptionsCamera").style.display = "inline-block";
|
||||
}
|
||||
@ -15475,7 +15652,7 @@ function listCameraSettings() {
|
||||
input.onchange = function(e) {
|
||||
//getById("label_"+e.target.dataset.keyname).innerHTML =e.target.dataset.keyname+": "+e.target.value;
|
||||
updateCameraConstraints(e.target.dataset.keyname, e.target.value);
|
||||
log(e.target.dataset.keyname, e.target.value);
|
||||
log(e.target.dataset.keyname + " " + e.target.value);
|
||||
};
|
||||
getById("popupSelector_constraints_video").appendChild(div);
|
||||
div.appendChild(label);
|
||||
@ -15633,16 +15810,18 @@ function updateCameraConstraints(constraint, value = null) {
|
||||
[constraint]: value
|
||||
}]
|
||||
}).then(() => {
|
||||
if (track0.getSettings){
|
||||
if (session.currentCameraConstraints.deviceId){
|
||||
cameraSettings['current'] = track0.getSettings(); // this won't let failed settings be stored.
|
||||
//cameraSettings['current'][constraint] = value; // setting value is a problem, as it will allow for failed settings to be stored.
|
||||
setStorage("camera_"+session.currentCameraConstraints.deviceId, cameraSettings);
|
||||
if (toggleSettingsState == true) {
|
||||
listCameraSettings();
|
||||
//setTimeout(function(){
|
||||
if (track0.getSettings){
|
||||
if (session.currentCameraConstraints.deviceId){
|
||||
cameraSettings['current'] = track0.getSettings(); // this won't let failed settings be stored.
|
||||
//cameraSettings['current'][constraint] = value; // setting value is a problem, as it will allow for failed settings to be stored.
|
||||
setStorage("camera_"+session.currentCameraConstraints.deviceId, cameraSettings);
|
||||
if (toggleSettingsState == true) {
|
||||
listCameraSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//},500, track0);
|
||||
}).catch(e => {
|
||||
errorlog("coulnd't save defaults"); // this doesn't get triggered when a setting fails for some reason.
|
||||
});
|
||||
@ -15911,7 +16090,7 @@ async function shareWebsite(autostart=false, evt=false){
|
||||
getById("websitesharebutton").title = "Hold CTRL (or CMD) and click to spotlight this video";
|
||||
if (autostart===false){
|
||||
window.focus();
|
||||
var iframeURL = await promptAlt(miscTranslations["enter-website"], false, value=session.defaultIframeSrc);
|
||||
var iframeURL = await promptAlt(miscTranslations["enter-website"], false, false, session.defaultIframeSrc);
|
||||
} else {
|
||||
var iframeURL = autostart;
|
||||
}
|
||||
@ -16341,6 +16520,17 @@ function generateQRPage() {
|
||||
}
|
||||
}
|
||||
|
||||
async function updateLinkWelcome(arg, input) {
|
||||
if (input.checked){
|
||||
var response = await promptAlt("Enter the message you'd like the guests to see");
|
||||
response = encodeURIComponent(response);
|
||||
var param = input.dataset.param.split("=")[0];
|
||||
input.dataset.param = param + "=" + response;
|
||||
}
|
||||
updateLink(arg, input);
|
||||
}
|
||||
|
||||
|
||||
function updateLinkWebP(arg, input) {
|
||||
if (input.checked){
|
||||
if (!((getById("director_block_" + arg).dataset.raw.includes("&broadcast")) || (getById("director_block_" + arg).dataset.raw.includes("?broadcast")))){
|
||||
@ -17474,7 +17664,7 @@ async function recordVideo(target, event, videoKbps = false) { // event.currentT
|
||||
if (defaultRecordingBitrate == false) {
|
||||
videoKbps = 4000; // 4mbps recording bitrate
|
||||
window.focus();
|
||||
videoKbps = await promptAlt(miscTranslations["press-ok-to-record"], false, value=videoKbps);
|
||||
videoKbps = await promptAlt(miscTranslations["press-ok-to-record"], false, false, videoKbps);
|
||||
if (videoKbps === null) {
|
||||
//target.style.backgroundColor = null;
|
||||
//target.innerHTML = '<i class="las la-circle"></i><span data-translate="record"> record local</span>';
|
||||
|
||||
55
main.css
55
main.css
@ -530,6 +530,49 @@ hr {
|
||||
transform: scale(1);
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
.signal-meter{
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
top: 1px;
|
||||
background-color: #FFF2;
|
||||
font-size: 1.5em;
|
||||
display:none;
|
||||
z-index: 2;
|
||||
cursor: help;
|
||||
}
|
||||
.signal-meter[data-cpu="0"]>.la-signal {
|
||||
display:block;
|
||||
}
|
||||
.signal-meter[data-cpu="0"]>.la-fire-alt {
|
||||
display:none;
|
||||
}
|
||||
.signal-meter[data-cpu="1"]>.la-signal {
|
||||
display:none;
|
||||
}
|
||||
.signal-meter[data-cpu="1"]>.la-fire {
|
||||
display:block;
|
||||
}
|
||||
.signal-meter[data-level="0"] {
|
||||
color:#000F;
|
||||
}
|
||||
.signal-meter[data-level="1"] {
|
||||
color:#FF1B01;
|
||||
}
|
||||
.signal-meter[data-level="2"] {
|
||||
color:#FF8D01;
|
||||
}
|
||||
.signal-meter[data-level="3"] {
|
||||
color:#FFD201;
|
||||
}
|
||||
.signal-meter[data-level="4"] {
|
||||
color:#C6FF01;
|
||||
}
|
||||
.signal-meter[data-level="5"] {
|
||||
color:#00FF00;
|
||||
}
|
||||
|
||||
|
||||
.mirror {
|
||||
transform: scaleX(-1);
|
||||
@ -2987,8 +3030,8 @@ input:checked + .slider:before {
|
||||
border-radius: 10px;
|
||||
font-weight: bold;
|
||||
z-index:31;
|
||||
min-width:500px;
|
||||
max-width:90%;
|
||||
width:550px;
|
||||
max-width:100%;
|
||||
overflow: hidden;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
@ -3004,7 +3047,7 @@ input:checked + .slider:before {
|
||||
.promptModalInner {
|
||||
position: relative;
|
||||
padding: 1em;
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.promptModalMessage {
|
||||
@ -3335,6 +3378,8 @@ input:checked + .slider:before {
|
||||
content: "\f017"; }
|
||||
.la-tachometer-alt:before {
|
||||
content: "\f3fd"; }
|
||||
.la-fire-alt:before {
|
||||
content: "\f7e4"; }
|
||||
.la-book-open:before {
|
||||
content: "\f518"; }
|
||||
.la-caret-down:before {
|
||||
@ -3419,7 +3464,9 @@ input:checked + .slider:before {
|
||||
content: "\f001"; }
|
||||
.la-hdd:before {
|
||||
content: "\f0a0"; }
|
||||
|
||||
.la-signal:before {
|
||||
content: "\f012"; }
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--color-mode: dark;
|
||||
|
||||
36
main.js
36
main.js
@ -320,10 +320,27 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
directorLanding = false;
|
||||
}
|
||||
session.meterStyle = 1;
|
||||
session.signalMeter = true;
|
||||
} else if (filename === "director") {
|
||||
directorLanding = true;
|
||||
filename = false;
|
||||
session.meterStyle = 1;
|
||||
session.signalMeter = true;
|
||||
}
|
||||
|
||||
if (urlParams.has('signalmeter')) {
|
||||
session.signalMeter = urlParams.get('signalmeter');
|
||||
if (session.signalMeter === "false") {
|
||||
session.signalMeter = false;
|
||||
} else if (session.signalMeter=== "0") {
|
||||
session.signalMeter = false;
|
||||
} else if (session.signalMeter === "no") {
|
||||
session.signalMeter = false;
|
||||
} else if (session.signalMeter === "off") {
|
||||
session.signalMeter = false;
|
||||
} else {
|
||||
session.signalMeter = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (urlParams.has('rooms')) {
|
||||
@ -466,7 +483,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
// session.devicePixelRatio = window.devicePixelRatio; // this annoys me to no end.
|
||||
//}
|
||||
|
||||
if (urlParams.has('speakermute') || urlParams.has('mutespeaker') || urlParams.has('sm') || urlParams.has('ms')) {
|
||||
if (urlParams.has('speakermute') || urlParams.has('speakermuted') || urlParams.has('mutespeaker') || urlParams.has('sm') || urlParams.has('ms')) {
|
||||
session.speakerMuted = true;
|
||||
getById("mutespeakertoggle").className = "las la-volume-mute my-float toggleSize";
|
||||
//getById("mutespeakerbutton").className="advanced float2 red";
|
||||
@ -979,6 +996,10 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
if (urlParams.has('ruler') || urlParams.has('grid') || urlParams.has('thirds')) {
|
||||
session.ruleOfThirds=true;
|
||||
}
|
||||
|
||||
if (urlParams.has('proxy')) { // routes the wss traffic via an alternative network path. Not
|
||||
session.proxy=true; // only works if session.wss is set to false
|
||||
}
|
||||
|
||||
if (urlParams.has('nopreview') || urlParams.has('np')) {
|
||||
log("preview OFF");
|
||||
@ -1544,6 +1565,11 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
if (urlParams.has('easyexit') || urlParams.has('ee')) {
|
||||
session.noExitPrompt = true;
|
||||
}
|
||||
|
||||
if (urlParams.has('entrymsg') || urlParams.has('welcome')) {
|
||||
session.welcomeMessage = urlParams.get('entrymsg') || urlParams.get('welcome');
|
||||
session.welcomeMessage = decodeURIComponent(session.welcomeMessage);
|
||||
}
|
||||
|
||||
if (urlParams.has('videobitrate') || urlParams.has('bitrate') || urlParams.has('vb')) {
|
||||
session.bitrate = urlParams.get('videobitrate') || urlParams.get('bitrate') || urlParams.get('vb');
|
||||
@ -2335,6 +2361,10 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.screenshareid = session.streamID + "_screenshare";
|
||||
}
|
||||
}
|
||||
|
||||
if (urlParams.has('screensharevideoonly') || urlParams.has('ssvideoonly') || urlParams.has('ssvo')) {
|
||||
session.screenshareVideoOnly = true;
|
||||
}
|
||||
|
||||
if (urlParams.has('screensharefps') || urlParams.has('ssfps')) {
|
||||
if (urlParams.get('screensharefps') || urlParams.get('ssfps')) {
|
||||
@ -3221,7 +3251,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
var command = e.controller.number;
|
||||
var value = e.value;
|
||||
|
||||
midiHotkeysCommand(command, value)
|
||||
midiHotkeysCommand(command, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -3275,7 +3305,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
visAudioTimeout = setTimeout(function() {
|
||||
resetupAudioOut();
|
||||
activatedPreview=false;
|
||||
grabAudio("videosource", "#audioSource3");
|
||||
grabAudio("#audioSource3");
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
|
||||
634
mixer.html
634
mixer.html
@ -1,6 +1,6 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>IFRAME Example</title>
|
||||
<title>Scene Mixer - prototype</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
|
||||
<style>
|
||||
@ -13,9 +13,10 @@
|
||||
border:0;
|
||||
padding:0;
|
||||
display:block;
|
||||
width:1280px;
|
||||
width: calc(100vw - 330px);
|
||||
height:720px;
|
||||
background-color: #111;
|
||||
background-color: #0002;
|
||||
border-radius: 3px;
|
||||
}
|
||||
#viewlink {
|
||||
width:400px;
|
||||
@ -31,10 +32,12 @@
|
||||
button{
|
||||
padding:5px;
|
||||
margin:5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
canvas{
|
||||
padding:10px;
|
||||
cursor:pointer;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.thing {
|
||||
width: 100px;
|
||||
@ -46,9 +49,10 @@
|
||||
font-family: sans-serif;
|
||||
cursor: grab;
|
||||
text-align: center;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.empty {
|
||||
width: 100px;
|
||||
width: 108px;
|
||||
height: 2em;
|
||||
padding: 10px 0.5em 0 0.5em;
|
||||
margin: 0.5em;
|
||||
@ -57,18 +61,22 @@
|
||||
font-family: sans-serif;
|
||||
user-select: none;
|
||||
text-align: center;
|
||||
font-size: 70%;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.col {
|
||||
width: 130px;
|
||||
height: 450px;
|
||||
padding: 1em;
|
||||
height: calc(100vh - 20px);
|
||||
padding: 5px;
|
||||
border: 1px solid;
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
float: left;
|
||||
user-select: none;
|
||||
}
|
||||
.pressed{
|
||||
border: solid 2px black;
|
||||
background-color: #FFFA;
|
||||
}
|
||||
a{
|
||||
display:block;
|
||||
@ -78,8 +86,455 @@
|
||||
background-color: rgb(191 191 191);
|
||||
margin: 3px 0 10px 0;
|
||||
text-align: center;
|
||||
padding: 10px 15px 0 15px;
|
||||
padding: 10px 10px 0 15px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
@keyframes move {
|
||||
100% {
|
||||
transform: translate3d(0, 0, 1px) rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.background {
|
||||
position: fixed;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: #bfbfbf;
|
||||
overflow: hidden;
|
||||
z-index:-1;
|
||||
}
|
||||
|
||||
.background span {
|
||||
width: 50vmin;
|
||||
height: 50vmin;
|
||||
border-radius: 50vmin;
|
||||
backface-visibility: hidden;
|
||||
position: absolute;
|
||||
animation: move;
|
||||
animation-duration: 7;
|
||||
animation-timing-function: linear;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
|
||||
.background span:nth-child(0) {
|
||||
color: #a9a0bb;
|
||||
top: 26%;
|
||||
left: 54%;
|
||||
animation-duration: 133s;
|
||||
animation-delay: -143s;
|
||||
transform-origin: 17vw 23vh;
|
||||
box-shadow: 100vmin 0 13.032236536031524vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(1) {
|
||||
color: #888aa0;
|
||||
top: 32%;
|
||||
left: 60%;
|
||||
animation-duration: 98s;
|
||||
animation-delay: -19s;
|
||||
transform-origin: -9vw -17vh;
|
||||
box-shadow: -100vmin 0 13.361880379427102vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(2) {
|
||||
color: #a9a0bb;
|
||||
top: 76%;
|
||||
left: 30%;
|
||||
animation-duration: 27s;
|
||||
animation-delay: -382s;
|
||||
transform-origin: -21vw -12vh;
|
||||
box-shadow: -100vmin 0 13.29654068929897vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(3) {
|
||||
color: #a9a0bb;
|
||||
top: 13%;
|
||||
left: 3%;
|
||||
animation-duration: 89s;
|
||||
animation-delay: -71s;
|
||||
transform-origin: -5vw -23vh;
|
||||
box-shadow: -100vmin 0 13.269376230706396vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(4) {
|
||||
color: #888aa0;
|
||||
top: 98%;
|
||||
left: 83%;
|
||||
animation-duration: 61s;
|
||||
animation-delay: -57s;
|
||||
transform-origin: 19vw -16vh;
|
||||
box-shadow: 100vmin 0 13.465063933009704vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(5) {
|
||||
color: #4b6477;
|
||||
top: 73%;
|
||||
left: 100%;
|
||||
animation-duration: 312s;
|
||||
animation-delay: -390s;
|
||||
transform-origin: 23vw -6vh;
|
||||
box-shadow: -100vmin 0 12.719463296930117vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(6) {
|
||||
color: #888aa0;
|
||||
top: 6%;
|
||||
left: 84%;
|
||||
animation-duration: 176s;
|
||||
animation-delay: -255s;
|
||||
transform-origin: 16vw 3vh;
|
||||
box-shadow: -100vmin 0 13.358884039462355vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(7) {
|
||||
color: #888aa0;
|
||||
top: 99%;
|
||||
left: 9%;
|
||||
animation-duration: 221s;
|
||||
animation-delay: -385s;
|
||||
transform-origin: -16vw -9vh;
|
||||
box-shadow: 100vmin 0 13.435082385169103vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(8) {
|
||||
color: #a9a0bb;
|
||||
top: 8%;
|
||||
left: 92%;
|
||||
animation-duration: 142s;
|
||||
animation-delay: -99s;
|
||||
transform-origin: -1vw -14vh;
|
||||
box-shadow: -100vmin 0 13.456440775816723vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(9) {
|
||||
color: #a9a0bb;
|
||||
top: 80%;
|
||||
left: 70%;
|
||||
animation-duration: 99s;
|
||||
animation-delay: -124s;
|
||||
transform-origin: 21vw -10vh;
|
||||
box-shadow: 100vmin 0 13.007405893839119vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(10) {
|
||||
color: #888aa0;
|
||||
top: 42%;
|
||||
left: 2%;
|
||||
animation-duration: 70s;
|
||||
animation-delay: -341s;
|
||||
transform-origin: -15vw -23vh;
|
||||
box-shadow: 100vmin 0 13.005431373357645vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(11) {
|
||||
color: #a9a0bb;
|
||||
top: 28%;
|
||||
left: 2%;
|
||||
animation-duration: 244s;
|
||||
animation-delay: -369s;
|
||||
transform-origin: -17vw -16vh;
|
||||
box-shadow: 100vmin 0 13.351086475613746vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(12) {
|
||||
color: #4b6477;
|
||||
top: 80%;
|
||||
left: 50%;
|
||||
animation-duration: 117s;
|
||||
animation-delay: -399s;
|
||||
transform-origin: 24vw 8vh;
|
||||
box-shadow: 100vmin 0 12.979558964166843vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(13) {
|
||||
color: #888aa0;
|
||||
top: 74%;
|
||||
left: 65%;
|
||||
animation-duration: 283s;
|
||||
animation-delay: -50s;
|
||||
transform-origin: 13vw 14vh;
|
||||
box-shadow: 100vmin 0 13.282742227479792vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(14) {
|
||||
color: #888aa0;
|
||||
top: 64%;
|
||||
left: 61%;
|
||||
animation-duration: 194s;
|
||||
animation-delay: -278s;
|
||||
transform-origin: -6vw 4vh;
|
||||
box-shadow: -100vmin 0 13.333280580396286vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(15) {
|
||||
color: #a9a0bb;
|
||||
top: 11%;
|
||||
left: 86%;
|
||||
animation-duration: 403s;
|
||||
animation-delay: -329s;
|
||||
transform-origin: 3vw 0vh;
|
||||
box-shadow: -100vmin 0 13.1162690433691vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(16) {
|
||||
color: #4b6477;
|
||||
top: 14%;
|
||||
left: 59%;
|
||||
animation-duration: 100s;
|
||||
animation-delay: -15s;
|
||||
transform-origin: -23vw 21vh;
|
||||
box-shadow: -100vmin 0 13.30508866110655vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(17) {
|
||||
color: #888aa0;
|
||||
top: 68%;
|
||||
left: 45%;
|
||||
animation-duration: 394s;
|
||||
animation-delay: -137s;
|
||||
transform-origin: 18vw -20vh;
|
||||
box-shadow: -100vmin 0 12.809008306332636vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(18) {
|
||||
color: #a9a0bb;
|
||||
top: 7%;
|
||||
left: 33%;
|
||||
animation-duration: 132s;
|
||||
animation-delay: -346s;
|
||||
transform-origin: -22vw -17vh;
|
||||
box-shadow: -100vmin 0 12.940258664941906vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(19) {
|
||||
color: #a9a0bb;
|
||||
top: 24%;
|
||||
left: 65%;
|
||||
animation-duration: 49s;
|
||||
animation-delay: -44s;
|
||||
transform-origin: 0vw -24vh;
|
||||
box-shadow: -100vmin 0 12.733081490401828vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(20) {
|
||||
color: #888aa0;
|
||||
top: 98%;
|
||||
left: 49%;
|
||||
animation-duration: 204s;
|
||||
animation-delay: -160s;
|
||||
transform-origin: -1vw 3vh;
|
||||
box-shadow: -100vmin 0 13.05844646387434vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(21) {
|
||||
color: #a9a0bb;
|
||||
top: 2%;
|
||||
left: 29%;
|
||||
animation-duration: 294s;
|
||||
animation-delay: -272s;
|
||||
transform-origin: 13vw -18vh;
|
||||
box-shadow: -100vmin 0 12.626917095797205vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(22) {
|
||||
color: #a9a0bb;
|
||||
top: 73%;
|
||||
left: 32%;
|
||||
animation-duration: 424s;
|
||||
animation-delay: -59s;
|
||||
transform-origin: 19vw 3vh;
|
||||
box-shadow: 100vmin 0 13.092155905631065vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(23) {
|
||||
color: #888aa0;
|
||||
top: 45%;
|
||||
left: 93%;
|
||||
animation-duration: 277s;
|
||||
animation-delay: -215s;
|
||||
transform-origin: 0vw -14vh;
|
||||
box-shadow: 100vmin 0 12.768802405913084vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(24) {
|
||||
color: #4b6477;
|
||||
top: 35%;
|
||||
left: 40%;
|
||||
animation-duration: 375s;
|
||||
animation-delay: -205s;
|
||||
transform-origin: -16vw -21vh;
|
||||
box-shadow: -100vmin 0 12.845025825087218vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(25) {
|
||||
color: #a9a0bb;
|
||||
top: 82%;
|
||||
left: 77%;
|
||||
animation-duration: 211s;
|
||||
animation-delay: -150s;
|
||||
transform-origin: 15vw -14vh;
|
||||
box-shadow: 100vmin 0 12.825514275205975vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(26) {
|
||||
color: #4b6477;
|
||||
top: 99%;
|
||||
left: 95%;
|
||||
animation-duration: 342s;
|
||||
animation-delay: -118s;
|
||||
transform-origin: -16vw -10vh;
|
||||
box-shadow: 100vmin 0 13.09952938429165vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(27) {
|
||||
color: #a9a0bb;
|
||||
top: 24%;
|
||||
left: 43%;
|
||||
animation-duration: 191s;
|
||||
animation-delay: -249s;
|
||||
transform-origin: 10vw 25vh;
|
||||
box-shadow: -100vmin 0 12.948079018854608vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(28) {
|
||||
color: #888aa0;
|
||||
top: 35%;
|
||||
left: 83%;
|
||||
animation-duration: 38s;
|
||||
animation-delay: -5s;
|
||||
transform-origin: -15vw 21vh;
|
||||
box-shadow: -100vmin 0 12.884993041770123vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(29) {
|
||||
color: #4b6477;
|
||||
top: 50%;
|
||||
left: 19%;
|
||||
animation-duration: 83s;
|
||||
animation-delay: -367s;
|
||||
transform-origin: -17vw 24vh;
|
||||
box-shadow: 100vmin 0 12.943907699048086vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(30) {
|
||||
color: #4b6477;
|
||||
top: 94%;
|
||||
left: 43%;
|
||||
animation-duration: 139s;
|
||||
animation-delay: -151s;
|
||||
transform-origin: 15vw 13vh;
|
||||
box-shadow: -100vmin 0 13.188888046545854vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(31) {
|
||||
color: #4b6477;
|
||||
top: 1%;
|
||||
left: 30%;
|
||||
animation-duration: 276s;
|
||||
animation-delay: -118s;
|
||||
transform-origin: 20vw -13vh;
|
||||
box-shadow: 100vmin 0 12.67400347628477vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(32) {
|
||||
color: #a9a0bb;
|
||||
top: 62%;
|
||||
left: 91%;
|
||||
animation-duration: 179s;
|
||||
animation-delay: -95s;
|
||||
transform-origin: 21vw 0vh;
|
||||
box-shadow: 100vmin 0 13.078495151792405vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(33) {
|
||||
color: #a9a0bb;
|
||||
top: 62%;
|
||||
left: 24%;
|
||||
animation-duration: 176s;
|
||||
animation-delay: -417s;
|
||||
transform-origin: 11vw 1vh;
|
||||
box-shadow: -100vmin 0 13.180095388225237vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(34) {
|
||||
color: #4b6477;
|
||||
top: 44%;
|
||||
left: 7%;
|
||||
animation-duration: 15s;
|
||||
animation-delay: -23s;
|
||||
transform-origin: -5vw 24vh;
|
||||
box-shadow: -100vmin 0 12.99638150831451vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(35) {
|
||||
color: #888aa0;
|
||||
top: 41%;
|
||||
left: 18%;
|
||||
animation-duration: 52s;
|
||||
animation-delay: -66s;
|
||||
transform-origin: 10vw 18vh;
|
||||
box-shadow: 100vmin 0 12.881618623995024vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(36) {
|
||||
color: #888aa0;
|
||||
top: 32%;
|
||||
left: 75%;
|
||||
animation-duration: 377s;
|
||||
animation-delay: -252s;
|
||||
transform-origin: 19vw -21vh;
|
||||
box-shadow: -100vmin 0 13.235523992130878vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(37) {
|
||||
color: #4b6477;
|
||||
top: 26%;
|
||||
left: 96%;
|
||||
animation-duration: 352s;
|
||||
animation-delay: -359s;
|
||||
transform-origin: -22vw -3vh;
|
||||
box-shadow: 100vmin 0 13.203141789834469vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(38) {
|
||||
color: #4b6477;
|
||||
top: 63%;
|
||||
left: 64%;
|
||||
animation-duration: 9s;
|
||||
animation-delay: -70s;
|
||||
transform-origin: 16vw 10vh;
|
||||
box-shadow: 100vmin 0 12.63072769188053vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(39) {
|
||||
color: #a9a0bb;
|
||||
top: 69%;
|
||||
left: 81%;
|
||||
animation-duration: 56s;
|
||||
animation-delay: -361s;
|
||||
transform-origin: -17vw 11vh;
|
||||
box-shadow: 100vmin 0 13.123746520776026vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(40) {
|
||||
color: #888aa0;
|
||||
top: 54%;
|
||||
left: 33%;
|
||||
animation-duration: 142s;
|
||||
animation-delay: -2s;
|
||||
transform-origin: 4vw 24vh;
|
||||
box-shadow: 100vmin 0 13.216474278399133vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(41) {
|
||||
color: #4b6477;
|
||||
top: 56%;
|
||||
left: 10%;
|
||||
animation-duration: 65s;
|
||||
animation-delay: -105s;
|
||||
transform-origin: 3vw -24vh;
|
||||
box-shadow: 100vmin 0 13.322200697362886vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(42) {
|
||||
color: #4b6477;
|
||||
top: 2%;
|
||||
left: 39%;
|
||||
animation-duration: 213s;
|
||||
animation-delay: -62s;
|
||||
transform-origin: 4vw 10vh;
|
||||
box-shadow: -100vmin 0 12.580279613916804vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(43) {
|
||||
color: #888aa0;
|
||||
top: 100%;
|
||||
left: 49%;
|
||||
animation-duration: 12s;
|
||||
animation-delay: -71s;
|
||||
transform-origin: 9vw -21vh;
|
||||
box-shadow: 100vmin 0 13.356960223158397vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(44) {
|
||||
color: #a9a0bb;
|
||||
top: 75%;
|
||||
left: 59%;
|
||||
animation-duration: 286s;
|
||||
animation-delay: -81s;
|
||||
transform-origin: -6vw 18vh;
|
||||
box-shadow: 100vmin 0 12.718648874626872vmin currentColor;
|
||||
}
|
||||
.background span:nth-child(45) {
|
||||
color: #888aa0;
|
||||
top: 22%;
|
||||
left: 12%;
|
||||
animation-duration: 87s;
|
||||
animation-delay: -298s;
|
||||
transform-origin: -17vw 5vh;
|
||||
box-shadow: 100vmin 0 13.066314361220197vmin currentColor;
|
||||
}
|
||||
|
||||
</style>
|
||||
<script>
|
||||
|
||||
@ -114,6 +569,15 @@
|
||||
|
||||
function drag(ev) {
|
||||
ev.dataTransfer.setData("text", ev.target.id);
|
||||
var eles = document.querySelectorAll(".thing");
|
||||
for (var i=0;i<eles.length;i++){
|
||||
if (eles[i].id == ev.target.id){continue;}
|
||||
eles[i].style.boxShadow = "0px 0px 8px 2px #Fff";
|
||||
}
|
||||
var eles = document.querySelectorAll(".empty");
|
||||
for (var i=0;i<eles.length;i++){
|
||||
eles[i].style.boxShadow = "0px 0px 8px 2px #Fff";
|
||||
}
|
||||
}
|
||||
|
||||
function drop(ev) {
|
||||
@ -126,6 +590,16 @@
|
||||
ev.target.style.border = "";
|
||||
origThing.style.border = "";
|
||||
//var newThing = origThing.cloneNode(true);
|
||||
|
||||
var eles = document.querySelectorAll(".thing");
|
||||
for (var i=0;i<eles.length;i++){
|
||||
eles[i].style.boxShadow = "unset";
|
||||
}
|
||||
var eles = document.querySelectorAll(".empty");
|
||||
for (var i=0;i<eles.length;i++){
|
||||
eles[i].style.boxShadow = "unset";
|
||||
}
|
||||
|
||||
if (ev.target.classList.contains("thing")){
|
||||
//ev.target.parentNode.insertBefore(origThing, ev.target.nextSibling);
|
||||
//elem.parentNode.insertBefore(elem, elem.parentNode.firstChild);
|
||||
@ -133,13 +607,19 @@
|
||||
var slot = origThing.dataset.slot;
|
||||
origThing.dataset.slot = ev.target.dataset.slot;
|
||||
ev.target.dataset.slot = slot;
|
||||
var oldColor = origThing.style.backgroundColor;
|
||||
origThing.style.backgroundColor = ev.target.style.backgroundColor;
|
||||
ev.target.style.backgroundColor = oldColor;
|
||||
} else if (ev.target.classList.contains("empty")){
|
||||
|
||||
if (!ev.target.dataset.slot){return;}
|
||||
if (ev.target.dataset.slot=="undefined"){return;}
|
||||
if (ev.target.dataset.slot=="undefined"){return;}
|
||||
ev.target.parentNode.insertBefore(origThing, ev.target.nextSibling);
|
||||
|
||||
console.warn(origThing);
|
||||
|
||||
if (origThing.dataset.slot){
|
||||
if (origThing.dataset.slot && (origThing.dataset.slot!=="undefined")){
|
||||
document.querySelector(".empty[data-slot='"+origThing.dataset.slot+"']").style.display = "block";
|
||||
}
|
||||
origThing.dataset.slot = ev.target.dataset.slot;
|
||||
@ -237,8 +717,12 @@
|
||||
for (var i=0;i<layout.length;i++){
|
||||
//layout[i].z = i;
|
||||
if (!layout[i]){continue;}
|
||||
if (!("i" in layout[i])){continue;}
|
||||
|
||||
var stream = document.querySelector(".thing[data-slot='"+(i+1)+"'");
|
||||
var stream = document.querySelector(".thing[data-slot='"+(layout[i].i+1)+"'");
|
||||
console.log(stream);
|
||||
console.log(i);
|
||||
console.log(layout);
|
||||
if (!stream){continue;}
|
||||
combined[stream.dataset.sid] = layout[i];
|
||||
}
|
||||
@ -246,7 +730,7 @@
|
||||
var layout = null;
|
||||
combined = false;
|
||||
}
|
||||
|
||||
console.log(combined);
|
||||
iframe.contentWindow.postMessage({"scene":"0", "layout":combined}, '*');
|
||||
var layoutButtons = document.querySelectorAll("canvas[data-layout]");
|
||||
|
||||
@ -256,41 +740,6 @@
|
||||
this.classList.add("pressed");
|
||||
}
|
||||
|
||||
function activate(){
|
||||
console.log(this.dataset.layout);
|
||||
var layout = JSON.parse(this.dataset.layout);
|
||||
|
||||
iframe.contentWindow.postMessage({"target":"*", "remove":true}, '*');
|
||||
|
||||
|
||||
|
||||
for (var i=0;i<layout.length;i++){
|
||||
|
||||
var stream = document.querySelector(".thing[data-slot='"+(i+1)+"'");
|
||||
if (!stream){continue;}
|
||||
|
||||
var x = layout[i].x|| 0;
|
||||
var y = layout[i].y || 0;
|
||||
var w = layout[i].w || 0;
|
||||
var h = layout[i].h || 0;
|
||||
var cover = layout[i].c || false;
|
||||
|
||||
if (!(w && h)){continue;}
|
||||
|
||||
x = x + "%";
|
||||
y = y + "%";
|
||||
w = w + "%";
|
||||
h = h + "%";
|
||||
|
||||
if (cover){
|
||||
cover = "object-fit:cover;";
|
||||
} else {
|
||||
cover = "";
|
||||
}
|
||||
|
||||
iframe.contentWindow.postMessage({"target":stream.dataset.sid, "add":true, "settings":{"style": "width:"+w+";height:"+h+";position:absolute;left:"+x+";top:"+y+";display:block;"+cover}}, '*');
|
||||
}
|
||||
}
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Refresh list";
|
||||
@ -329,10 +778,17 @@
|
||||
var slots = document.getElementById("col1").children;
|
||||
for (var i=0;i<slots.length;i++){
|
||||
slots[i].style.backgroundColor = colors[i];
|
||||
slots[i].style.opacity = "0.4";
|
||||
slots[i].style.opacity = "0.9";
|
||||
}
|
||||
|
||||
function drawLayout(layoutOriginal){
|
||||
function addLayout(){
|
||||
var layout = prompt("Enter your new layout as a JSON string", '[{"x":0,"y":0,"w":100,"h":100}]');
|
||||
layout = JSON.parse(layout);
|
||||
console.log(layout);
|
||||
drawLayout(layout, true);
|
||||
}
|
||||
|
||||
function drawLayout(layoutOriginal, customlayout=false){
|
||||
|
||||
var layout = [];
|
||||
for (var i=0;i<layoutOriginal.length;i++){
|
||||
@ -361,7 +817,11 @@
|
||||
canvas.width="80";
|
||||
canvas.height="45";
|
||||
var ctx = canvas.getContext('2d');
|
||||
document.getElementById("container").appendChild(canvas);
|
||||
if (customlayout){
|
||||
document.getElementById("addlayout").parentNode.insertBefore(canvas, document.getElementById("addlayout"));
|
||||
} else {
|
||||
document.getElementById("container").appendChild(canvas);
|
||||
}
|
||||
ctx.beginPath();
|
||||
ctx.rect(0, 0, 80, 45);
|
||||
ctx.fillStyle = "#000";
|
||||
@ -382,7 +842,6 @@
|
||||
}
|
||||
|
||||
canvas.dataset.layout = JSON.stringify(layout);
|
||||
//canvas.onclick = activate;
|
||||
canvas.onclick = remoteActivate;
|
||||
|
||||
if (slotsNeeded<layout.length){
|
||||
@ -414,13 +873,36 @@
|
||||
|
||||
ctx.fillStyle = "#FFF";
|
||||
ctx.font = "15px Arial";
|
||||
ctx.fillText(" clear ", 4, 25);
|
||||
ctx.fillText(" Clear ", 16, 18);
|
||||
ctx.fillText(" Layout ", 12, 35);
|
||||
|
||||
canvas.dataset.layout = false;
|
||||
//canvas.onclick = activate;
|
||||
canvas.onclick = remoteActivate;
|
||||
|
||||
|
||||
}
|
||||
|
||||
function drawAddNewLayout(){
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width="80";
|
||||
canvas.height="45";
|
||||
var ctx = canvas.getContext('2d');
|
||||
document.getElementById("container").appendChild(canvas);
|
||||
ctx.beginPath();
|
||||
ctx.rect(0, 0, 80, 45);
|
||||
ctx.fillStyle = "#000";
|
||||
ctx.fill();
|
||||
|
||||
ctx.fillStyle = "#FFF";
|
||||
ctx.font = "15px Arial";
|
||||
ctx.fillText(" Add ", 20, 18);
|
||||
ctx.fillText(" Layout ", 12, 35);
|
||||
canvas.id = "addlayout";
|
||||
canvas.dataset.layout = false;
|
||||
canvas.onclick = addLayout;
|
||||
|
||||
|
||||
}
|
||||
|
||||
drawAutoLayout();
|
||||
@ -530,6 +1012,8 @@
|
||||
drawLayout(data);
|
||||
|
||||
|
||||
drawAddNewLayout();
|
||||
|
||||
|
||||
iframe.src = iframesrc;
|
||||
iframeContainer.appendChild(iframe);
|
||||
@ -589,5 +1073,53 @@
|
||||
</div>
|
||||
<div id="container">
|
||||
</div>
|
||||
<div class="background">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@ -36,7 +36,8 @@ body {
|
||||
|
||||
h1 {
|
||||
color: white;
|
||||
margin: 20px 0px;
|
||||
margin: 20px auto;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
h1 small {
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
</head>
|
||||
<body onload="loadIframe();">
|
||||
<h1>
|
||||
VDO.Ninja Speed Test
|
||||
VDO.Ninja's video streaming quality test
|
||||
</h1>
|
||||
<div id="container">
|
||||
</div>
|
||||
@ -42,22 +42,23 @@
|
||||
<li>Select your camera.</li>
|
||||
<li>Hit start</li>
|
||||
<li>
|
||||
Wait for the video to load side-by-side. *If it does not auto-load
|
||||
within 20s, refresh and try again.*
|
||||
Wait for the video to load side-by-side. *If it does not auto-load within 20s, refresh and try again.*
|
||||
</li>
|
||||
<li>
|
||||
Stats will load on the right-hand side of the page here. (or press
|
||||
CTRL + LeftClick on the new video to open stats that way)
|
||||
Stats will be printed to screen, along with graphs visualizing the most important metrics. You can also hold CTRL (cmd) + Click on the video to access even more stats.
|
||||
</li>
|
||||
<li>
|
||||
Bitrate, Buffer delay, and packet loss are important connection
|
||||
quality metrics
|
||||
Bitrate, Buffer delay, and packet loss are important connection quality metrics. Monitor them for at least a minute.
|
||||
</li>
|
||||
<li>
|
||||
Change the video bitrate by pressing the buttons below the video. It
|
||||
should approach 6000-kbps if the network allows.
|
||||
Change the video bitrate by pressing the buttons below the video. It should approach 6000-kbps if the network allows.
|
||||
</li>
|
||||
<li>
|
||||
Good packet loss will not exceed 0.1% and bad packet loss will exceed 1%. You can try testing against different global regions with the drop-down menu below.
|
||||
</li>
|
||||
<li>
|
||||
Check out <a href="https://youtu.be/je2ljlvLzlY" target="_blank" style='color:#DEF;'>this Youtube video</a> for more details and solutions to reduce packet loss if suffering from any.
|
||||
</li>
|
||||
|
||||
</ol>
|
||||
<div id="screen" style="color: #CCC; margin:10px 0;"><a href="./speedtest?screen" style="color: #CCC;">Test screen-sharing performance here</a></div>
|
||||
<div id="remote"></div>
|
||||
@ -69,9 +70,10 @@
|
||||
<option value="fr1">Strasbourg, France</option>
|
||||
<option value="bra1">São Paulo, Brazil</option>
|
||||
<option value="cae1">Montreal, Canada</option>
|
||||
<option value="use1">Virgina, USA</option>
|
||||
<option value="usc1">Chicago, USA</option>
|
||||
<option value="usw1">Los Angeles 1, USA</option>
|
||||
<option value="usw2">Los Angeles 2, USA</option>
|
||||
<option value="usw1">Los Angeles, USA</option>
|
||||
<option value="usw2">Oregon, USA</option>
|
||||
<option value="aus1">Sydney, Australia</option>
|
||||
<option value="jap1">Tokyo, Japan</option>
|
||||
<option value="sing1">Singapore</option>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
"join-room": "Unirse sala",
|
||||
"load-the-next-guest-in-queue": "Cargar el siguiente invitado en la cola",
|
||||
"toggle-the-chat": "Conmutar Chat",
|
||||
"mute-the-speaker": "Mute Orador",
|
||||
"mute-the-speaker": "Mutear Orador",
|
||||
"mute-the-mic": "Mute Micro",
|
||||
"disable-the-camera": "Desactivar Cámara",
|
||||
"share-a-screen-with-others": "Compartir Pantalla con otros",
|
||||
@ -78,27 +78,27 @@
|
||||
"add-this-video-to-any-remote-scene-1-": "Añadir este Video a '&scene=1' remoto",
|
||||
"mute-this-guest-everywhere": "Mute this guest everywhere",
|
||||
"add-this-video-to-any-remote-scene-2-": "Añadir este Video a '&scene=2' remoto",
|
||||
"remotely-mute-this-audio-in-all-remote-scene-views": "Remotely Mute this Audio in all remote '&scene' views",
|
||||
"add-to-scene-3": "Add to Scene 3",
|
||||
"add-to-scene-4": "Add to Scene 4",
|
||||
"add-to-scene-5": "Add to Scene 5",
|
||||
"add-to-scene-6": "Add to Scene 6",
|
||||
"add-to-scene-7": "Add to Scene 7",
|
||||
"add-to-scene-8": "Add to Scene 8",
|
||||
"remotely-mute-this-audio-in-all-remote-scene-views": "Silenciar este Audio de forma remota, en todas las vista (y escena)",
|
||||
"add-to-scene-3": "Añadir Escena 3",
|
||||
"add-to-scene-4": "Añadir Escena 4",
|
||||
"add-to-scene-5": "Añadir Escena 5",
|
||||
"add-to-scene-6": "Añadir Escena 6",
|
||||
"add-to-scene-7": "Añadir Escena 7",
|
||||
"add-to-scene-8": "Añadir Escena 8",
|
||||
"force-the-remote-sender-to-issue-a-keyframe-to-all-scenes-fixing-pixel-smearing-issues-": "Force the remote sender to issue a keyframe to all scenes, fixing Pixel Smearing issues.",
|
||||
"request-the-statistics-of-this-video-in-any-active-scene": "Request the statistics of this video in any active scene",
|
||||
"solo-this-video-everywhere": "Solo this video everywhere",
|
||||
"hide-this-guest-everywhere": "Hide this guest everywhere",
|
||||
"toggle-the-remote-guest-s-speaker-output": "Toggle the remote guest's speaker output",
|
||||
"toggle-the-remote-guest-s-display-output": "Toggle the remote guest's display output",
|
||||
"shift-this-video-down-in-order": "Shift this Video Down in Order",
|
||||
"current-index-order-of-this-video": "Current Index Order of this Video",
|
||||
"shift-this-video-up-in-order": "Shift this Video Up in Order",
|
||||
"remotely-reload-the-guest-s-page-with-a-new-url": "Remotely reload the guest's page with a new URL",
|
||||
"change-user-parameters": "Change user parameters",
|
||||
"request-the-statistics-of-this-video-in-any-active-scene": "Solicitar las estadisticas de este video en cualquier escena activa",
|
||||
"solo-this-video-everywhere": "Solamente este video en todas vistas",
|
||||
"hide-this-guest-everywhere": "Ocultar este video de todas las vistas",
|
||||
"toggle-the-remote-guest-s-speaker-output": "Alternar la salida de audio del invitado",
|
||||
"toggle-the-remote-guest-s-display-output": "Alternar la salida de pantalla del invitado",
|
||||
"shift-this-video-down-in-order": "Desplaza este Video en el orden",
|
||||
"current-index-order-of-this-video": "Orden del indice actual del Video",
|
||||
"shift-this-video-up-in-order": "Prioriza este Video en el orden",
|
||||
"remotely-reload-the-guest-s-page-with-a-new-url": "Vuelva a cargar la pagina del invitado con la nueva URL",
|
||||
"change-user-parameters": "Cambia los parametros del usuario",
|
||||
"start-recording-this-remote-stream-to-this-local-drive-experimental-": "Comenzar Grabación de este stream remoto en local. *experimental*'",
|
||||
"the-remote-guest-will-record-their-local-stream-to-their-local-drive-experimental-": "The Remote Guest will record their local stream to their local drive. *experimental*",
|
||||
"remotely-change-the-volume-of-this-guest": "Remotely change the volume of this guest",
|
||||
"the-remote-guest-will-record-their-local-stream-to-their-local-drive-experimental-": "El invitado grabara su transmisión en su unidad local. *experimental*",
|
||||
"remotely-change-the-volume-of-this-guest": "Cambiar remotamente el volumente de este invitado",
|
||||
"disable-video-preview": "Deshabilitar Previsualización",
|
||||
"low-quality-preview": "Previo Baja Calidad",
|
||||
"high-quality-preview": "Previo Alta Calidad",
|
||||
@ -403,4 +403,4 @@
|
||||
"confirm-disconnect-users": "Are you sure you wish to disconnect these users?",
|
||||
"confirm-disconnect-user": "Are you sure you wish to disconnect this user?"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user