recent updates; comms app,etc

This commit is contained in:
steveseguin 2022-10-27 08:22:45 -04:00
parent fbbc6c6c31
commit 25015a33a3
31 changed files with 8647 additions and 330 deletions

2140
comms.html Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,319 @@
<html>
<head>
<title>IFRAME Example</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>
body{
padding:0;
margin:0;
background-color: #0000;
}
iframe {
border:0;
margin:0;
padding:0;
display:block;
width:100%;
height:90%
}
#viewlink {
width:400px;
}
#container {
display:block;
padding:0px;
padding:0px;
}
input{
padding:5px;
margin:5px;
}
button{
padding:5px;
margin:5px;
}
</style>
<script>
function loadIframe(){
document.getElementById("container").innerHTML = "";
var iframe = document.createElement("iframe");
var iframeContainer = document.createElement("div");
iframe.allow = "autoplay;camera;microphone;fullscreen;picture-in-picture;display-capture;";
iframe.src = "../?dir=teststeve123&password=1234";
iframeContainer.appendChild(iframe);
document.getElementById("container").appendChild(iframeContainer);
var listOfStreamIDs = [
"1234_pov"
];
for (var i=0;i<listOfStreamIDs.length;i++){
var button = document.createElement("a");
button.innerHTML = "Invite "+listOfStreamIDs[i];
button.target = "_blank";
button.href = "../?room=teststeve123&password=1234&broadcast&transparent&autostart&nmb&nvb&gain=0&webcam&l=stevetest&push="+listOfStreamIDs[i];
iframeContainer.appendChild(button);
///////////////////
var button = document.createElement("button");
button.innerHTML = "speaker true "+listOfStreamIDs[i];
button.dataset.sid = listOfStreamIDs[i];
button.onclick = function(){
iframe.contentWindow.postMessage({
action: "speaker",
value: true,
target: this.dataset.sid
}, '*');
}; // target can be a stream ID or * for all.
iframeContainer.appendChild(button);
var button = document.createElement("button");
button.innerHTML = "speaker false "+listOfStreamIDs[i];
button.dataset.sid = listOfStreamIDs[i];
button.onclick = function(){
iframe.contentWindow.postMessage({
action: "speaker",
value: false,
target: this.dataset.sid
}, '*');
}; // target can be a stream ID or * for all.
iframeContainer.appendChild(button);
///////////////////
var button = document.createElement("button");
button.innerHTML = "display true "+listOfStreamIDs[i];
button.dataset.sid = listOfStreamIDs[i];
button.onclick = function(){
iframe.contentWindow.postMessage({
action: "display",
value: true,
target: this.dataset.sid
}, '*');
}; // target can be a stream ID or * for all.
iframeContainer.appendChild(button);
var button = document.createElement("button");
button.innerHTML = "display false "+listOfStreamIDs[i];
button.dataset.sid = listOfStreamIDs[i];
button.onclick = function(){
iframe.contentWindow.postMessage({
action: "display",
value: false,
target: this.dataset.sid
}, '*');
}; // target can be a stream ID or * for all.
iframeContainer.appendChild(button);
///////////////////
var button = document.createElement("button");
button.innerHTML = "MUTE true "+listOfStreamIDs[i];
button.dataset.sid = listOfStreamIDs[i];
button.onclick = function(){
iframe.contentWindow.postMessage({
action: "mic",
value: true,
target: this.dataset.sid
}, '*');
}; // target can be a stream ID or * for all.
iframeContainer.appendChild(button);
var button = document.createElement("button");
button.innerHTML = "UN-MUTE "+listOfStreamIDs[i];
button.dataset.sid = listOfStreamIDs[i];
button.onclick = function(){
iframe.contentWindow.postMessage({
action: "mic",
value: false,
target: this.dataset.sid
}, '*');
}; // target can be a stream ID or * for all.
iframeContainer.appendChild(button);
///////////////////
var button = document.createElement("button");
button.innerHTML = "addScene 1 toggle "+listOfStreamIDs[i];
button.dataset.sid = listOfStreamIDs[i];
button.onclick = function(){
iframe.contentWindow.postMessage({
action: "addScene",
value: 1,
target: this.dataset.sid
}, '*');
}; // target can be a stream ID or * for all.
iframeContainer.appendChild(button);
var button = document.createElement("button");
button.innerHTML = "Scene 1 toggle "+listOfStreamIDs[i];
button.dataset.sid = listOfStreamIDs[i];
button.onclick = function(){
iframe.contentWindow.postMessage({
action: "addScene",
value: "toggle",
target: this.dataset.sid
}, '*');
}; // target can be a stream ID or * for all.
iframeContainer.appendChild(button);
var button = document.createElement("button");
button.innerHTML = "add Scene 1"+listOfStreamIDs[i];
button.dataset.sid = listOfStreamIDs[i];
button.onclick = function(){
iframe.contentWindow.postMessage({
action: "addScene",
value: true,
target: this.dataset.sid
}, '*');
}; // target can be a stream ID or * for all.
iframeContainer.appendChild(button);
var button = document.createElement("button");
button.innerHTML = "remove Scene 1"+listOfStreamIDs[i];
button.dataset.sid = listOfStreamIDs[i];
button.onclick = function(){
iframe.contentWindow.postMessage({
action: "addScene",
value: false,
target: this.dataset.sid
}, '*');
}; // target can be a stream ID or * for all.
iframeContainer.appendChild(button);
///////////////////
///////////////////
var button = document.createElement("button");
button.innerHTML = "MUTE SCENE "+listOfStreamIDs[i];
button.dataset.sid = listOfStreamIDs[i];
button.onclick = function(){
iframe.contentWindow.postMessage({
action: "muteScene",
value: true,
target: this.dataset.sid
}, '*');
}; // target can be a stream ID or * for all.
iframeContainer.appendChild(button);
var button = document.createElement("button");
button.innerHTML = "un-mute Scene "+listOfStreamIDs[i];
button.dataset.sid = listOfStreamIDs[i];
button.onclick = function(){
iframe.contentWindow.postMessage({
action: "muteScene",
value: false,
target: this.dataset.sid
}, '*');
}; // target can be a stream ID or * for all.
iframeContainer.appendChild(button);
///////////////////
var button = document.createElement("button");
button.innerHTML = "soloChat "+listOfStreamIDs[i];
button.dataset.sid = listOfStreamIDs[i];
button.onclick = function(){
iframe.contentWindow.postMessage({
action: "soloChat",
value: true,
target: this.dataset.sid
}, '*');
}; // target can be a stream ID or * for all.
iframeContainer.appendChild(button);
var button = document.createElement("button");
button.innerHTML = "soloChat off"+listOfStreamIDs[i];
button.dataset.sid = listOfStreamIDs[i];
button.onclick = function(){
iframe.contentWindow.postMessage({
action: "soloChat",
value: false,
target: this.dataset.sid
}, '*');
}; // target can be a stream ID or * for all.
iframeContainer.appendChild(button);
}
//////////// LISTEN FOR EVENTS
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message";
/// If you have a routing system setup, you could have just one global listener for all iframes instead.
eventer(messageEvent, function (e) {
if (e.source != iframe.contentWindow){return} // reject messages send from other iframes
if (typeof e.data !== "object"){return;}
if ("action" in e.data){
var outputWindow = document.createElement("div");
outputWindow.innerHTML = "event: "+e.data.action+"<br />";
outputWindow.style.border="1px dotted black";
iframeContainer.appendChild(outputWindow);
}
if ("streamIDs" in e.data){
var outputWindow = document.createElement("div");
outputWindow.innerHTML = "streamID list:<br />";
for (var key in e.data.streamIDs) {
outputWindow.innerHTML += "streamID: " + key + ", label:"+e.data.streamIDs[key] + "\n";
}
outputWindow.style.border="1px dotted black";
iframeContainer.appendChild(outputWindow);
}
});
}
</script>
</head>
<body>
<div id="container">
<button onclick="loadIframe();">Go to Directors Room</button>
<br />
The password for guests is 1234<br />
<br />
<br />
Custom guest invites and toggles for add/removing from scene=1 are on the bottom.
</div>
</body>
</html>

View File

@ -57,8 +57,8 @@
<meta property="twitter:image" content="./media/vdoNinja_logo_full.png" />
<meta name="msapplication-TileColor" content="#da532c" />
<meta name="theme-color" content="#ffffff" />
<link rel="stylesheet" href="./main.css?ver=215" />
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/adapter.min.js"></script>
<link rel="stylesheet" href="./main.css?ver=221" />
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/adapter.js"></script>
<style id="lightbox-animations" type="text/css"></style>
<!-- <link rel="manifest" href="manifest.json" /> -->
<!-- ios support
@ -81,8 +81,9 @@
<span itemprop="thumbnail" itemscope itemtype="http://schema.org/ImageObject">
<link itemprop="url" href="./media/vdoNinja_logo_full.png" />
</span>
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/CodecsHandler.js?ver=37"></script>
<script type="text/javascript" crossorigin="anonymous" src="./webrtc.js?ver=521"></script>
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/CodecsHandler.js?ver=39"></script>
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/aes.js"></script>
<script type="text/javascript" crossorigin="anonymous" src="./webrtc.js?ver=529"></script>
<input id="zoomSlider" type="range" style="display: none;" />
<span id="electronDragZone" style="pointer-events: none; z-index:-10; position:absolute;top:0;left:0;width:100%;height:2%;-webkit-app-region: drag;min-height:20px;"></span>
<div id="header">
@ -133,81 +134,81 @@
<div id="obsState" class="hidden" >ACTIVE</div>
<div id="subControlButtons">
<div id="blindAllGuests" title="Blind all guests in room (toggle)" alt="Blind all guests in room (toggle)" onmousedown="event.preventDefault(); event.stopPropagation();" onclick="blindAllGuests(this, event)" tabindex="16" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;" >
<div id="blindAllGuests" title="Blind all guests in room (toggle)" alt="Blind all guests in room (toggle)" aria-label="Blind all guests in room" onmousedown="event.preventDefault(); event.stopPropagation();" onclick="blindAllGuests(this, event)" tabindex="16" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;" >
<i class="toggleSize las la-eye my-float"></i>
</div>
<div id="queuebutton" title="Load the next guest in queue" alt="Load the next guest in queue" onmousedown="event.preventDefault(); event.stopPropagation();" onclick="nextQueue()" tabindex="16" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;" >
<div id="queuebutton" title="Load the next guest in queue" alt="Load the next guest in queue" aria-label="Load next guest in queue" onmousedown="event.preventDefault(); event.stopPropagation();" onclick="nextQueue()" tabindex="16" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;" >
<i id="queuetoggle" class="toggleSize las la-stream my-float"></i>
<div id="queueNotification"></div>
</div>
<div id="sharefilebutton" title="Transfer any file to the group" alt="Transfer any file to the group" onmousedown="event.preventDefault(); event.stopPropagation();" onclick="toggleFileshare()" tabindex="16" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float" style="cursor: pointer;" >
<div id="sharefilebutton" title="Transfer any file to the group" alt="Transfer any file to the group" aria-label="Select file to transfer" onmousedown="event.preventDefault(); event.stopPropagation();" onclick="toggleFileshare()" tabindex="16" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float" style="cursor: pointer;" >
<i id="filesharetoggle" class="toggleSize las la-file-upload my-float"></i>
<div id="transferNotification"></div>
</div>
<div id="chatbutton" title="Toggle the Chat" alt="Toggle the Chat" onmousedown="event.preventDefault(); event.stopPropagation();" onclick="toggleChat()" tabindex="16" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;" >
<div id="chatbutton" title="Toggle the Chat" alt="Toggle the Chat" aria-label="Text chat" onmousedown="event.preventDefault(); event.stopPropagation();" onclick="toggleChat()" tabindex="16" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;" >
<i id="chattoggle" class="toggleSize las la-comment-alt my-float"></i>
<div id="chatNotification"></div>
</div>
<div id="mutespeakerbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Mute the Speaker" onclick="toggleSpeakerMute()" tabindex="17" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;" alt="Toggle the speaker output.">
<div id="mutespeakerbutton" onmousedown="event.preventDefault(); event.stopPropagation();" alt="Toggle the speaker output." aria-label="Mute Speaker output" title="Mute the Speaker" onclick="toggleSpeakerMute()" tabindex="17" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;" >
<i id="mutespeakertoggle" class="toggleSize las la-volume-up my-float" style="position: relative; top: 0.5px;"></i>
</div>
<div id="mutebutton" onmousedown="toggleMute(false, event);event.preventDefault(); event.stopPropagation();" title="Mute the Mic" ontouchstart="toggleMute(false, event);event.preventDefault(); event.stopPropagation();" tabindex="18" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;" alt="Toggle the mic">
<div id="mutebutton" onmousedown="toggleMute(false, event);event.preventDefault(); event.stopPropagation();" alt="Mute the Mic" aria-label="Mute Microphone" title="Mute the Mic" ontouchstart="toggleMute(false, event);event.preventDefault(); event.stopPropagation();" tabindex="18" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;">
<i id="mutetoggle" class="toggleSize las la-microphone my-float" style="position: relative; top: 0.5px;"></i>
</div>
<div id="mutevideobutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Disable the Camera" alt="Disable the Camera" onclick="toggleVideoMute()" tabindex="19" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;">
<div id="mutevideobutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Disable the Camera" alt="Disable the Camera" aria-label="Mute Camera" onclick="toggleVideoMute()" tabindex="19" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;">
<i id="mutevideotoggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-video my-float"></i>
</div>
<div id="screensharebutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Share a Screen with others" alt="Share a Screen with others" onclick="screenshareTypeDecider(1)" tabindex="20" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden task" data-menu="context-menu-screen-share" style="cursor: pointer;">
<div id="screensharebutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Share a Screen with others" alt="Share a Screen with others" aria-label="Share a screen" onclick="screenshareTypeDecider(1)" tabindex="20" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden task" data-menu="context-menu-screen-share" style="cursor: pointer;">
<i id="screensharetoggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-desktop my-float"></i>
</div>
<div id="screenshare2button" onmousedown="event.preventDefault(); event.stopPropagation();" title="Add a Screen Share" alt="Add a Screen Share" onclick="screenshareTypeDecider(2)" tabindex="20" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden task" data-menu="context-menu-screen-share" style="cursor: pointer;">
<div id="screenshare2button" onmousedown="event.preventDefault(); event.stopPropagation();" title="Add a Screen Share" alt="Add a Screen Share" aria-label="Share a screen" onclick="screenshareTypeDecider(2)" tabindex="20" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden task" data-menu="context-menu-screen-share" style="cursor: pointer;">
<i id="screenshare2toggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-tv my-float"></i>
</div>
<div id="screenshare3button" onmousedown="event.preventDefault(); event.stopPropagation();" title="Create a Third Stream" alt="Create a Third Stream" onclick="screenshareTypeDecider(3)" tabindex="20" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden task" data-menu="context-menu-screen-share" style="cursor: pointer;">
<div id="screenshare3button" onmousedown="event.preventDefault(); event.stopPropagation();" title="Share a Screen with others" alt="Add a Screen Share" aria-label="Share a screen" onclick="screenshareTypeDecider(3)" tabindex="20" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden task" data-menu="context-menu-screen-share" style="cursor: pointer;">
<i id="screenshare3toggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-tv my-float"></i>
</div>
<div id="websitesharebutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Share a website with your guests (IFRAME)" alt="Share a website with your guests (IFRAME)" onclick="shareWebsite(false, event)" tabindex="21" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden" style="cursor: pointer;">
<div id="websitesharebutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Share a website with your guests (IFRAME)" aria-label="Share a website" alt="Share a website with your guests (IFRAME)" onclick="shareWebsite(false, event)" tabindex="21" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden" style="cursor: pointer;">
<i id="websitesharetoggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-window-maximize my-float"></i>
</div>
<div id="websitesharebutton2" onmousedown="event.preventDefault(); event.stopPropagation();" title="Hold CTRL (or CMD) and click to spotlight this video" alt="Share a website as an embedded iFRAME" onclick="shareWebsite(false, event)" tabindex="21" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float2 orange shake hidden" style="cursor: pointer;max-width: 200px;margin: auto;padding: 0 10px;">
<div id="websitesharebutton2" onmousedown="event.preventDefault(); event.stopPropagation();" title="Hold CTRL (or CMD) and click to spotlight this video" alt="Share a website as an embedded iFRAME" aria-label="Share a website" onclick="shareWebsite(false, event)" tabindex="21" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float2 orange shake hidden" style="cursor: pointer;max-width: 200px;margin: auto;padding: 0 10px;">
<i onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las my-float la-window-close" style="display: inline-block;"></i>
<div style="display: inline-block;width: 85px;line-height: 1; font-size: 0.9em;">
Stop Sharing Website
</div>
</div>
<div id="flipcamerabutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Cycle the Cameras" onclick="cycleCameras()" class="hidden float" tabindex="21" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" alt="Cycle the Cameras">
<div id="flipcamerabutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Cycle the Cameras" onclick="cycleCameras()" class="hidden float" tabindex="21" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" aria-label="Cycle Cameras" alt="Cycle the Cameras">
<i id="settingstoggle" class="toggleSize las la-sync-alt my-float"></i>
</div>
<div id="obscontrolbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="OBS Remote Controller; start/stop and change scenes." onclick="toggleOBSControls();" class="hidden float" tabindex="22" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" alt="Toggle the Remote OBS Controls Menu">
<div id="obscontrolbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="OBS Remote Controller; start/stop and change scenes." onclick="toggleOBSControls();" class="hidden float" tabindex="22" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" aria-label="Remote OBS control menu" alt="Toggle the Remote OBS Controls Menu">
<i id="obscontroltoggle" class="toggleSize las la-gamepad my-float"></i>
</div>
<div id="roomsettingsbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Room Settings" onclick="toggleRoomSettings();" class="hidden float" tabindex="22" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" alt="Toggle the Room Settings Menu">
<div id="roomsettingsbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Room Settings" onclick="toggleRoomSettings();" class="hidden float" tabindex="22" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" alt="Toggle the Room Settings Menu" aria-label="Room settings menu">
<i id="roomsettingstoggle" class="toggleSize las la-users-cog my-float"></i>
</div>
<div id="settingsbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Your audio and video Settings" onclick="toggleSettings()" class="hidden float" tabindex="22" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" alt="Toggle Settings Menu">
<div id="settingsbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Your audio and video Settings" onclick="toggleSettings()" class="hidden float" tabindex="22" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" alt="Toggle Settings Menu" aria-label="Settings menu">
<i id="settingstoggle" class="toggleSize las la-cog my-float"></i>
</div>
<div id="hangupbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Hangup the Call" alt="Hangup the Call" onclick="hangup()" class="hidden float" tabindex="23" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" >
<div id="hangupbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Hangup the Call" aria-label="Hang up" alt="Hangup the Call" onclick="hangup()" class="hidden float" tabindex="23" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" >
<i class="toggleSize my-float las la-phone rotate225" aria-hidden="true"></i>
</div>
<div id="raisehandbutton" onmousedown="event.preventDefault(); event.stopPropagation();" data-raised="0" title="Alert the host you want to speak" alt="Alert the host you want to speak" tabindex="24" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" onclick="raisehand()" class="hidden float" style="cursor: pointer;">
<div id="raisehandbutton" onmousedown="event.preventDefault(); event.stopPropagation();" data-raised="0" title="Alert the host you want to speak" aria-label="Raise hand" alt="Alert the host you want to speak" tabindex="24" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" onclick="raisehand()" class="hidden float" style="cursor: pointer;">
<i class="toggleSize my-float las la-hand-paper" style="position: relative; right: 1px;" aria-hidden="true"></i>
</div>
<div id="recordLocalbutton" onmousedown="event.preventDefault(); event.stopPropagation();" data-state="0" title="Record your stream to disk" alt="Record your stream to disk" tabindex="25" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" onclick="recordLocalVideoToggle();" class="hidden float" style="cursor: pointer;">
<div id="recordLocalbutton" onmousedown="event.preventDefault(); event.stopPropagation();" data-state="0" title="Record your stream to disk" aria-label="Record your stream to disk" alt="Record your stream to disk" tabindex="25" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" onclick="recordLocalVideoToggle();" class="hidden float" style="cursor: pointer;">
<i class="toggleSize my-float las la-dot-circle" style="position: relative;" aria-hidden="true"></i>
</div>
<span id="miniPerformer" style="pointer-events: auto;" class="hidden"></span>
<span id="rooms" class="hidden" style="padding-top:3px;padding-left:6px;pointer-events: auto;color:#fff;"></span>
<span id="groups" class="hidden" style="padding-top:3px;padding-left:6px;pointer-events: auto;color:#fff;text-align: center;"></span>
<div id="hangupbutton2" onmousedown="event.preventDefault(); event.stopPropagation();" title="Cancel the Director's Video/Audio" onclick="hangup2()" class="hidden float" tabindex="26" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" alt="Disconnect Direcotor's cam">
<div id="hangupbutton2" onmousedown="event.preventDefault(); event.stopPropagation();" title="Cancel the Director's Video/Audio" onclick="hangup2()" class="hidden float" tabindex="26" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" aria-label="stop publishing audio and video" alt="Disconnect Direcotor's cam">
<i class="toggleSize my-float las la-phone rotate225" aria-hidden="true"></i>
</div>
</div>
@ -229,7 +230,7 @@
>
<i style="float: right; bottom: 0px; cursor: pointer; position: fixed; right: 33px; color: #d9e4eb; padding: 2px; margin: 2px 2px 0 0; font-size: 140%;" class="las la-question-circle" aria-hidden="true"></i>
</span>
<span title="Language Options" onclick="toggle(document.getElementById('languages'));" id="translateButton">
<span title="Language Options" onclick="toggle(document.getElementById('languages'));" aria-label="language options" aria-pressed="false" id="translateButton">
<i style="float: right; bottom: 0px; cursor: pointer; position: fixed; right: 10px; color: #d9e4eb; padding: 2px; margin: 2px 2px 0 0; font-size: 140%;" class="las la-language" aria-hidden="true"></i>
</span>
<span title="Add to Calendar" onclick="toggle(document.getElementById('calendar'));" id="calendarButton">
@ -373,7 +374,7 @@
<span data-translate="ask-for-permissions">Allow Access to Camera/Microphone</span>
</button>
<span style="display:block;">
<button onclick="publishWebcam(this)" title="start streaming" tabindex="15" id="gowebcam" class="gowebcam" alt="Start Streaming" disabled data-audioready="false" data-ready="false" >
<button onclick="publishWebcam(this)" title="start streaming" aria-label="Start streaming" aria-pressed="false" tabindex="15" id="gowebcam" class="gowebcam" alt="Start Streaming" disabled data-audioready="false" data-ready="false" >
<span data-translate="waiting-for-camera">Waiting for Camera to Load</span>
</button>
</span>
@ -390,7 +391,7 @@
<span id="videoMenu" class="videoMenu">
<span style="padding-right:2px;display:inline-block;position:relative;top:1px;"><i class="las la-video"></i><span data-translate="video-source"> Video Source </span></span>
<span style="display:inline-block;padding-top: 5px;">
<select id="videoSourceSelect" ></select>
<select id="videoSourceSelect" alt="Video source list"></select>
<span id="gear_webcam" onclick="toggle(document.getElementById('videoSettings'));">
<i class="las la-cog" style="font-size: 140%; vertical-align: middle;" aria-hidden="true"></i>
</span>
@ -404,17 +405,17 @@
<center>
<span id="videoSettings" style="display: none;">
<form id="webcamquality">
<input type="radio" id="fullhd" name="resolution" value="0" />
<input type="radio" id="fullhd" alt="1080p60 video capture" name="resolution" value="0" />
<label for="fullhd">
<span data-translate="max-resolution">Max Resolution</span>
</label> |
<input type="radio" checked id="halfhd" name="resolution" value="1" />
<input type="radio" checked id="halfhd" alt="720p60 video capture" name="resolution" value="1" />
<label for="halfhd">
<span data-translate="balanced">Balanced</span>
</label> |
<input type="radio" id="nothd" name="resolution" value="2" />
<input type="radio" id="nothd" name="resolution" alt="360p30 video capture" value="2" />
<label for="nothd">
<span data-translate="smooth-cool">Smooth and Cool</span>
</label>
@ -424,7 +425,7 @@
</center>
<div id="audioMenu" class="form-group multiselect" alt="tip: Hold CTRL (command) to select Multiple" title="tip: Hold CTRL (command) to select Multiple">
<span class='gear_microphone hidden'>
<input type="checkbox" id='micStereoMonoInput' onchange="toggleMonoStereoMic(this);">Mono
<input type="checkbox" id='micStereoMonoInput' alt="Mono microphone audio" onchange="toggleMonoStereoMic(this);">Mono
</span>
<a id="multiselect-trigger" class="form-control multiselect-trigger" >
<div class="audioTitle">
@ -451,7 +452,7 @@
<div class="audioTitle2">
<i class="las la-headphones"></i><span data-translate="select-output-source"> Audio Output Destination
</span><button onclick="playtone()" class="white" style="margin:0 0 0 15px;padding: 2px 10px 0px 10px;" type="button">Test</button></div>
<select id="outputSource" ></select>
<select id="outputSource" alt="Audio output device" ></select>
<div id="headphoneTip1" class="cameraTip hidden">
<i class="las la-info-circle"></i>
<p><span id="headphoneTipContext1"></span></p>
@ -479,7 +480,7 @@
<div style="text-align: left;display: inline-block;">
<i class="las la-robot"></i><span data-translate="select-digital-effect"> Digital Video Effects </span>
</div>
<select id="effectSelector" onchange="effectsDynamicallyUpdate(event, this);">
<select id="effectSelector" alt="Digital video effect options" onchange="effectsDynamicallyUpdate(event, this);">
<option value="0" data-translate="no-effects-applied">No effects applied</option>
<option value="3" data-translate="blurred-background">Blurred background</option>
<option value="4" data-translate="digital-greenscreen">Digital greenscreen</option>
@ -716,7 +717,7 @@
</span>
</div>
</div>
<div>See the
<div class="invite_setting_group_links">See the
<a style="text-decoration: none; color: blue;" target="_blank" href="https://docs.vdo.ninja/advanced-settings">documentation</a> for a list of all options and details.<br /><br />
Try out the advanced <a style="text-decoration: none; color: blue;" target="_blank" href="https://invite.vdo.ninja/">invite generator</a> here as well.
</div>
@ -805,7 +806,17 @@
</div>
<div id="container-8" class="column columnfade pointer rounded card hidden" style="overflow: hidden;" onclick="window.location = './mixer.html';">
<h2><span data-translate="try-the-mixer-out">Try out the Mixer</span></h2>
<h2><span data-translate="try-the-mixer-out">Create layouts with Mixer</span></h2>
<i style="margin-top:30px;font-size:600%;overflow:hidden;" class="las la-blender"></i>
</div>
<div id="container-14" class="column columnfade pointer rounded card hidden" style="overflow: hidden;" onclick="window.location = 'https://versus.cam';">
<h2><span data-translate="try-out-versus-cam">Manage streams with Versus</span></h2>
<i style="margin-top:30px;font-size:600%;overflow:hidden;" class="las la-blender"></i>
</div>
<div id="container-15" class="column columnfade pointer rounded card hidden" style="overflow: hidden;" onclick="window.location = './comms.html';">
<h2><span data-translate="voice-comms-app">Production voice comms</span></h2>
<i style="margin-top:30px;font-size:600%;overflow:hidden;" class="las la-blender"></i>
</div>
@ -873,7 +884,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 August 2022. <a target="_blank" href="https://docs.vdo.ninja/releases/v21">v21 release notes</a>. If having new issues, the previous version <a href="https://vdo.ninja/v20/">is here</a>, and the <a href="https://vdo.ninja/beta/">upcoming next version is here</a>. Development <a target="_blank" href='https://updates.vdo.ninja/'>updates are here.</a>
Site updated October 2022. <a target="_blank" href="https://docs.vdo.ninja/releases/v21">v21 release notes</a>. If having new issues, the previous version <a href="https://vdo.ninja/v20/">is here</a>, and the <a href="https://vdo.ninja/beta/">upcoming next version is here</a>. Development <a target="_blank" href='https://updates.vdo.ninja/'>updates are here.</a>
<br />
<br />
<h3>
@ -1950,7 +1961,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" id="welcomeMsg" data-translate='welcome-to-obs-ninja-chat'>
<div class="inMessage" id="welcomeMsg" data-translate='welcome-to-vdo-ninja-chat'>
Welcome to VDO.Ninja! You can send text messages directly to connected peers from here.
</div>
</div>
@ -1971,6 +1982,22 @@
<input id="highlightDirector" style="width: 15px; height: 15px; margin:10px;" name="highlightDirector" data-action-type="solo-video" type="checkbox" onchange="requestInfocus(this);" />
<label for="highlightDirector" data-translate="highlight-director-only-video-guests-will-see">Highlight Director (only video guests will see)</label>
</span>
<span style="margin: 20px 0 0 0;display:block" id='globalTimerDirectorSpan'>
<button data-action-type="create-timer-global" title="Set a countdown timer that this guest sees. CTRL (cmd) + click to pause." onclick="directTimer(this, event);">
<i class="las la-clock"></i>
<span data-translate="create-global-timer">Create Global Count-down Timer</span>
</button>
<button data-action-type="create-timer-up-global" title="Set a count-up timer that this guest sees. CTRL (cmd) + click to pause." onclick="directTimer(this, event);">
<i class="las la-clock"></i>
<span data-translate="create-global-up-timer">Create Global Count-up Timer</span>
</button>
<button data-action-type="create-clock-global" title="Set a count-up timer that this guest sees. CTRL (cmd) + click to pause." onclick="directTimer(this, event);">
<i class="las la-clock"></i>
<span data-translate="create-clock-timer">Toggle Room Clock</span>
</button>
</span>
<span style="margin: 5px 0 0 0;display:block" id='enableCodirector' title="Allow for remote co-directors">
<span id="coDirectorEnableSpan">
<input id="coDirectorEnable" style="width: 15px; height: 15px; margin:10px;" name="coDirectorEnable" data-action-type="codirector" type="checkbox" onchange="toggleCoDirector(this);" />
@ -2076,7 +2103,7 @@
<div id="connectUsers">
<div style="margin-bottom:5px"><u ><span data-translate="invisible-guests">Not Visible</span></u>
<span title="Hide this window" style="cursor:pointer;font-size:1.2em; float: right;" onclick="session.showList=false;getById('connectUsers').style.display = 'none';"><i class="las la-times"></i></span></div>
<span title="Hide this window" id='hideusers' style="cursor:pointer;font-size:1.2em; float: right;" onclick="session.showList=false;getById('connectUsers').style.display = 'none';"><i class="las la-times"></i></span></div>
<span style="height:5px;display:block;"></span>
<div id="userList">
</div>
@ -2194,7 +2221,7 @@
var session = WebRTC.Media; // session is a required global variable if configuring manually. Run before loading main.js but after webrtc.js.
session.version = "22.4";
session.version = "22.5";
session.streamID = session.generateStreamID(); // randomly generates a streamID for this session. You can set your own programmatically if needed
session.defaultPassword = "someEncryptionKey123"; // Change this password if self-deploying for added security/privacy
@ -2265,12 +2292,11 @@
// session.darkmode = false; // enable or disable the dark style theme as the default
// session.defaultBackgroundImages = ["./media/bg_sample1.webp", "./media/bg_sample2.webp"]; // for &effects=5 (virtual backgrounds)
</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=488"></script>
<script type="text/javascript" crossorigin="anonymous" id="lib-js" src="./lib.js?ver=511"></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=445"></script>
<script type="text/javascript" crossorigin="anonymous" id="main-js" src="./main.js?ver=461"></script>
</body>
</html>

648
lib.js

File diff suppressed because it is too large Load Diff

View File

@ -277,7 +277,7 @@ button.white:active {
}
#header {
width: 100%;
margin: 1px;
padding: 1px;
background-color: #0F131D;
color: #FFF;
-webkit-app-region: drag;
@ -1351,7 +1351,9 @@ body {
display:block;
z-index:10;
}
div[data-action-type='toggle-group'] {
padding: 0 10px;
}
.infoblob {
color: white;
width: 100%;
@ -2617,11 +2619,13 @@ button.toggleSettings{
font-size: 100%;
}
#minipreview > #videosource {
height:auto!important;
width:auto!important;
max-height:100%!important;
max-width:100%!important;
border-radius: 0!important;
}
#videoSourceSelect {
@ -3787,9 +3791,6 @@ input:checked + .slider:before {
margin: 0px auto 10px auto;
}
.darktheme .startupWarning{
}
#alertModal {
position: absolute;
background-color: rgb(221 221 221);
@ -4369,4 +4370,7 @@ body.darktheme .containerGreen{
}
body.darktheme .startupWarning>.las {
color:white!important;
}
body.darktheme .invite_setting_group_links a {
color:#d2e5ff!important;
}

172
main.js
View File

@ -345,10 +345,6 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
}
// flagship
if (urlParams.has('broadcast') || urlParams.has('bc')) {
log("Broadcast flag set");
session.broadcast = urlParams.get('broadcast') || urlParams.get('bc') || null;
@ -389,6 +385,9 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
session.showList = true;
}
}
if (session.showList===true){
getById("hideusers").classList.add("hidden");
}
if (urlParams.has('meshcast')) {
session.meshcast = urlParams.get('meshcast') || "any";
@ -398,37 +397,39 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
var filename = false;
try {
filename = window.location.pathname.substring(window.location.pathname.lastIndexOf('/') + 1);
filename = filename.replace("??", "?");
filename2 = filename.split("?")[0];
// split at ???
if (filename.split(".").length == 1) {
if (filename2.length < 2) { // easy win
filename = false;
} else if (filename.startsWith("&")) { // easy win
var tmpHref = window.location.href.substring(0, window.location.href.lastIndexOf('/')) + "/?" + filename.split("&").slice(1).join("&");
log("TMP " + tmpHref);
updateURL(filename.split("&")[1], true, tmpHref);
filename = false;
} else if (filename2.split("&")[0].includes("=")) {
log("asdf " + filename.split("&")[0]);
if (history.pushState) {
var tmpHref = window.location.href.substring(0, window.location.href.lastIndexOf('/'));
tmpHref = tmpHref + "/?" + filename;
if (!session.decrypted){
filename = window.location.pathname.substring(window.location.pathname.lastIndexOf('/') + 1);
filename = filename.replace("??", "?");
filename2 = filename.split("?")[0];
// split at ???
if (filename.split(".").length == 1) {
if (filename2.length < 2) { // easy win
filename = false;
//warnUser("Please ensure your URL is correctly formatted.");
window.history.pushState({path: tmpHref.toString()}, '', tmpHref.toString());
} else if (filename.startsWith("&")) { // easy win
var tmpHref = window.location.href.substring(0, window.location.href.lastIndexOf('/')) + "/?" + filename.split("&").slice(1).join("&");
log("TMP " + tmpHref);
updateURL(filename.split("&")[1], true, tmpHref);
filename = false;
} else if (filename2.split("&")[0].includes("=")) {
log("asdf " + filename.split("&")[0]);
if (history.pushState) {
var tmpHref = window.location.href.substring(0, window.location.href.lastIndexOf('/'));
tmpHref = tmpHref + "/?" + filename;
filename = false;
//warnUser("Please ensure your URL is correctly formatted.");
window.history.pushState({path: tmpHref.toString()}, '', tmpHref.toString());
}
} else {
filename = filename2.split("&")[0];
if (filename2 != filename) {
warnUser("Warning: Please ensure your URL is correctly formatted.");
}
}
} else {
filename = filename2.split("&")[0];
if (filename2 != filename) {
warnUser("Warning: Please ensure your URL is correctly formatted.");
}
filename = false;
}
} else {
filename = false;
log(filename);
}
log(filename);
} catch (e) {
errorlog(e);
}
@ -454,8 +455,8 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
}
session.slotmode = false; // temporary; remove in the future TODO: ## -----------------------
if (urlParams.has('slotmode')){
session.slotmode = parseInt(urlParams.get('slotmode')) || 1;
if (urlParams.has('slotmode') || urlParams.has('slotsmode')){
session.slotmode = parseInt(urlParams.get('slotmode')) || parseInt(urlParams.get('slotsmode')) || 1;
}
@ -698,6 +699,19 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
}
}
}
if (urlParams.has('layouts')) { // an ordered array of layouts, which can be used to switch between using the API layouts action.
// ie: ?layouts=[[{"x":0,"y":0,"w":100,"h":100,"slot":0}],[{"x":0,"y":0,"w":100,"h":100,"slot":1}],[{"x":0,"y":0,"w":100,"h":100,"slot":2}],[{"x":0,"y":0,"w":100,"h":100,"slot":3}],[{"x":0,"y":0,"w":50,"h":100,"c":false,"slot":0},{"x":50,"y":0,"w":50,"h":100,"c":false,"slot":1}],[{"x":0,"y":0,"w":100,"h":100,"z":0,"c":false,"slot":1},{"x":70,"y":70,"w":30,"h":30,"z":1,"c":true,"slot":0}],[{"x":0,"y":0,"w":50,"h":50,"c":true,"slot":0},{"x":50,"y":0,"w":50,"h":50,"c":true,"slot":1},{"x":0,"y":50,"w":50,"h":50,"c":true,"slot":2},{"x":50,"y":50,"w":50,"h":50,"c":true,"slot":3}],[{"x":0,"y":16.667,"w":66.667,"h":66.667,"c":true,"slot":0},{"x":66.667,"y":0,"w":33.333,"h":33.333,"c":true,"slot":1},{"x":66.667,"y":33.333,"w":33.333,"h":33.333,"c":true,"slot":2},{"x":66.667,"y":66.667,"w":33.333,"h":33.333,"c":true,"slot":3}]]
try {
session.layouts = JSON.parse(decodeURIComponent(urlParams.get('layouts'))) || JSON.parse(urlParams.get('layouts')) || {};
} catch(e){
try {
session.layouts = JSON.parse(urlParams.get('layouts')) || false;
} catch(e){
session.layouts = false;
}
}
}
if (urlParams.has('deaf') || urlParams.has('deafen')) {
session.directorSpeakerMuted=true; // false == true in this case.
@ -1261,6 +1275,28 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
}
}
}
} else if (urlParams.has('labelsuggestion') || urlParams.has('ls')) {
session.label = urlParams.get('labelsuggestion') || urlParams.get('ls') || null;
var updateURLAsNeed = true;
window.focus();
var label = await promptAlt(miscTranslations["enter-display-name"], true);
if (label) {
session.label = sanitizeLabel(label); // alphanumeric was too strict.
} else {
session.label = sanitizeLabel(session.label);
updateURLAsNeed = false;
}
document.title = session.label; // what the result is.
if (updateURLAsNeed) {
var label = encodeURIComponent(session.label);
if (urlParams.has('l')) {
updateURL("l=" + label, true, false);
} else {
updateURL("label=" + label, true, false);
}
}
}
if (urlParams.has('transparent') || urlParams.has('transparency')) { // sets the window to be transparent - useful for IFRAMES?
@ -1778,10 +1814,10 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
//session.manual=true;
//innerHTML =
}
if (urlParams.has('keyframeinterval') || urlParams.has('keyframeRate') || urlParams.has('keyframe') || urlParams.has('fki')) {
if (urlParams.has('keyframeinterval') || urlParams.has('keyframerate') || urlParams.has('keyframe') || urlParams.has('fki')) {
log("keyframeRate ENABLED");
session.keyframeRate = parseInt(urlParams.get('keyframeinterval') || urlParams.get('keyframeRate') || urlParams.get('keyframe') || urlParams.get('fki')) || 0;
session.keyframeRate = parseInt(urlParams.get('keyframeinterval') || urlParams.get('keyframerate') || urlParams.get('keyframe') || urlParams.get('fki')) || 0;
}
if (urlParams.has('obsoff') || urlParams.has('oo') || urlParams.has('disableobs')) {
@ -2247,6 +2283,10 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
session.groupAudio = true;
}
if (urlParams.has('groupmode') || urlParams.has('gm')) {
session.allowNoGroup = true;
}
if (urlParams.has('host')) {
session.roomhost = true;
}
@ -3329,21 +3369,20 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
}
}
}
if (session.roomid || urlParams.has('roomid') || urlParams.has('r') || urlParams.has('room') || filename || (session.permaid !== false)) {
var roomid = "";
if (urlParams.has('room')) { // needs to be first; takes priority
roomid = urlParams.get('room');
} else if (filename) {
roomid = filename;
} else if (urlParams.has('roomid')) {
roomid = urlParams.get('roomid');
} else if (urlParams.has('r')) {
roomid = urlParams.get('r');
} else if (session.roomid) {
roomid = session.roomid;
}
} else if (filename) {
roomid = filename;
}
session.roomid = sanitizeRoomName(roomid);
}
@ -3544,6 +3583,8 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
getById("container-11").style.display = 'none';
getById("container-12").style.display = 'none';
getById("container-13").style.display = 'none';
getById("container-14").style.display = 'none';
getById("container-15").style.display = 'none';
getById("mainmenu").style.alignSelf = "center";
getById("mainmenu").classList.add("mainmenuclass");
getById("header").style.alignSelf = "center";
@ -4016,6 +4057,58 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
}
if ("groups" in e.data) {
if (typeof e.data.groups == "object"){
session.group = e.data.groups || [];
} else if (!e.data.group){
session.group = [];
} else {
session.group = e.data.groups.split(",");
}
var eleGroup = getById("groups");
eleGroup.querySelectorAll('[data-action-type="toggle-group"][data-group]').forEach(group=>{
if (!(session.group && session.group.includes(group))){
group.remove("green");
}
});
if (session.group){
session.group.forEach(group =>{
var ele = eleGroup.querySelector('[data-action-type="toggle-group"][data-group="'+group+'"');
if (!ele){
ele = document.createElement("div");
ele.dataset.actionType = "toggle-group";
ele.dataset.group = group;
ele.classList.add('float');
ele.style.display = "inline-block";
ele.role = "button";
ele.innerHTML = '<i class="my-float las la-users" aria-hidden="true"></i><br />'+group;
eleGroup.appendChild(ele);
ele.onclick = function(){
changeGroupDirectorAPI(this.dataset.group);
}
}
ele.classList.add("green");
});
}
updateMixer();
if (session.group.length || session.allowNoGroup){
session.sendMessage({"group":session.group.join(",")});
if (session.screenShareState && (session.screenshareType ===3)){
session.sendMessage({"group":session.group.join(","), altUUID:true});
}
} else {
session.sendMessage({"group":false});
if (session.screenShareState && (session.screenshareType ===3)){
session.sendMessage({"group":false, altUUID:true});
}
}
}
if ("mute" in e.data) {
if (e.data.mute === true) { // unmute
session.speakerMuted = true; // set
@ -4314,7 +4407,6 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
stats.total_inbound_connections = Object.keys(session.rpcs).length;
for (var i in session.rpcs) {
stats.inbound_stats[session.rpcs[i].streamID] = session.rpcs[i].stats;
console.log(stats);
}
for (var uuid in session.pcs) {
setTimeout(function(UUID) {

1949
meet.html Normal file

File diff suppressed because one or more lines are too long

View File

@ -867,19 +867,19 @@
<div class="center-content">
<div class="title"><h1 class="main-heading">Mixer App</h1><h2>Video chat with custom <b>layouts</b></h2></div>
<label for="roomname"><input name="roomname" id="roomname" type="text" placeholder="Room Name" /></label>
<label for="roomname"><input name="roomname" autocorrect="off" autocapitalize="off" id="roomname" type="text" placeholder="Room Name" /></label>
<font class="tooltip">
<button onclick="randomRoomName();" class="randomRoomName"></button><span class="tooltiptext">Generate a random room name</span>
</font>
<br />
<label for="roompassword"><input name="roompassword" id="roompassword" type="text" placeholder="Room Password (optional)"/></label><br />
<label for="roompassword"><input name="roompassword" autocorrect="off" autocapitalize="off" id="roompassword" type="text" placeholder="Room Password (optional)"/></label><br />
<button onclick="startRoom();">Get started!</button><br /><br />
<span id="lastSavedRoom" class="hidden">
<br /><br />
<label for="savedroomname">
<input name="savedroomname" id="savedroomname" type="text" disabled placeholder="Room Name" /></label>
<input name="savedroomname" autocorrect="off" autocapitalize="off" id="savedroomname" type="text" disabled placeholder="Room Name" /></label>
<label for="savedroompassword" id="savedpasswordlabel"><br />
<input name="savedroompassword" id="savedroompassword" disabled type="password" placeholder="Room Password"/></label>
<input name="savedroompassword" autocorrect="off" autocapitalize="off" id="savedroompassword" disabled type="password" placeholder="Room Password"/></label>
<button onclick="startLastRoom();">Restore last room</button>
</span>
<br /><br />
@ -1068,7 +1068,7 @@
var assignSlotToGuest = true;
var toggleLabel = false;
var toggleBroadcast = true;
var messageList = [];
var password = false;
if (urlParams.has('password') || urlParams.has('pass') || urlParams.has('pw') || urlParams.has('p')) {
password = urlParams.get('password') || urlParams.get('pass') || urlParams.get('pw') || urlParams.get('p');
@ -1966,7 +1966,7 @@
roomname = generateString(10);
}
var iframesrc = "./index.html?novice&ltb=350&transparent&hideheader&hidetranslate&cleandirector&chatbutton=0&director="+roomname+additional+additional2+"&b64css="+injectCSS;
var iframesrc = "./index.html?novice&showdirector&ltb=350&transparent&hideheader&hidetranslate&cleandirector&chatbutton=0&director="+roomname+additional+additional2+"&b64css="+injectCSS;
if (roomname!==false){
setStorage("savedRoom", {roomname:roomname,password:password}, 9999);
@ -2112,6 +2112,15 @@
//console.log(e.data);
if ("gotChat" in e.data){
messageList.push(e.data.gotChat);
messageList = messageList.slice(-100);
updateMessages(e.data.gotChat);
} else if ("messageList" in e.data){
messageList = e.data.messageList;
updateMessages();
}
if ("action" in e.data){
///var outputWindow = document.createElement("div");
//outputWindow.innerHTML = "event: "+e.data.action+"<br />";

View File

@ -59,6 +59,14 @@
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>
<h2>Unsupervised guest check option</h2>
<span style="margin:5px;line-height:32px;font-size:110%;">
You can also use <a target="_blank" style="color: #CCC;" href='./check.html'>this tool</a> to have a guest perform a system and connection test, with those results being available to you via a result's page for up to a week.<br />
You can either ask the remote guest to send you the link to their results page when they complete the test, or you can use <i style="color: #CCF;" >check.html?id=xxx</i> to pre-assign the test ID (ie: xxx), which will have the results then be available at <i style="color: #CCF;" >results.html?id=xxx</i>.
<br />If you have questions, <a href="https://discord.vdo.ninja" style="color: #CCC;" target="_blank">join the Discord here</a>.
</span>
<br />
<h3>More testing options below</h3>
<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>
<br />

View File

@ -300,6 +300,8 @@ var CodecsHandler = (function() {
if (!codecPayload) {
return defaultBitrate;
}
var codecDetails = findLine(sdpLines, 'a=fmtp:'+codecPayload);
var rtxIndex = findLine(sdpLines, 'a=rtpmap', 'rtx/90000');
var rtxPayload;
@ -311,13 +313,23 @@ var CodecsHandler = (function() {
return defaultBitrate;
}
var rtxFmtpLineIndex = findLine(sdpLines, 'a=fmtp:' + rtxPayload.toString());
var rtxFmtpLineIndex = findLine(sdpLines, 'a=fmtp:' + codecPayload.toString());
if (rtxFmtpLineIndex !== null) {
try {
var maxBitrate = parseInt(sdpLines[rtxFmtpLineIndex].split("x-google-max-bitrate=")[1].split(";")[0]);
var minBitrate = parseInt(sdpLines[rtxFmtpLineIndex].split("x-google-min-bitrate=")[1].split(";")[0]);
} catch(e){
return defaultBitrate;
rtxFmtpLineIndex = findLine(sdpLines, 'a=fmtp:' + codecPayload.toString());
if (rtxFmtpLineIndex !== null) {
try {
var maxBitrate = parseInt(sdpLines[rtxFmtpLineIndex].split("x-google-max-bitrate=")[1].split(";")[0]);
var minBitrate = parseInt(sdpLines[rtxFmtpLineIndex].split("x-google-min-bitrate=")[1].split(";")[0]);
} catch(e){
return defaultBitrate;
}
} else {
return defaultBitrate;
}
}
if (minBitrate>maxBitrate){
@ -328,12 +340,9 @@ var CodecsHandler = (function() {
} else {
return defaultBitrate;
}
}
function setVideoBitrates(sdp, params, codec) { // modified + Improved by Steve.
function setVideoBitrates(sdp, params = false, codec=false) { // modified + Improved by Steve.
if (codec){
codec = codec.toUpperCase();
@ -358,9 +367,15 @@ var CodecsHandler = (function() {
codec = codecName || codec; // Try to find first Codec; else use expected/default
params = params || {};
var min_bitrate = params.min.toString() || '30';
var max_bitrate = params.max.toString() || '2500';
var min_bitrate = "30";
if (params.min){
min_bitrate = params.min.toString() || '30';
}
var max_bitrate = "2500";
if (params.max){
max_bitrate = params.max.toString() || '2500';
}
var codecIndex = findLine(sdpLines, 'a=rtpmap', codec+'/90000');
var codecPayload;

3514
thirdparty/adapter.js vendored Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -126,7 +126,7 @@ const JeelizThreeHelper = (function(){
const videoGeometry = new THREE.BufferGeometry()
const videoScreenCorners = new Float32Array([-1,-1, 1,-1, 1,1, -1,1]);
videoGeometry.addAttribute( 'position', new THREE.BufferAttribute( videoScreenCorners, 2 ) );
videoGeometry.setAttribute( 'position', new THREE.BufferAttribute( videoScreenCorners, 2 ) );
videoGeometry.setIndex(new THREE.BufferAttribute(new Uint16Array([0,1,2, 0,2,3]), 1));
_threeVideoMesh = new THREE.Mesh(videoGeometry, videoMaterial);
that.apply_videoTexture(_threeVideoMesh);

View File

@ -378,8 +378,8 @@
"animate-mixing": "Animate mixing",
"prefix-screenshare": "Prefix screenshare IDs",
"more-than-four-can-join": "These four guest slots are just for demonstration. More than four guests can actually join a room.",
"welcome-to-obs-ninja-chat": "\nWelcome! You can send text messages directly to connected peers from here.\n",
"privacy-disabled": "Privacy warning: The director will be able to remotely access your camera and microphone if you continue.",
"welcome-to-vdo-ninja-chat": "\nWelcome! You can send text messages directly to connected peers from here.\n",
"privacy-disabled": "Privacy warning: The director will be able to remotely change which camera and microphone is being used while this page is open, if you continue.",
"face-mesh": "Face mesh (slow load)",
"anonymous-mask": "Anonymous mask",
"dog-face": "Dog ears and nose",

View File

@ -394,7 +394,7 @@
"animate-mixing": "动画合成",
"prefix-screenshare": "前缀屏幕共享 ID",
"more-than-four-can-join": "这四个客人位置仅用于演示。一个房间可以容纳四位以上的客人。",
"welcome-to-obs-ninja-chat": "\n欢迎您可以从此处直接向连接的对等方发送文本信息。\n",
"welcome-to-vdo-ninja-chat": "\n欢迎您可以从此处直接向连接的对等方发送文本信息。\n",
"privacy-disabled": "隐私警告:如果您继续,房管将能够远程访问您的摄像头和麦克风。",
"face-mesh": "面网格(缓慢加载)",
"anonymous-mask": "匿名面具",

View File

@ -288,7 +288,7 @@
"push-to-talk-enable": "🔊 Povolit administrátorovi Push-to-Talk mód",
"welcome-to-control-room": "Welcome. This is the control-room for the group-chat. There are different things you can use this room for:<br><br>\t<li>You can host a group chat with friends using a room. Share the blue link to invite guests who will join the chat automatically.</li>\t<li>A group room can handle around 4 to 30 guests, depending on numerous factors, including CPU and available bandwidth of all guests in the room.</li>\t<li>Solo-views of each video are offered under videos as they load. These can be used within an OBS Browser Source.</li>\t<li>You can use the auto-mixing Group Scene, the green link, to auto arrange multiple videos for you in OBS.</li>\t<li>You can use this control room to record isolated video or audio streams, but it is an experimental feature still.</li>\t<li>Videos in the Director's room will be of low quality on purpose; to save bandwidth/CPU</li>\t<li>Guest's in the room will see each other's videos at a very limited quality to conserve bandwidth/CPU.</li>\t<li>OBS will see a guest's video in high-quality; the default video bitrate is 2500kbps.</li>\t<br>\tAs guests join, their videos will appear below. You can bring their video streams into OBS as solo-scenes or you can add them to the Group Scene.\t<br>The Group Scene auto-mixes videos that have been added to the group scene. Please note that the Auto-Mixer requires guests be manually added to it for them to appear in it; they are not added automatically.<br><br>Apple mobile devices, such as iPhones and iPads, do not fully support Video Group Chat. This is a hardware constraint.<br><br>\tFor advanced options and parameters, <a href=\"https://github.com/steveseguin/vdo.ninja/wiki/Guides-and-How-to's#urlparameters\">see the Wiki.</a>",
"more-than-four-can-join": "Tyto čtyři sloty pro hosty slouží pouze k předvedení. K místnosti se mohou skutečně připojit více než čtyři hosté.",
"welcome-to-obs-ninja-chat": "\n\tVítejte na VDO.Ninja! můžete ihned poslat zprávy ostatním členům této místnosti\n",
"welcome-to-vdo-ninja-chat": "\n\tVítejte na VDO.Ninja! můžete ihned poslat zprávy ostatním členům této místnosti\n",
"names-and-labels-coming-soon": "\n\tJména členů bude jedna z budoucích funkcí VDO.ninja.\n",
"send-chat": "Poslat",
"available-languages": "Dostupné jazyky:",

View File

@ -288,7 +288,7 @@
"push-to-talk-enable": "🔊 Audio und Video mit Gästen teilen (Push-to-Talk Mode)",
"welcome-to-control-room": "Welcome. This is the control-room for the group-chat. There are different things you can use this room for:<br><br><li>You can host a group chat with friends using a room. Share the blue link to invite guests who will join the chat automatically.</li><li>A group room can handle around 4 to 30 guests, depending on numerous factors, including CPU and available bandwidth of all guests in the room.</li><li>Solo-views of each video are offered under videos as they load. These can be used within an OBS Browser Source.</li><li>You can use the auto-mixing Group Scene, the green link, to auto arrange multiple videos for you in OBS.</li><li>You can use this control room to record isolated video or audio streams, but it is an experimental feature still.</li><li>Videos in the Director's room will be of low quality on purpose; to save bandwidth/CPU</li><li>Guest's in the room will see each other's videos at a very limited quality to conserve bandwidth/CPU.</li><li>OBS will see a guest's video in high-quality; the default video bitrate is 2500kbps.</li><br>As guests join, their videos will appear below. You can bring their video streams into OBS as solo-scenes or you can add them to the Group Scene.<br>The Group Scene auto-mixes videos that have been added to the group scene. Please note that the Auto-Mixer requires guests be manually added to it for them to appear in it; they are not added automatically.<br><br>Apple mobile devices, such as iPhones and iPads, do not fully support Video Group Chat. This is a hardware constraint.<br><br>For advanced options and parameters, <a href=\"https://github.com/steveseguin/vdo.ninja/wiki/Guides-and-How-to's#urlparameters\">see the Wiki.</a>",
"more-than-four-can-join": "These four guest slots are just for demonstration. More than four guests can actually join a room.",
"welcome-to-obs-ninja-chat": "\nWillkommen zu VDO.Ninja! Schicken Sie anderen Gästen eine Message.\n",
"welcome-to-vdo-ninja-chat": "\nWillkommen zu VDO.Ninja! Schicken Sie anderen Gästen eine Message.\n",
"names-and-labels-coming-soon": "\nNames identifying connected peers will be a feature in an upcoming release.\n",
"send-chat": "Abschicken",
"available-languages": "Verfügbare Sprachen:",

View File

@ -361,7 +361,7 @@
"toggle-control-video": "Toggle control bar",
"picture-in-picture": "Picture-in-picture",
"chrome-cast": "Cast..",
"welcome-to-obs-ninja-chat": "\nWelcome to VDO.Ninja! You can send text messages directly to connected peers from here.\n",
"welcome-to-vdo-ninja-chat": "\nWelcome to VDO.Ninja! You can send text messages directly to connected peers from here.\n",
"send-chat": "Send",
"apply-new-guest-settings": "Apply settings",
"cancel": "Cancel",

View File

@ -384,7 +384,7 @@
"application-audio-capture": "Para capturar el audio especifico de una aplicación, <a href=\"https://docs.vdo.ninja/audio\" style=\"color: #007AC8;\">vea aquí</a>",
"animate-mixing": "Animar",
"prefix-screenshare": "Prefijo de ID de pantalla compartida ",
"welcome-to-obs-ninja-chat": "\n\t¡Bienvenido a VDO.Ninja! Desde aquí puede enviar mensajes de texto para conectar mejor a sus amigos.\n",
"welcome-to-vdo-ninja-chat": "\n\t¡Bienvenido a VDO.Ninja! Desde aquí puede enviar mensajes de texto para conectar mejor a sus amigos.\n",
"privacy-disabled": "Advertencia de Privacidad: El Director podra acceder a la Cámara y al Microfono si continua",
"face-mesh": "Mapeado de la cara (Carga lento)",
"anonymous-mask": "Mascara de Anonymous",

View File

@ -410,7 +410,7 @@
"click-start-to-join": "Click Start to Join",
"waiting-for-mic-to-load": "Waiting for mic to load",
"waiting-for-camera-to-load": "Waiting for Camera to load",
"welcome-to-obs-ninja-chat": "\n\tWelcome! You can send text messages directly to connected peers from here.\n",
"welcome-to-vdo-ninja-chat": "\n\tWelcome! You can send text messages directly to connected peers from here.\n",
"please-select-option-to-join": "Please select an option to join.",
"show-controls-video": "Show control bar",
"hide-controls-video": "Hide control bar",

View File

@ -288,7 +288,7 @@
"push-to-talk-enable": "🔊 Permettre à l'administrateur d'utiliser le push-to-talk",
"welcome-to-control-room": "Welcome. This is the control-room for the group-chat. There are different things you can use this room for:<br><br>\t<li>You can host a group chat with friends using a room. Share the blue link to invite guests who will join the chat automatically.</li>\t<li>A group room can handle around 4 to 30 guests, depending on numerous factors, including CPU and available bandwidth of all guests in the room.</li>\t<li>Solo-views of each video are offered under videos as they load. These can be used within an OBS Browser Source.</li>\t<li>You can use the auto-mixing Group Scene, the green link, to auto arrange multiple videos for you in OBS.</li>\t<li>You can use this control room to record isolated video or audio streams, but it is an experimental feature still.</li>\t<li>Videos in the Director's room will be of low quality on purpose; to save bandwidth/CPU</li>\t<li>Guest's in the room will see each other's videos at a very limited quality to conserve bandwidth/CPU.</li>\t<li>OBS will see a guest's video in high-quality; the default video bitrate is 2500kbps.</li>\t<br>\tAs guests join, their videos will appear below. You can bring their video streams into OBS as solo-scenes or you can add them to the Group Scene.\t<br>The Group Scene auto-mixes videos that have been added to the group scene. Please note that the Auto-Mixer requires guests be manually added to it for them to appear in it; they are not added automatically.<br><br>Apple mobile devices, such as iPhones and iPads, do not fully support Video Group Chat. This is a hardware constraint.<br><br>\tFor advanced options and parameters, <a href=\"https://github.com/steveseguin/vdo.ninja/wiki/Guides-and-How-to's#urlparameters\">see the Wiki.</a>",
"more-than-four-can-join": "These four guest slots are just for demonstration. More than four guests can actually join a room.",
"welcome-to-obs-ninja-chat": "\n\tWelcome to VDO.Ninja! You can send text messages directly to connected peers from here.\n",
"welcome-to-vdo-ninja-chat": "\n\tWelcome to VDO.Ninja! You can send text messages directly to connected peers from here.\n",
"names-and-labels-coming-soon": "\n\tNames identifying connected peers will be a feature in an upcoming release.\n",
"send-chat": "Send",
"available-languages": "Options de langues disponibles :",

View File

@ -288,7 +288,7 @@
"push-to-talk-enable": "🔊 Abilita Director's Push-to-Talk Mode",
"welcome-to-control-room": "Benvenuto. Questa è la sala di controllo per la chat di gruppo. Ci sono diverse cose per cui puoi usare questa stanza:<br><br>\t<li>Puoi ospitare una chat di gruppo con gli amici utilizzando una stanza. Condividi il link blu per invitare gli ospiti che si uniranno automaticamente alla chat.</li>\t<li>Una sala per gruppi può ospitare da 4 a 30 persone, a seconda di numerosi fattori, tra cui CPU e larghezza di banda disponibile di tutti gli ospiti nella stanza.</li>\t<li>Solo-views of each video are offered under videos as they load. These can be used within an OBS Browser Source.</li>\t<li>You can use the auto-mixing Group Scene, the green link, to auto arrange multiple videos for you in OBS.</li>\t<li>You can use this control room to record isolated video or audio streams, but it is an experimental feature still.</li>\t<li>Videos in the Director's room will be of low quality on purpose; to save bandwidth/CPU</li>\t<li>Guest's in the room will see each other's videos at a very limited quality to conserve bandwidth/CPU.</li>\t<li>OBS will see a guest's video in high-quality; the default video bitrate is 2500kbps.</li>\t<br>\tAs guests join, their videos will appear below. You can bring their video streams into OBS as solo-scenes or you can add them to the Group Scene.\t<br>The Group Scene auto-mixes videos that have been added to the group scene. Please note that the Auto-Mixer requires guests be manually added to it for them to appear in it; they are not added automatically.<br><br>Apple mobile devices, such as iPhones and iPads, do not fully support Video Group Chat. This is a hardware constraint.<br><br>\tFor advanced options and parameters, <a href=\"https://github.com/steveseguin/vdo.ninja/wiki/Guides-and-How-to's#urlparameters\">see the Wiki.</a>",
"more-than-four-can-join": "These four guest slots are just for demonstration. More than four guests can actually join a room.",
"welcome-to-obs-ninja-chat": "\n\tBenvenuto in VDO.Ninja! Da qui puoi inviare messaggi di testo direttamente ai peer connessi.\n",
"welcome-to-vdo-ninja-chat": "\n\tBenvenuto in VDO.Ninja! Da qui puoi inviare messaggi di testo direttamente ai peer connessi.\n",
"names-and-labels-coming-soon": "\n\tI nomi che identificano i peer connessi saranno una funzionalità in una prossima versione..\n",
"send-chat": "Invia",
"available-languages": "Lingue Disponibili:",

View File

@ -288,7 +288,7 @@
"push-to-talk-enable": "🔊 Enable Director's Push-to-Talk Mode",
"welcome-to-control-room": "Welcome. This is the control-room for the group-chat. There are different things you can use this room for:<br><br>\t<li>You can host a group chat with friends using a room. Share the blue link to invite guests who will join the chat automatically.</li>\t<li>A group room can handle around 4 to 30 guests, depending on numerous factors, including CPU and available bandwidth of all guests in the room.</li>\t<li>Solo-views of each video are offered under videos as they load. These can be used within an OBS Browser Source.</li>\t<li>You can use the auto-mixing Group Scene, the green link, to auto arrange multiple videos for you in OBS.</li>\t<li>You can use this control room to record isolated video or audio streams, but it is an experimental feature still.</li>\t<li>Videos in the Director's room will be of low quality on purpose; to save bandwidth/CPU</li>\t<li>Guest's in the room will see each other's videos at a very limited quality to conserve bandwidth/CPU.</li>\t<li>OBS will see a guest's video in high-quality; the default video bitrate is 2500kbps.</li>\t<br>\tAs guests join, their videos will appear below. You can bring their video streams into OBS as solo-scenes or you can add them to the Group Scene.\t<br>The Group Scene auto-mixes videos that have been added to the group scene. Please note that the Auto-Mixer requires guests be manually added to it for them to appear in it; they are not added automatically.<br><br>Apple mobile devices, such as iPhones and iPads, do not fully support Video Group Chat. This is a hardware constraint.<br><br>\tFor advanced options and parameters, <a href=\"https://github.com/steveseguin/vdo.ninja/wiki/Guides-and-How-to's#urlparameters\">see the Wiki.</a>",
"more-than-four-can-join": "These four guest slots are just for demonstration. More than four guests can actually join a room.",
"welcome-to-obs-ninja-chat": "\n\tWelcome to VDO.Ninja! You can send text messages directly to connected peers from here.\n",
"welcome-to-vdo-ninja-chat": "\n\tWelcome to VDO.Ninja! You can send text messages directly to connected peers from here.\n",
"names-and-labels-coming-soon": "\n\tNames identifying connected peers will be a feature in an upcoming release.\n",
"send-chat": "Send",
"available-languages": "Available Languages:",

View File

@ -288,7 +288,7 @@
"push-to-talk-enable": "🔊 Enable Director's Push-to-Talk Mode Zet ",
"welcome-to-control-room": "Welcome. This is the control-room for the group-chat. There are different things you can use this room for:<br><br>\t<li>You can host a group chat with friends using a room. Share the blue link to invite guests who will join the chat automatically.</li>\t<li>A group room can handle around 4 to 30 guests, depending on numerous factors, including CPU and available bandwidth of all guests in the room.</li>\t<li>Solo-views of each video are offered under videos as they load. These can be used within an OBS Browser Source.</li>\t<li>You can use the auto-mixing Group Scene, the green link, to auto arrange multiple videos for you in OBS.</li>\t<li>You can use this control room to record isolated video or audio streams, but it is an experimental feature still.</li>\t<li>Videos in the Director's room will be of low quality on purpose; to save bandwidth/CPU</li>\t<li>Guest's in the room will see each other's videos at a very limited quality to conserve bandwidth/CPU.</li>\t<li>OBS will see a guest's video in high-quality; the default video bitrate is 2500kbps.</li>\t<br>\tAs guests join, their videos will appear below. You can bring their video streams into OBS as solo-scenes or you can add them to the Group Scene.\t<br>The Group Scene auto-mixes videos that have been added to the group scene. Please note that the Auto-Mixer requires guests be manually added to it for them to appear in it; they are not added automatically.<br><br>Apple mobile devices, such as iPhones and iPads, do not fully support Video Group Chat. This is a hardware constraint.<br><br>\tFor advanced options and parameters, <a href=\"https://github.com/steveseguin/vdo.ninja/wiki/Guides-and-How-to's#urlparameters\">see the Wiki.</a>",
"more-than-four-can-join": "Er staan momenteel vier gasten plekken gevuld voor de demonstratie. Het is mogelijk om meer gasten te hebben in een kamer.",
"welcome-to-obs-ninja-chat": "\n\tWelcome to VDO.Ninja! You can send text messages directly to connected peers from here.\n",
"welcome-to-vdo-ninja-chat": "\n\tWelcome to VDO.Ninja! You can send text messages directly to connected peers from here.\n",
"names-and-labels-coming-soon": "\n\tNames identifying connected peers will be a feature in an upcoming release.\n",
"send-chat": "Verstuur",
"available-languages": "Beschikbare talen:",

View File

@ -288,7 +288,7 @@
"push-to-talk-enable": " Enable Director's Push-to-Talk Mode",
"welcome-to-control-room": "\n\tErehay ouyay ancay epray-enerategay\n",
"more-than-four-can-join": "Erehay ouyay ancay epray-enerategay.",
"welcome-to-obs-ninja-chat": "\n\tErehay ouyay ancay epray-enerategay.\n",
"welcome-to-vdo-ninja-chat": "\n\tErehay ouyay ancay epray-enerategay.\n",
"names-and-labels-coming-soon": "\n\tErehay ouyay ancay epray-enerategay.\n",
"send-chat": "Erehay ouyay ancay epray-enerategay",
"available-languages": "AErehay ouyay ancay epray-enerategay:",

View File

@ -218,7 +218,7 @@
"waiting-for-camera-to-load": "Aguardando a câmera carregar",
"waiting-for-mic-to-load": "Aguardando o microfone carregar",
"welcome-to-control-room": "\n<b>Bem-vindo. Esta é a sala de controle do diretor para o bate-papo em grupo.</b><br><br>\nVocê pode hospedar um bate-papo em grupo com amigos usando uma sala. Compartilhe o link azul para convidar as pessoas que participarão do bate-papo automaticamente.\n<br><br>\nUma sala de grupo pode lidar normalmente com cerca de 6 a 20 convidados, dependendo de vários fatores, incluindo CPU e largura de banda disponível de todos os convidados na sala\n",
"welcome-to-obs-ninja-chat": "\nBem-vindo! Você pode enviar mensagens de texto diretamente para as pessoas conectadas a partir daqui.\n",
"welcome-to-vdo-ninja-chat": "\nBem-vindo! Você pode enviar mensagens de texto diretamente para as pessoas conectadas a partir daqui.\n",
"you-are-in-the-control-center": "Centro de controle para sala:",
"you-are-using-headphones-earphones": "Você está usando headphones/fones de ouvido",
"your-connection-is-hardwired-instead-of-wifi": "Sua conexão é cabeada em vez de Wi-Fi",

View File

@ -288,7 +288,7 @@
"push-to-talk-enable": "🔊 Ativar Push-to-talk do realizador",
"welcome-to-control-room": "Bem-vindo. Esta é a sala de controlo para o chat de grupo. Há diferentes coisas que pode fazer aqui:<br><br>\t<li>Pode hospedar um chat de grupo com amigos. Partilhe o link azul para os convidados se juntarem ao chat de forma automática.</li>\t<li>Uma sala de grupo pode hospedar entre 4 a 30 4 to 30 convidados, dependendo de inúmeros factores, incluindo CPU e largura de banda de todos os convidados na sala.</li>\t<li>Visualizações individuais de cada vídeo serão mostradas quando carregam. Estas podem ser usadas em Fontes do tipo Browser no OBS.</li>\t<li>Pode usar a cena de grupo automática, o link verde, para dispôr automaticamente os vídeos por si no OBS.</li>\t<li>Pode usar esta sala de controlo para gravar streams isolados de vídeo ou áudio, mas isto é ainda experimental.</li>\t<li>Vídeos na sala de controle são de baixa qualidade propositadamente; para poupar largura de banda/CPU</li>\t<li>Convidados na sala irão ver-se numa qualidade muito reduzida para conservar largura de banda/CPU.</li>\t<li>OBS tem acesso ao vídeo do convidado em alta qualidade; o bitrate de vídeo por omissão é 2500kbps.</li>\t<br>\tÀ medida que os convidados entram, os seus vídeos são mostrados abaixo. Pode levar os seus sinais para o OBS como cenas individuais ou pode adicioná-los à cena de grupo.\t<br>A Cena de grupo auto-mistura vídeos que lhe forem adicionados. Note que a auto-mistura requer que os convidados sejam manualmente adicionados; não são adicionados automaticamente.<br><br>Dispositivos móveis Apple, como iPhones e iPads, não suportam totalmente o Chat de Grupo. Este é um constrangimento de hardware.<br><br>\tPara opções avançadas e parâmetros, <a href=\"https://github.com/steveseguin/vdo.ninja/wiki/Guides-and-How-to's#urlparameters\">veja o Wiki.</a>",
"more-than-four-can-join": "Estes quatro convidados são apenas ilustrativos. Podem juntar-se mais de quatro convidados numa sala.",
"welcome-to-obs-ninja-chat": "\n\tBem vindo ao VDO.Ninja! Pode enviar mensagens diretas a quem estiver aqui ligado a partir daqui.\n",
"welcome-to-vdo-ninja-chat": "\n\tBem vindo ao VDO.Ninja! Pode enviar mensagens diretas a quem estiver aqui ligado a partir daqui.\n",
"names-and-labels-coming-soon": "\n\tNomes a identificar as ligações será uma funcionalidade futura.\n",
"send-chat": "Enviar",
"available-languages": "Línguas disponíveis:",

View File

@ -415,7 +415,7 @@
"animate-mixing": "Анимированный переход",
"prefix-screenshare": "Prefix screenshare IDs",
"more-than-four-can-join": "Этот шаблон на 4 гостей только для демонстрации. Гостей может быть больше.",
"welcome-to-obs-ninja-chat": "Пожалуйста, сделайте все возможное, чтобы немедленно остановить эту кровавую войну! Иначе завтра может не быть",
"welcome-to-vdo-ninja-chat": "Пожалуйста, сделайте все возможное, чтобы немедленно остановить эту кровавую войну! Иначе завтра может не быть",
"privacy-disabled": "Ведущий сможет удаленно управлять вашим микрофоном и камерой.",
"face-mesh": "Face mesh (slow load)",
"anonymous-mask": "Маска анонимуса",

View File

@ -309,7 +309,7 @@
"push-to-talk-enable": "🔊 Yönetmen bas-konuş'u etkinleştir",
"welcome-to-control-room": "Hoş geldiniz. Bu grup konuşması için kontrol odasıdır. Bu odayı farklı amaçlar için kullanabilirsiniz:<br><br>\t<li>Arkadaşlarınız ile grup konunşması yapmak için bir oda kullanabilirsiniz. Otomatik olarak gruba dahil etmek için misafirleriniz ile mavi bağlantıyı paylaşın.</li>\t<li>Bir grup odası 4 - 30 sayıda misafir ağırlayabilir. Ancak bu bir çok etkene göre değişebilir, yeterli CPU ve internet bant genişliği gibi.</li>\t<li>Her videonun tekil görüntüsü bağlantıları misafirler bağlandıkça videolarının altında yer alacak. Bunları OBS tarayıcı kaynağı olarak kullanabilirsiniz.</li>\t<li>Otomatik-karıştırma grup sahnesi (yeşil bağlantı) bir çok videoyu OBS'de otomatik ayarlamak için kullanabilirsiniz.</li>\t<li>Bu odayı kullanarak her bir video için ayrı ayrı video ve ses kaynaklarını kaydedebilirsiniz, ancak bu özellik halen deneysel aşamadadır.</li>\t<li>Yönetmen odasında yer alan videolar kasten düşük kalitede tutulmuştur; CPU ve internetbant genişliğinden tasarruf için</li>\t<li>Odada yer alan misafirler, CPU ve internetten tasarruf etmek amacıyla bir birlerinin videolarını düşük kalitede görecek.</li>\t<li>OBS misafirlerin videolarını çok yüksek kalitede alacak, varsayılan kalite 2500kbps'dir.</li>\t<br>\tMisafirler eklendikçe videoları aşağıda belirecek. OBS'ye videolarını tekil sahneler olarak ekleyebilir, ya da grup sahnelerine ekleyebilirsiniz.\t<br>Grup sahnesi, eklenmiş videoları otomatik olarak karıştırır. Otomatik karıştırmanın çalışması için misafirlerin el ile bu sahneye eklenmesi gerektiğini unutmayın; otomatik olarak sahnelere eklenmeyeceklerdir.<br><br>iPhone iPad gibi Apple mobil cihazlar, tam olarak video grup görüşmeyi desteklemiyor. Bu bir donanım sınırlamasıdır.<br><br>\tGekişmiş özellik ve parametreler için <a href=\"https://github.com/steveseguin/vdo.ninja/wiki/Guides-and-How-to's#urlparameters\">Wiki'ye göz atın.</a>",
"more-than-four-can-join": "These four guest slots are just for demonstration. More than four guests can actually join a room.",
"welcome-to-obs-ninja-chat": "\n\tVDO.Ninja'ya hoş geldin! Bağlı olan kişilere buradan yazılı mesajlar gönderebilirsin.\n",
"welcome-to-vdo-ninja-chat": "\n\tVDO.Ninja'ya hoş geldin! Bağlı olan kişilere buradan yazılı mesajlar gönderebilirsin.\n",
"names-and-labels-coming-soon": "\n\tBağlanan kişileri tanımlayan isimler ileriki bir geliştirmede yer alacak.\n",
"send-chat": "Gönder",
"available-languages": "Diller:",

View File

@ -319,7 +319,7 @@
"advanced-camera-settings": "<i class=\"las la-sliders-h\"></i> Відео налаштування",
"open-in-new-tab": "Відкрити у новій закладинці",
"copy-to-clipboard": "Скопіювати у буфер",
"welcome-to-obs-ninja-chat": "\n\tWelcome to VDO.Ninja! You can send text messages directly to connected peers from here.\n",
"welcome-to-vdo-ninja-chat": "\n\tWelcome to VDO.Ninja! You can send text messages directly to connected peers from here.\n",
"names-and-labels-coming-soon": "\n\tNames identifying connected peers will be a feature in an upcoming release.\n",
"send-chat": "Надіслати",
"available-languages": "Доступні мови:",

File diff suppressed because one or more lines are too long