mirror of
https://github.com/eliasstepanik/vdo.ninja.git
synced 2026-01-11 05:38:31 +00:00
improving the iframe API / darkmode added
version v19.1
This commit is contained in:
parent
42fb75b756
commit
491b41abca
121
examples/bigmutebutton.html
Normal file
121
examples/bigmutebutton.html
Normal file
@ -0,0 +1,121 @@
|
||||
<html>
|
||||
<head><title>Twitch + Video</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:#003;
|
||||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
iframe {
|
||||
width:100%;
|
||||
height:100%;
|
||||
border:0;
|
||||
margin:0;
|
||||
padding:0;
|
||||
position:absolute;
|
||||
display:block;
|
||||
}
|
||||
|
||||
|
||||
input{
|
||||
padding:10px;
|
||||
width:80%;
|
||||
font-size:1.2em;
|
||||
z-index: 1000;
|
||||
margin:10%;
|
||||
}
|
||||
|
||||
#startButton{
|
||||
margin: 10px;
|
||||
padding: 20px
|
||||
display: block;
|
||||
border-radius: 50px;
|
||||
font-size:1.5em;
|
||||
}
|
||||
|
||||
#toggleMute{
|
||||
margin: 10px;
|
||||
padding: 30px 0;
|
||||
border-radius: 50px;
|
||||
font-size:1.5em;
|
||||
display: block;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width:200px;
|
||||
left: calc(50% - 100px);
|
||||
}
|
||||
|
||||
.pressed {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="clean">
|
||||
<center>
|
||||
<input placeholder="Enter a VDON stream ID here" id="viewlink" type="text" />
|
||||
<button id="startButton" onclick="loadIframes()" style="display:block;padding:10px;margin:10px;">START</button></center>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
window.addEventListener("orientationchange", function() {
|
||||
// Announce the new orientation number
|
||||
// alert(window.orientation);
|
||||
}, false);
|
||||
|
||||
|
||||
|
||||
|
||||
function loadIframes(url=false){
|
||||
|
||||
var streamID = document.getElementById("viewlink").value;
|
||||
https://vdo.ninja/?label&webcam&cleanoutput&ad=1&vd=1
|
||||
|
||||
var path = "vdo.ninja"; //window.location.host+window.location.pathname.split("/").slice(0,-1).join("/");
|
||||
var streamSrc = "https://"+path+"/?push="+streamID+"&label&webcam&cleanoutput&ad=1&vd=1";
|
||||
|
||||
document.getElementById("clean").parentNode.removeChild(document.getElementById("clean"));
|
||||
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.allow = "autoplay;camera;microphone;fullscreen;picture-in-picture;";
|
||||
iframe.src = streamSrc;
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
function sendSelfCommand(action, value=null){
|
||||
iframe.contentWindow.postMessage({"target":null, "action":action, "value":value}, '*');
|
||||
}
|
||||
|
||||
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.id = "toggleMute";
|
||||
button.innerHTML = "Mute";
|
||||
button.dataset.value = "true";
|
||||
document.body.appendChild(button);
|
||||
|
||||
button.onclick = function(){
|
||||
|
||||
if (this.dataset.value=="true"){
|
||||
this.dataset.value = "false";
|
||||
this.classList.add("pressed");
|
||||
this.innerHTML = "Un-Mute";
|
||||
sendSelfCommand("mic",false);
|
||||
} else {
|
||||
this.classList.remove("pressed");
|
||||
this.innerHTML = "Mute";
|
||||
this.dataset.value = "true";
|
||||
sendSelfCommand("mic",true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
401
examples/obs_remote/index.html
Normal file
401
examples/obs_remote/index.html
Normal file
@ -0,0 +1,401 @@
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript" src="./thirdparty/obs-websocket.min.js"></script>
|
||||
<link rel="stylesheet" href="https://vdo.ninja/main.css" />
|
||||
<title>OBS Controller Demo using VDO.Ninja</title>
|
||||
<style>
|
||||
|
||||
.container {
|
||||
max-width: 80%;
|
||||
width: fit-content;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin: 10px;
|
||||
box-shadow: 0 4px 8px 0 rgb(0 0 0 / 10%);
|
||||
background-color: #ddd;
|
||||
color: black;
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
.card>div {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.card h2 {
|
||||
font-size: 1.5em;
|
||||
padding: 10px;
|
||||
background-color: #457b9d;
|
||||
color: white;
|
||||
border-bottom: 2px solid #3b6a87;
|
||||
}
|
||||
|
||||
small {
|
||||
font-style: italic;
|
||||
display: block;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
span.warning {
|
||||
color: rgb(212, 191, 0);
|
||||
}
|
||||
|
||||
input {
|
||||
padding: 10px;
|
||||
display: inline-block;
|
||||
flex-flow: unset;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
video {
|
||||
max-width: 640px;
|
||||
max-height: 360px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
audio {
|
||||
max-width: 640px;
|
||||
max-height: 360px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
div#processing {
|
||||
display: none;
|
||||
justify-content: center;
|
||||
place-items: center;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
background: #141926;
|
||||
flex-direction: column;
|
||||
}
|
||||
button {
|
||||
margin:5px;
|
||||
border:solid black 2px;
|
||||
}
|
||||
|
||||
body {
|
||||
color:white;
|
||||
display: inline-block;
|
||||
flex-flow: unset;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #CEF!important;
|
||||
}
|
||||
|
||||
#info{
|
||||
margin: 20px;
|
||||
max-height: 50%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#client {
|
||||
margin:10px;
|
||||
display:block;
|
||||
}
|
||||
label {
|
||||
color:white;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>OBS remote (server)</h1>
|
||||
<span id='setup'>
|
||||
<label for="address">Websocket Address</label>
|
||||
<input name="address" id="address" placeholder="address (optional)" value="localhost:4444" />
|
||||
<label for="address">Websocket Password</label>
|
||||
<input name="password" id="password" placeholder="password here (optional)" />
|
||||
<br />
|
||||
<label for="vdoroomname">Room name to use</label>
|
||||
<input name="vdoroomname" id="vdoroomname" placeholder="vdo room name to use (optional)" />
|
||||
<label for="vdopassword">Room password to use</label>
|
||||
<input name="vdopassword" id="vdopassword" placeholder="vdo password to use (optional)" />
|
||||
<br />
|
||||
<button id="address_button">Connect</button>
|
||||
<button id="address_button_2">Connect and share OBS Output</button>
|
||||
</span>
|
||||
<a id="client" target="_blank"></a>
|
||||
<div id="info"></div>
|
||||
<small>Code available on GitHub: <a target="_blank" href='https://github.com/steveseguin/remote_ninja'>https://github.com/steveseguin/remote_ninja</a></small>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
var hostname = "vdo.ninja"; // all that's supported as of this moment.
|
||||
|
||||
const obs = new OBSWebSocket();
|
||||
var scenesData = {};
|
||||
scenesData.scenes = [];
|
||||
|
||||
function sendToOBS(action, data={}){
|
||||
document.getElementById("info").innerHTML = action + "<br />"+document.getElementById("info").innerHTML;
|
||||
obs.sendCallback(action, data, sendCallback)
|
||||
}
|
||||
|
||||
(function(w) {
|
||||
w.URLSearchParams = w.URLSearchParams || function(searchString) {
|
||||
var self = this;
|
||||
searchString = searchString.replace("??", "?");
|
||||
self.searchString = searchString;
|
||||
self.get = function(name) {
|
||||
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(self.searchString);
|
||||
if (results == null) {
|
||||
return null;
|
||||
} else {
|
||||
return decodeURI(results[1]) || 0;
|
||||
}
|
||||
};
|
||||
};
|
||||
})(window);
|
||||
|
||||
var urlEdited = window.location.search.replace(/\?\?/g, "?");
|
||||
urlEdited = urlEdited.replace(/\?/g, "&");
|
||||
urlEdited = urlEdited.replace(/\&/, "?");
|
||||
|
||||
if (urlEdited !== window.location.search){
|
||||
warnlog(window.location.search + " changed to " + urlEdited);
|
||||
window.history.pushState({path: urlEdited.toString()}, '', urlEdited.toString());
|
||||
}
|
||||
var urlParams = new URLSearchParams(urlEdited);
|
||||
|
||||
var roomname = Math.floor(Math.random() * 1000000);
|
||||
var pwurl = Math.floor(Math.random() * 1000000);
|
||||
|
||||
if (urlParams.get("password")){
|
||||
pwurl = urlParams.get("password");
|
||||
localStorage.setItem('password',pwurl)
|
||||
} else if (localStorage.getItem('password')){
|
||||
pwurl = localStorage.getItem('password');
|
||||
} else {
|
||||
localStorage.setItem('password',pwurl)
|
||||
}
|
||||
|
||||
if (urlParams.get("room")){
|
||||
roomname = urlParams.get("room")
|
||||
localStorage.setItem('roomname',roomname)
|
||||
} else if (localStorage.getItem('roomname')){
|
||||
roomname = localStorage.getItem('roomname');
|
||||
} else {
|
||||
localStorage.setItem('roomname',roomname)
|
||||
}
|
||||
|
||||
document.getElementById('vdoroomname').value = roomname;
|
||||
document.getElementById('vdopassword').value = pwurl;
|
||||
|
||||
|
||||
if (localStorage.getItem('address')){
|
||||
document.getElementById('address').value = localStorage.getItem('address');
|
||||
}
|
||||
|
||||
if (localStorage.getItem('wspass')){
|
||||
document.getElementById('password').value = localStorage.getItem('wspass');
|
||||
}
|
||||
|
||||
var iframe = null;
|
||||
function createIFrame(visible=true){
|
||||
iframe = document.createElement("iframe");
|
||||
|
||||
if (visible){
|
||||
iframe.src = "https://"+hostname+"/?room="+roomname+"&push=mainOBSOutput&od=0&transparent&webcam&vd=obs&view&password="+pwurl+"&label=OBS_"+Math.floor(Math.random() * 1000000);
|
||||
iframe.style.minWidth = "720px";
|
||||
iframe.style.minHeight = "480px";
|
||||
iframe.style.maxWidth = "50%";
|
||||
iframe.style.maxHeight = "50%";
|
||||
iframe.style.display = "block";
|
||||
iframe.style.margin = "auto";
|
||||
iframe.allow = "autoplay;camera;microphone;fullscreen;picture-in-picture;";
|
||||
} else {
|
||||
iframe.src = "https://"+hostname+"/?room="+roomname+"&push&autostart&vd=0&view&ad=0&transparent&cleanoutput&password="+pwurl+"&label=OBS_"+Math.floor(Math.random() * 1000000);
|
||||
iframe.style.opacity = 0;
|
||||
iframe.style.width = 0;
|
||||
iframe.style.height = 0;
|
||||
iframe.style.position = "absolulte";
|
||||
iframe.style.top = "-100px";
|
||||
iframe.style.left = "-100px";
|
||||
}
|
||||
document.getElementById("client").parentNode.insertBefore(iframe, document.getElementById("client").nextSibling);
|
||||
|
||||
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
|
||||
var eventer = window[eventMethod];
|
||||
var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message";
|
||||
eventer(messageEvent, function (e) {
|
||||
if (e.source != iframe.contentWindow){return} // reject messages send from other iframes
|
||||
console.log(e);
|
||||
if ("dataReceived" in e.data){
|
||||
if ("sendToOBS" in e.data.dataReceived){
|
||||
if ("action" in e.data.dataReceived.sendToOBS){
|
||||
if ("data" in e.data.dataReceived.sendToOBS){
|
||||
sendToOBS(e.data.dataReceived.sendToOBS.action, e.data.dataReceived.sendToOBS.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ("action" in e.data){
|
||||
if (e.data.action === "new-push-connection"){
|
||||
console.log(e.data);
|
||||
updateSceneList();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function sendCallback(err, data){
|
||||
console.log("CALLBACK TRIGGERED");
|
||||
var msg = {};
|
||||
msg.sentFromOBS = {};
|
||||
msg.sentFromOBS.callbackData = data;
|
||||
msg.sentFromOBS.callbackError = err;
|
||||
try {
|
||||
iframe.contentWindow.postMessage({"sendData":msg}, '*');
|
||||
} catch(e){}
|
||||
}
|
||||
|
||||
function sendRawData(data){
|
||||
var msg = {};
|
||||
msg.sentFromOBS = {};
|
||||
msg.sentFromOBS.rawData = data;
|
||||
try {
|
||||
iframe.contentWindow.postMessage({"sendData":msg}, '*');
|
||||
} catch(e){}
|
||||
}
|
||||
|
||||
function heartBeat(){
|
||||
obs.send("GetStats");
|
||||
}
|
||||
|
||||
function updateSceneList(){
|
||||
var msg = {};
|
||||
msg.sentFromOBS = {};
|
||||
msg.sentFromOBS.scenes = scenesData;
|
||||
try {
|
||||
iframe.contentWindow.postMessage({"sendData":msg}, '*');
|
||||
} catch(e){}
|
||||
console.log(msg);
|
||||
obs.send("GetSourcesList");
|
||||
obs.send('GetCurrentScene');
|
||||
obs.send("GetVideoInfo");
|
||||
obs.send("ListOutputs");
|
||||
}
|
||||
|
||||
document.getElementById('address_button').addEventListener('click', e => {
|
||||
connect(e, false);
|
||||
});
|
||||
|
||||
document.getElementById('address_button_2').addEventListener('click', e => {
|
||||
connect(e, true);
|
||||
});
|
||||
|
||||
var heartBeatInterval = null;
|
||||
|
||||
function connect(e, camera){
|
||||
const address = document.getElementById('address').value || "localhost:4444";
|
||||
const password = document.getElementById('password').value;
|
||||
|
||||
|
||||
roomname = document.getElementById('vdoroomname').value || Math.floor(Math.random() * 1000000);
|
||||
pwurl = document.getElementById('vdopassword').value || Math.floor(Math.random() * 1000000);
|
||||
localStorage.setItem('roomname',roomname)
|
||||
localStorage.setItem('password',pwurl)
|
||||
|
||||
createIFrame(camera); // connects to VDO.Ninja's IFRAME API
|
||||
|
||||
localStorage.setItem('address',address);
|
||||
if (password){
|
||||
localStorage.setItem('wspass',password);
|
||||
var ret = obs.connect({
|
||||
address: address,
|
||||
password: password
|
||||
});
|
||||
} else {
|
||||
var ret = obs.connect({
|
||||
address: address
|
||||
});
|
||||
}
|
||||
|
||||
ret.then(() => {
|
||||
console.log(`Success!`);
|
||||
return obs.send('GetSceneList');
|
||||
}).then(data => {
|
||||
document.getElementById("setup").style.display = "none";
|
||||
scenesData = data;
|
||||
updateSceneList();
|
||||
var pathname = window.location.pathname.split("/");
|
||||
pathname.pop();
|
||||
pathname = pathname.join("/");
|
||||
var clientLink = window.location.protocol + "//" + window.location.host + pathname + "/interface.html?room="+roomname+"&password="+pwurl;
|
||||
document.getElementById("client").href = clientLink;
|
||||
document.getElementById("client").innerHTML = "<b><font style='color:#70c4ff;'>client link:</font></b> "+clientLink;
|
||||
document.getElementById("info").innerHTML = "<br /><p style='color:#bdffbd;'>Connection to OBS websockets opened.</p>" + document.getElementById("info").innerHTML;
|
||||
try {
|
||||
obs._socket.onmessage2 = obs._socket.onmessage; // hijacking the obs-websocket.js framework
|
||||
obs._socket.onmessage = function(data){
|
||||
console.log(data);
|
||||
obs._socket.onmessage2(data);
|
||||
if (data.type && data.data){
|
||||
if (data.type == "message"){
|
||||
sendRawData(data.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(e){console.error(e);}
|
||||
|
||||
clearInterval(heartBeatInterval);
|
||||
heartBeatInterval = setInterval(function(){heartBeat();},3000);
|
||||
|
||||
}).catch(err => { // Promise convention dicates you have a catch on every chain.
|
||||
console.log(err);
|
||||
document.getElementById("info").innerHTML = "<br />Error trying to connect. Is SSL enabled on your domain?" + document.getElementById("info").innerHTML;
|
||||
if ("error" in err){
|
||||
document.getElementById("info").innerHTML = "<br />"+err.error + document.getElementById("info").innerHTML;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// We use the source visibility one and filter visibility web socket commands quite often in shows.
|
||||
|
||||
obs.on('SwitchScenes', data => {
|
||||
console.log(`New Active Scene: ${data.sceneName}`);
|
||||
scenesData.currentScene = data.sceneName
|
||||
updateSceneList();
|
||||
});
|
||||
obs.on('ConnectionOpened', (data) => function(){
|
||||
document.getElementById("setup").style.display = "none";
|
||||
document.getElementById("info").innerHTML = "<br /><p style='color:#bdffbd;'>Connection to OBS websockets opened.</p>" + document.getElementById("info").innerHTML;
|
||||
});
|
||||
obs.on('ConnectionClosed', (data) => function(){
|
||||
document.getElementById("setup").style.display = "unset";
|
||||
document.getElementById("info").innerHTML = "<br />Connection to OBS websockets closed" + document.getElementById("info").innerHTML;
|
||||
});
|
||||
obs.on('AuthenticationSuccess', (data) => function(){
|
||||
document.getElementById("setup").style.display = "none";
|
||||
document.getElementById("info").innerHTML = "<br />OBS websockets authenticated" + document.getElementById("info").innerHTML;
|
||||
});
|
||||
obs.on('AuthenticationFailure', (data) => function(){
|
||||
document.getElementById("setup").style.display = "unset";
|
||||
document.getElementById("info").innerHTML = "<br />Authentication to OBS websockets failed" + document.getElementById("info").innerHTML;
|
||||
});
|
||||
obs.on('ScenesChanged', (data) => function(){
|
||||
scenesData = data;
|
||||
updateSceneList()
|
||||
});
|
||||
// You must add this handler to avoid uncaught exceptions.
|
||||
obs.on('error', err => {
|
||||
document.getElementById("info").innerHTML = "<br />OBS websockets error" + document.getElementById("info").innerHTML;
|
||||
console.error('socket error:', err);
|
||||
if ("error" in err){
|
||||
document.getElementById("info").innerHTML = "<br />"+err.error + document.getElementById("info").innerHTML;
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
474
examples/obs_remote/interface.html
Normal file
474
examples/obs_remote/interface.html
Normal file
@ -0,0 +1,474 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript" src="./thirdparty/obs-websocket.min.js"></script>
|
||||
<link rel="stylesheet" href="https://vdo.ninja/main.css" />
|
||||
<style>
|
||||
|
||||
.container {
|
||||
max-width: 80%;
|
||||
width: fit-content;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.card {
|
||||
margin: 10px;
|
||||
box-shadow: 0 4px 8px 0 rgb(0 0 0 / 10%);
|
||||
background-color: #ddd;
|
||||
color: black;
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
.card>div {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.card h2 {
|
||||
font-size: 1.5em;
|
||||
padding: 10px;
|
||||
background-color: #457b9d;
|
||||
color: white;
|
||||
border-bottom: 2px solid #3b6a87;
|
||||
}
|
||||
|
||||
small {
|
||||
font-style: italic;
|
||||
display: block;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
span.warning {
|
||||
color: rgb(212, 191, 0);
|
||||
}
|
||||
|
||||
input {
|
||||
padding: 10px;
|
||||
display: inline-block;
|
||||
flex-flow: unset;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
video {
|
||||
max-width: 640px;
|
||||
max-height: 360px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
audio {
|
||||
max-width: 640px;
|
||||
max-height: 360px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
div#processing {
|
||||
display: none;
|
||||
justify-content: center;
|
||||
place-items: center;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
background: #141926;
|
||||
flex-direction: column;
|
||||
}
|
||||
button {
|
||||
margin:5px;
|
||||
border:solid black 2px;
|
||||
}
|
||||
|
||||
body {
|
||||
color:white;
|
||||
display: inline-block;
|
||||
flex-flow: unset;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #225273!important;
|
||||
}
|
||||
|
||||
.hidden{
|
||||
display:none !important;
|
||||
}
|
||||
|
||||
.stat {
|
||||
background-color: black;
|
||||
margin: 7px;
|
||||
padding: 5px;
|
||||
}
|
||||
.stat:nth-child(2n) {
|
||||
background-color: #333;
|
||||
}
|
||||
.stat:empty {
|
||||
display:none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
</style>
|
||||
<title>OBS Controller Demo using VDO.NInja</title>
|
||||
</head>
|
||||
|
||||
<div class="container">
|
||||
<h1>OBS remote (client)</h1>
|
||||
<div id="info">
|
||||
<div class="card">
|
||||
<h2>Scenes</h2>
|
||||
<div id="scene_list">
|
||||
</div>
|
||||
</div>
|
||||
<div class="card hidden">
|
||||
<h2>General</h2>
|
||||
<div>
|
||||
<button onclick="basicCommand(this);" data-command="GetVersion">GetVersion</button>
|
||||
<button onclick="basicCommand(this);" data-command="GetStats">GetStats</button>
|
||||
<button onclick="basicCommand(this);" data-command="GetVideoInfo">GetVideoInfo</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h2>Output</h2>
|
||||
<div id="outputs">
|
||||
<button onclick="basicCommand(this);" data-command="ListOutputs">ListOutputs</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h2>Active Sources</h2>
|
||||
<div id="active_source_list">
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h2>All Sources</h2>
|
||||
<div id="source_list">
|
||||
</div>
|
||||
</div>
|
||||
<div class="card hidden">
|
||||
<h2>Source debug</h2>
|
||||
<div>
|
||||
<button onclick="basicCommand(this);" data-command="GetMediaSourcesList">GetMediaSourcesList</button>
|
||||
<button onclick="basicCommand(this);" data-command="GetSourcesList">GetSourcesList</button>
|
||||
<button onclick="basicCommand(this);" data-command="GetSourceActive">GetSourceActive</button>
|
||||
<button onclick="basicCommand(this);" data-command="GetAudioActive">GetAudioActive</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="audio" class="card hidden">
|
||||
<h2>Audio</h2>
|
||||
<div>
|
||||
<button class="hidden" onclick="basicCommand(this, {source:selectedSource});" data-command="GetVolume">GetVolume</button>
|
||||
<input type='range' min="0" max="100" value="100" onchange="basicCommand(this, {source:selectedSource, volume:parseInt(this.value)/100});" data-command="SetVolume" />
|
||||
<button class="hidden" onclick="basicCommand(this, {source:selectedSource});" data-command="ToggleMute">ToggleMute</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" id='commands'>
|
||||
<h2>Custom Commands</h2>
|
||||
<input id="newCommand" placeholder="enter a custom command" type='text' /><button id="goCreate" onclick="createCommand()">Create</button>
|
||||
<br />
|
||||
A list of possible commands <a href="https://github.com/Palakis/obs-websocket/blob/4.x-current/docs/generated/protocol.md#requests">available here:</a><br />
|
||||
</div>
|
||||
</div>
|
||||
<div style="width:100%;display:block;margin:0;padding:0;">
|
||||
<div id='OBSstats' style="width:49%;display:inline-block;vertical-align: top;">
|
||||
<div id="stat-current-profile" class='stat'></div>
|
||||
<div id="stat-current-scene" class='stat'></div>
|
||||
<div id="stat-streaming" class='stat'></div>
|
||||
<div id="stat-memory-usage" class='stat'></div>
|
||||
<div id="stat-recording" class='stat'></div>
|
||||
<div id="stat-recording-paused" class='stat'></div>
|
||||
<div id="stat-average-frame-time" class='stat'></div>
|
||||
<div id="stat-cpu-usage" class='stat'></div>
|
||||
<div id="stat-fps" class='stat'></div>
|
||||
<div id="stat-free-disk-space" class='stat'></div>
|
||||
</div>
|
||||
<div id='OBSsettings' style="width:49%;display:inline-block;vertical-align: top;">
|
||||
<div id="setting-baseHeight" class='stat'></div>
|
||||
<div id="setting-baseWidth" class='stat'></div>
|
||||
<div id="setting-outputHeight" class='stat'></div>
|
||||
<div id="setting-outputWidth" class='stat'></div>
|
||||
<div id="setting-scaleType" class='stat'></div>
|
||||
<div id="setting-fps" class='stat'></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script>
|
||||
|
||||
function basicCommand(ele, data={}){
|
||||
sendToOBS(ele.dataset.command, data);
|
||||
}
|
||||
|
||||
function createCommand(){
|
||||
var command = document.getElementById("newCommand").value;
|
||||
document.getElementById("newCommand").value = "";
|
||||
var button = document.createElement("button");
|
||||
button.innerText = command;
|
||||
button.dataset.command = command;
|
||||
button.onclick = function(){basicCommand(this);};
|
||||
document.getElementById("commands").appendChild(button);
|
||||
}
|
||||
|
||||
(function(w) {
|
||||
w.URLSearchParams = w.URLSearchParams || function(searchString) {
|
||||
var self = this;
|
||||
searchString = searchString.replace("??", "?");
|
||||
self.searchString = searchString;
|
||||
self.get = function(name) {
|
||||
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(self.searchString);
|
||||
if (results == null) {
|
||||
return null;
|
||||
} else {
|
||||
return decodeURI(results[1]) || 0;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
})(window);
|
||||
|
||||
var urlEdited = window.location.search.replace(/\?\?/g, "?");
|
||||
urlEdited = urlEdited.replace(/\?/g, "&");
|
||||
urlEdited = urlEdited.replace(/\&/, "?");
|
||||
|
||||
if (urlEdited !== window.location.search){
|
||||
warnlog(window.location.search + " changed to " + urlEdited);
|
||||
window.history.pushState({path: urlEdited.toString()}, '', urlEdited.toString());
|
||||
}
|
||||
var urlParams = new URLSearchParams(urlEdited);
|
||||
|
||||
if (urlParams.get("password")){
|
||||
var password = urlParams.get("password");
|
||||
localStorage.setItem('password',password)
|
||||
} else if (localStorage.getItem('password')){
|
||||
password = localStorage.getItem('password');
|
||||
}
|
||||
if (urlParams.get("room")){
|
||||
var roomname = urlParams.get("room")
|
||||
localStorage.setItem('roomname',roomname)
|
||||
} else if (localStorage.getItem('roomname')){
|
||||
roomname = localStorage.getItem('roomname');
|
||||
}
|
||||
|
||||
const obs = new OBSWebSocket();
|
||||
var scenesData = {};
|
||||
var selectedSource = null;
|
||||
scenesData.scenes = [];
|
||||
|
||||
function sendToOBS(action, data){
|
||||
var msg = {};
|
||||
msg.sendToOBS = {};
|
||||
msg.sendToOBS.action = action;
|
||||
msg.sendToOBS.data = data;
|
||||
iframe.contentWindow.postMessage({"sendData":msg}, '*');
|
||||
}
|
||||
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.src = "https://vdo.ninja/?room="+roomname+"&password="+password+"&push&novideo=mainOBSOutput&noaudio=mainOBSOutput&autostart&vd=0&ad=0&transparent&cleanoutput&label=CLIENT_"+Math.floor(Math.random() * 1000000);
|
||||
// iframe.style.opacity = 0;
|
||||
iframe.style.width = "160px";
|
||||
iframe.style.height = "90px";
|
||||
iframe.style.position = "fixed";
|
||||
iframe.style.top = "10px";
|
||||
iframe.style.right = "170px";
|
||||
document.body.appendChild(iframe)
|
||||
|
||||
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
|
||||
var eventer = window[eventMethod];
|
||||
var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message";
|
||||
eventer(messageEvent, function (e) {
|
||||
if (e.source != iframe.contentWindow){return} // reject messages send from other iframes
|
||||
if ("dataReceived" in e.data){
|
||||
if ("sentFromOBS" in e.data.dataReceived){
|
||||
processIncoming(e.data.dataReceived.sentFromOBS);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function changeScene(scene){
|
||||
sendToOBS('SetCurrentScene', {
|
||||
'scene-name': scene
|
||||
});
|
||||
}
|
||||
|
||||
function processIncoming(data){
|
||||
if ("scenes" in data){
|
||||
scenesData = data.scenes;
|
||||
updateSceneList();
|
||||
}
|
||||
if ("callbackData" in data){
|
||||
console.log(data.callbackData);
|
||||
} else if ("callbackError" in data){
|
||||
console.log(data.callbackError);
|
||||
}
|
||||
if ("rawData" in data){
|
||||
var data = JSON.parse(data.rawData);
|
||||
console.log(data);
|
||||
if ("stats" in data){
|
||||
var i = "stats";
|
||||
for (var j in data[i]){
|
||||
if (document.getElementById("stat-"+j)){
|
||||
|
||||
if (typeof data[i][j] == "number"){
|
||||
data[i][j] = parseInt(data[i][j]*100)/100.0;
|
||||
}
|
||||
if (data[i][j]===true){
|
||||
document.getElementById("stat-"+j).innerHTML = j+ " : <font color='#CFC'>" + data[i][j]+"</font>";
|
||||
} else if (data[i][j] === false){
|
||||
document.getElementById("stat-"+j).innerHTML = j+ " : <font color='#FCC'>" + data[i][j]+"</font>";
|
||||
} else {
|
||||
document.getElementById("stat-"+j).innerHTML = j+ " : <font color='#DDD'>" + data[i][j]+"</font>";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ("baseHeight" in data){
|
||||
for (var i in data){
|
||||
if (document.getElementById("setting-"+i)){
|
||||
if (data[i]===true){
|
||||
document.getElementById("setting-"+i).innerHTML = i+ " : <font color='#CFC'>" + data[i]+"</font>";
|
||||
} else if (data[i] === false){
|
||||
document.getElementById("setting-"+i).innerHTML = i+ " : <font color='#FCC'>" + data[i]+"</font>";
|
||||
} else {
|
||||
document.getElementById("setting-"+i).innerHTML = i+ " : <font color='#DDD'>" + data[i]+"</font>";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ("sources" in data){
|
||||
if ("name" in data){
|
||||
document.getElementById("active_source_list").innerHTML = "";
|
||||
for (var i =0;i<data.sources.length;i++){
|
||||
var button = document.createElement("button");
|
||||
button.innerText = data.sources[i].name;
|
||||
button.dataset.name = data.sources[i].name;
|
||||
button.dataset.type = "source"
|
||||
button.onclick = function(){
|
||||
console.log("CLICKED: " + this.innerText);
|
||||
selectedSource = this.dataset.name;
|
||||
document.getElementById("audio").classList.add("hidden");
|
||||
var sources = document.querySelectorAll("[data-name");
|
||||
for (var k = 0 ; k<sources.length; k++){
|
||||
sources[k].classList.remove("pressed");
|
||||
}
|
||||
var sources = document.querySelectorAll("[data-name='"+selectedSource+"']");
|
||||
console.log(sources);
|
||||
for (var k = 0 ; k<sources.length; k++){
|
||||
document.getElementById("audio").classList.remove("hidden");
|
||||
sources[k].classList.add("pressed");
|
||||
}
|
||||
};
|
||||
document.getElementById("active_source_list").appendChild(button);
|
||||
}
|
||||
if (selectedSource){
|
||||
var sources = document.querySelectorAll("[data-name");
|
||||
document.getElementById("audio").classList.add("hidden");
|
||||
for (var k = 0 ; k<sources.length; k++){
|
||||
sources[k].classList.remove("pressed");
|
||||
}
|
||||
var sources = document.querySelectorAll("[data-name='"+selectedSource+"']");
|
||||
console.log(sources);
|
||||
for (var k = 0 ; k<sources.length; k++){
|
||||
sources[k].classList.add("pressed");
|
||||
document.getElementById("audio").classList.remove("hidden");
|
||||
}
|
||||
} else {
|
||||
document.getElementById("audio").classList.add("hidden");
|
||||
}
|
||||
} else {
|
||||
document.getElementById("source_list").innerHTML = "";
|
||||
for (var i =0;i<data.sources.length;i++){
|
||||
var button = document.createElement("button");
|
||||
button.innerText = data.sources[i].name;
|
||||
button.dataset.name = data.sources[i].name;
|
||||
button.dataset.type = "source"
|
||||
button.onclick = function(){
|
||||
console.log("CLICKED: " + this.innerText);
|
||||
selectedSource = this.dataset.name;
|
||||
document.getElementById("audio").classList.add("hidden");
|
||||
var sources = document.querySelectorAll("[data-name");
|
||||
for (var k = 0 ; k<sources.length; k++){
|
||||
sources[k].classList.remove("pressed");
|
||||
}
|
||||
var sources = document.querySelectorAll("[data-name='"+selectedSource+"']");
|
||||
console.log(sources);
|
||||
for (var k = 0 ; k<sources.length; k++){
|
||||
sources[k].classList.add("pressed");
|
||||
document.getElementById("audio").classList.remove("hidden");
|
||||
}
|
||||
};
|
||||
document.getElementById("source_list").appendChild(button);
|
||||
}
|
||||
if (selectedSource){
|
||||
var sources = document.querySelectorAll("[data-name");
|
||||
document.getElementById("audio").classList.add("hidden");
|
||||
for (var k = 0 ; k<sources.length; k++){
|
||||
sources[k].classList.remove("pressed");
|
||||
}
|
||||
var sources = document.querySelectorAll("[data-name='"+selectedSource+"']");
|
||||
console.log(sources);
|
||||
for (var k = 0 ; k<sources.length; k++){
|
||||
sources[k].classList.add("pressed");
|
||||
document.getElementById("audio").classList.remove("hidden");
|
||||
}
|
||||
} else {
|
||||
document.getElementById("audio").classList.add("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
<!-- congestion: 0 -->
|
||||
<!-- droppedFrames: 0 -->
|
||||
<!-- flags: {audio: true, encoded: true, multiTrack: true, rawValue: 31, service: true, …} -->
|
||||
<!-- height: 1080 -->
|
||||
<!-- name: "simple_stream" -->
|
||||
<!-- reconnecting: false -->
|
||||
<!-- settings: {bind_ip: 'default', dyn_bitrate: false, low_latency_mode_enabled: false, new_socket_loop_enabled: false} -->
|
||||
<!-- totalBytes: 351121 -->
|
||||
<!-- totalFrames: 30 -->
|
||||
<!-- type: "rtmp_output" -->
|
||||
<!-- width: 1920 -->
|
||||
|
||||
} else if ("outputs" in data){
|
||||
document.getElementById("outputs").innerHTML = "";
|
||||
for (var i =0;i<data.outputs.length;i++){
|
||||
var button = document.createElement("button");
|
||||
button.innerText = data.outputs[i].name;
|
||||
button.dataset.output = data.outputs[i].name;
|
||||
button.onclick = function(){
|
||||
console.log("CLICKED: " + this.innerText);
|
||||
var outputName = this.dataset.output;
|
||||
if (this.classList.contains("pressed")){
|
||||
this.classList.remove("pressed");
|
||||
sendToOBS("StopOutput",{outputName:outputName});
|
||||
} else {
|
||||
this.classList.add("pressed");
|
||||
sendToOBS("StartOutput",{outputName:outputName});
|
||||
}
|
||||
};
|
||||
document.getElementById("outputs").appendChild(button);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function updateSceneList(){
|
||||
var scenes = scenesData.scenes;
|
||||
document.getElementById("scene_list").innerHTML = "";
|
||||
scenes.forEach(scene => {
|
||||
var button = document.createElement("button");
|
||||
button.innerText = scene.name;
|
||||
button.onclick = function(){
|
||||
console.log("CLICKED");
|
||||
changeScene(this.innerText);
|
||||
}; // "speaker" also works in the same way.
|
||||
document.getElementById("scene_list").appendChild(button);
|
||||
|
||||
if (scene.name === scenesData.currentScene) {
|
||||
button.classList.add("pressed");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
10
examples/obs_remote/thirdparty/obs-websocket.min.js
vendored
Normal file
10
examples/obs_remote/thirdparty/obs-websocket.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
23
examples/readme.md
Normal file
23
examples/readme.md
Normal file
@ -0,0 +1,23 @@
|
||||
p2p is a sample of how to use vdo.ninja as a data transport tunneling service
|
||||
|
||||
twitch is an example of how to have a twitch live chat side-by-side with VDO.NInja on the same screen
|
||||
|
||||
dual is an example of how to have two VDO.Ninja windows (or any windows really) open on the same page; Picture-in-Picture style
|
||||
|
||||
sensors is an example of how to transmit sensor and video data from a phone to a computer, drawing it to canvas: youtube video for this exists
|
||||
|
||||
midi demonstrates the MIDI API for VDO.Ninja
|
||||
|
||||
draggable demonstrates how to drag multiple windows around, if you wanted to create a custom layout of elements. (experimental)
|
||||
|
||||
chat.html is an example of a chat-only interface for VDO.NInja; maybe dockable into OBS even
|
||||
|
||||
iframe.outbound-stats.html demostrates how to get stats from VDO.Ninja using the IFRAME API
|
||||
|
||||
changepass lets you create passwords and related HASH values for VDO.NInja rooms
|
||||
|
||||
webhid demonstrates how to interface with a USB device, like a streamdeck (mouse/keyboard not supported)
|
||||
|
||||
zoom.html is a tool for letting you publish into VDO.Ninja, but then full-screen the window once setup, allowing for window-capturing into zoom.
|
||||
|
||||
obs_remote is also hosted on github elsewhere, but it's an example of how to remotely control OBS using VDO.Ninja's tunneling abilities
|
||||
793
iframe.html
793
iframe.html
@ -12,8 +12,8 @@ iframe {
|
||||
padding:0;
|
||||
display:block;
|
||||
margin:10px;
|
||||
width:640px;
|
||||
height:320px;
|
||||
width:100%;
|
||||
height:520px;
|
||||
}
|
||||
#viewlink {
|
||||
width:400px;
|
||||
@ -77,312 +77,523 @@ function loadIframe(){ // this is pretty important if you want to avoid camera
|
||||
document.getElementById("container").appendChild(iframeContainer);
|
||||
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Mute Speaker";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"mute":true}, '*');}; // "speaker" also works in the same way.
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Un-Mute Speaker";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"mute":false}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Toggle Speaker";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"mute":"toggle"}, '*');}; // open to a better suggestion here.
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Mute Mic";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"mic":false}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Un-Mute Mic";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"mic":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Toggle Mic";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"mic":"toggle"}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Mute Camera";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"camera":false}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Unmute Camera";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"camera":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Toggle Camera";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"camera":"toggle"}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Disconnect";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"close":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Low Bitrate";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":30}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "High Bitrate";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":5000}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Default Bitrate";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":-1}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Reload";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"reload":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "50% Volume";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"volume":0.5}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "100% Volume";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"volume":1.0}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Pan Left";
|
||||
button.title = "Requires &panning to be added to the view link";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"panning":0}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Pan right";
|
||||
button.title = "Requires &panning to be added to the view link";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"panning":180}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Pan Center";
|
||||
button.title = "Requires &panning to be added to the view link";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"panning":90}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Request Loudness Levels";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Stop Sending Loudness Levels";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":false}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Start Recording";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"record":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Stop Recording";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"record":false}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Say Hello";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"sendChat":"Hello!"}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Send Keyframe";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"keyframe":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Insert Style Sheet";
|
||||
var stylesheet = "#main { zoom: 0.5;} video {float: left; margin: 0; padding: 0; } #info {display:none;}";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"style":stylesheet}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "get StreamIDs and labels";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"getStreamIDs":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Start AutoMixer";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"automixer":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Stop AutoMixer";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"automixer":false}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "ENABLE TALLY LIGHT";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"sceneState":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "STOP TALLY LIGHT";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"sceneState":false}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Add Target Video";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"target":"*", "add":true, "settings":{"style":{"width":"640px", "height":"360px", "float":"left", "border":"10px solid red", "display":"block"}}}, '*');}; // target can be a stream ID or * for all.
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Remove Target Video";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"target":"*", "remove": true}, '*');}; // target can be a stream ID or * for all.
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "previewWebcam()";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"function":"previewWebcam"}, '*');}; // publishScreen
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Change to Camera #2";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"changeVideoDevice":2}, '*');}; // change text of add camera button
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Change to Microphone #4";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"changeAudioDevice":4}, '*');}; // change text of add camera button
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "eval('alert(\"DANGERUS\")'";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"function":"eval", "value":'alert(\"DANGERUS\")'}, '*');}; // publishScreen
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Change Add Camera text";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"function":"changeHTML", "target":"add_camera", "value":"NEW CAMERA TEXT"}, '*');}; // change text of add camera button
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "CLOSE IFRAME";
|
||||
button.onclick = function(){iframeContainer.parentNode.removeChild(iframeContainer);};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////// LISTEN FOR EVENTS
|
||||
var h3 = document.createElement("h3");
|
||||
h3.innerText = "The following commands are exclusive to the IFRAME API.";
|
||||
iframeContainer.appendChild(h3);
|
||||
|
||||
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
|
||||
var eventer = window[eventMethod];
|
||||
var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message";
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Mute Speaker";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"mute":true}, '*');}; // "speaker" also works in the same way.
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Un-Mute Speaker";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"mute":false}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Toggle Speaker";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"mute":"toggle"}, '*');}; // open to a better suggestion here.
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Mute Mic";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"mic":false}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Un-Mute Mic";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"mic":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Toggle Mic";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"mic":"toggle"}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Mute Camera";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"camera":false}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Unmute Camera";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"camera":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Toggle Camera";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"camera":"toggle"}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Disconnect";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"close":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Low Bitrate";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":30}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "High Bitrate";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":5000}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Default Bitrate";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":-1}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Reload";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"reload":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "50% Volume";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"volume":0.5}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "100% Volume";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"volume":1.0}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Pan Left";
|
||||
button.title = "Requires &panning to be added to the view link";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"panning":0}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Pan right";
|
||||
button.title = "Requires &panning to be added to the view link";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"panning":180}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Pan Center";
|
||||
button.title = "Requires &panning to be added to the view link";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"panning":90}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Request Loudness Levels";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Stop Sending Loudness Levels";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":false}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Start Recording";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"record":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Stop Recording";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"record":false}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Say Hello";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"sendChat":"Hello!"}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Send Keyframe";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"keyframe":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Insert Style Sheet";
|
||||
var stylesheet = "#main { zoom: 0.5;} video {float: left; margin: 0; padding: 0; } #info {display:none;}";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"style":stylesheet}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "get StreamIDs and labels";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"getStreamIDs":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Start AutoMixer";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"automixer":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Stop AutoMixer";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"automixer":false}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "ENABLE TALLY LIGHT";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"sceneState":true}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "STOP TALLY LIGHT";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"sceneState":false}, '*');};
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Add Target Video";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"target":"*", "add":true, "settings":{"style":{"width":"640px", "height":"360px", "float":"left", "border":"10px solid red", "display":"block"}}}, '*');}; // target can be a stream ID or * for all.
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Remove Target Video";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"target":"*", "remove": true}, '*');}; // target can be a stream ID or * for all.
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "previewWebcam()";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"function":"previewWebcam"}, '*');}; // publishScreen
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Change to Camera #2";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"changeVideoDevice":2}, '*');}; // change text of add camera button
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Change to Microphone #4";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"changeAudioDevice":4}, '*');}; // change text of add camera button
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "eval('alert(\"DANGERUS\")'";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"function":"eval", "value":'alert(\"DANGERUS\")'}, '*');}; // publishScreen
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Change Add Camera text";
|
||||
button.onclick = function(){iframe.contentWindow.postMessage({"function":"changeHTML", "target":"add_camera", "value":"NEW CAMERA TEXT"}, '*');}; // change text of add camera button
|
||||
iframeContainer.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "CLOSE IFRAME";
|
||||
button.onclick = function(){iframeContainer.parentNode.removeChild(iframeContainer);};
|
||||
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.
|
||||
/// 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
|
||||
|
||||
eventer(messageEvent, function (e) {
|
||||
if (e.source != iframe.contentWindow){return} // reject messages send from other iframes
|
||||
if ("stats" in e.data){
|
||||
var outputWindow = document.createElement("div");
|
||||
console.log(e.data.stats);
|
||||
|
||||
if ("stats" in e.data){
|
||||
var outputWindow = document.createElement("div");
|
||||
console.log(e.data.stats);
|
||||
|
||||
|
||||
var out = "<br />total_inbound_connections:"+e.data.stats.total_inbound_connections;
|
||||
out += "<br />total_outbound_connections:"+e.data.stats.total_outbound_connections;
|
||||
|
||||
for (var streamID in e.data.stats.inbound_stats){
|
||||
out += "<br /><br /><b>streamID:</b> "+streamID+"<br />";
|
||||
out += printValues(e.data.stats.inbound_stats[streamID]);
|
||||
}
|
||||
|
||||
outputWindow.innerHTML = out;
|
||||
iframeContainer.appendChild(outputWindow);
|
||||
|
||||
var out = "<br />total_inbound_connections:"+e.data.stats.total_inbound_connections;
|
||||
out += "<br />total_outbound_connections:"+e.data.stats.total_outbound_connections;
|
||||
|
||||
for (var streamID in e.data.stats.inbound_stats){
|
||||
out += "<br /><br /><b>streamID:</b> "+streamID+"<br />";
|
||||
out += printValues(e.data.stats.inbound_stats[streamID]);
|
||||
}
|
||||
|
||||
if ("gotChat" in e.data){
|
||||
outputWindow.innerHTML = out;
|
||||
iframeContainer.appendChild(outputWindow);
|
||||
}
|
||||
|
||||
if ("gotChat" in e.data){
|
||||
var outputWindow = document.createElement("div");
|
||||
outputWindow.innerHTML = e.data.gotChat.msg;
|
||||
outputWindow.style.border="1px dotted black";
|
||||
iframeContainer.appendChild(outputWindow);
|
||||
}
|
||||
|
||||
if ("action" in e.data){
|
||||
var outputWindow = document.createElement("div");
|
||||
outputWindow.innerHTML = "child-page-action: "+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 = "child-page-action: streamIDs<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);
|
||||
}
|
||||
|
||||
if ("loudness" in e.data){
|
||||
console.log(e.data);
|
||||
if (document.getElementById("loudness")){
|
||||
outputWindow = document.getElementById("loudness");
|
||||
} else {
|
||||
var outputWindow = document.createElement("div");
|
||||
outputWindow.innerHTML = e.data.gotChat.msg;
|
||||
outputWindow.style.border="1px dotted black";
|
||||
iframeContainer.appendChild(outputWindow);
|
||||
outputWindow.id = "loudness";
|
||||
}
|
||||
outputWindow.innerHTML = "child-page-action: loudness<br />";
|
||||
for (var key in e.data.loudness) {
|
||||
outputWindow.innerHTML += key + " Loudness: " + e.data.loudness[key] + "\n";
|
||||
}
|
||||
outputWindow.style.border="1px black";
|
||||
|
||||
if ("action" in e.data){
|
||||
}
|
||||
|
||||
if ("sensors" in e.data){
|
||||
console.log(e.data);
|
||||
if (document.getElementById("sensors")){
|
||||
outputWindow = document.getElementById("sensors");
|
||||
} else {
|
||||
var outputWindow = document.createElement("div");
|
||||
outputWindow.innerHTML = "child-page-action: "+e.data.action+"<br />";
|
||||
outputWindow.style.border="1px dotted black";
|
||||
iframeContainer.appendChild(outputWindow);
|
||||
outputWindow.id = "sensors";
|
||||
}
|
||||
|
||||
|
||||
if ("streamIDs" in e.data){
|
||||
var outputWindow = document.createElement("div");
|
||||
outputWindow.innerHTML = "child-page-action: streamIDs<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);
|
||||
}
|
||||
|
||||
if ("loudness" in e.data){
|
||||
console.log(e.data);
|
||||
if (document.getElementById("loudness")){
|
||||
outputWindow = document.getElementById("loudness");
|
||||
} else {
|
||||
var outputWindow = document.createElement("div");
|
||||
outputWindow.style.border="1px dotted black";
|
||||
iframeContainer.appendChild(outputWindow);
|
||||
outputWindow.id = "loudness";
|
||||
}
|
||||
outputWindow.innerHTML = "child-page-action: loudness<br />";
|
||||
for (var key in e.data.loudness) {
|
||||
outputWindow.innerHTML += key + " Loudness: " + e.data.loudness[key] + "\n";
|
||||
}
|
||||
outputWindow.style.border="1px black";
|
||||
outputWindow.innerHTML = "child-page-action: sensors<br /><br />";
|
||||
|
||||
for (var key in e.data.sensors.lin) {
|
||||
outputWindow.innerHTML += key + " linear: " + e.data.sensors.lin[key] + "<br />";
|
||||
}
|
||||
for (var key in e.data.sensors.acc) {
|
||||
outputWindow.innerHTML += key + " acceleration: " + e.data.sensors.acc[key] + "<br />";
|
||||
}
|
||||
for (var key in e.data.sensors.gyro) {
|
||||
outputWindow.innerHTML += key + " gyro: " + e.data.sensors.gyro[key] + "<br />";
|
||||
}
|
||||
for (var key in e.data.sensors.mag) {
|
||||
outputWindow.innerHTML += key + " magnet: " + e.data.sensors.mag[key] + "<br />";
|
||||
}
|
||||
outputWindow.style.border="1px black";
|
||||
|
||||
if ("sensors" in e.data){
|
||||
console.log(e.data);
|
||||
if (document.getElementById("sensors")){
|
||||
outputWindow = document.getElementById("sensors");
|
||||
} else {
|
||||
var outputWindow = document.createElement("div");
|
||||
outputWindow.style.border="1px dotted black";
|
||||
iframeContainer.appendChild(outputWindow);
|
||||
outputWindow.id = "sensors";
|
||||
}
|
||||
outputWindow.innerHTML = "child-page-action: sensors<br /><br />";
|
||||
|
||||
for (var key in e.data.sensors.lin) {
|
||||
outputWindow.innerHTML += key + " linear: " + e.data.sensors.lin[key] + "<br />";
|
||||
}
|
||||
for (var key in e.data.sensors.acc) {
|
||||
outputWindow.innerHTML += key + " acceleration: " + e.data.sensors.acc[key] + "<br />";
|
||||
}
|
||||
for (var key in e.data.sensors.gyro) {
|
||||
outputWindow.innerHTML += key + " gyro: " + e.data.sensors.gyro[key] + "<br />";
|
||||
}
|
||||
for (var key in e.data.sensors.mag) {
|
||||
outputWindow.innerHTML += key + " magnet: " + e.data.sensors.mag[key] + "<br />";
|
||||
}
|
||||
outputWindow.style.border="1px black";
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function loadSelfCommands(){
|
||||
var commands = {}
|
||||
commands.speaker = function(value){sendSelfCommand("speaker",value)}; // "speaker" also works in the same way
|
||||
|
||||
commands.mic = function(value){sendSelfCommand("mic",value)};
|
||||
|
||||
commands.camera = function(value){sendSelfCommand("camera",value)};
|
||||
|
||||
commands.bitrate = function(value){sendSelfCommand("bitrate",value)};
|
||||
|
||||
commands.volume = function(value){sendSelfCommand("volume",value)};
|
||||
|
||||
commands.record = function(value){sendSelfCommand("record",value)};
|
||||
|
||||
commands.sayHello = function(value){sendSelfCommand("sendChat","Hello")};
|
||||
|
||||
var target_self = document.body;
|
||||
|
||||
var hr = document.createElement("hr");
|
||||
target_self.appendChild(hr);
|
||||
|
||||
var h3 = document.createElement("h3");
|
||||
h3.innerText = "The following commands re-use the Companion.Ninja HTTP/WSS API, except you can send them via this Iframe interface.";
|
||||
target_self.appendChild(h3);
|
||||
|
||||
var a = document.createElement("a");
|
||||
a.innerText = "More details of the below IFRAME API details are here: https://github.com/steveseguin/Companion-Ninja#api-commands";
|
||||
a.href = "https://github.com/steveseguin/Companion-Ninja#api-commands";
|
||||
a.target = "_blank";
|
||||
target_self.appendChild(a);
|
||||
|
||||
var hr = document.createElement("hr");
|
||||
target_self.appendChild(hr);
|
||||
|
||||
|
||||
for (var k in commands) {
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = k + ":<br />TRUE";
|
||||
button.dataset.command = k;
|
||||
button.onclick = function(){commands[this.dataset.command](true);}
|
||||
target_self.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = k + ":<br />FALSE";
|
||||
button.dataset.command = k;
|
||||
button.onclick = function(){commands[this.dataset.command](false);}
|
||||
target_self.appendChild(button);
|
||||
|
||||
} // list available commands to console
|
||||
|
||||
commands.reload = function(){sendSelfCommand("reload",true);};
|
||||
|
||||
commands.hangup = function(){sendSelfCommand("hangup",true);};
|
||||
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = k + ":<br />TRUE";
|
||||
button.onclick = function(){commands["reload"](true);}
|
||||
target_self.appendChild(button);
|
||||
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = k + ":<br />TRUE";
|
||||
button.onclick = function(){commands["hangup"](true);}
|
||||
target_self.appendChild(button);
|
||||
|
||||
return commands;
|
||||
|
||||
}
|
||||
|
||||
function loadGuestCommands(guestid, streamID=false){ // this is the same as the Companion API, but can be issued to the IFRAME API
|
||||
|
||||
var container = document.createElement("div");
|
||||
container.id = "guest_"+guestid+"_container";
|
||||
document.body.appendChild(container);
|
||||
|
||||
var hr = document.createElement("hr");
|
||||
container.appendChild(hr);
|
||||
var h3 = document.createElement("h3");
|
||||
if (streamID){
|
||||
h3.innerHTML = "These target guest with the streamID: <i>"+guestid+ "</i> (if a director)";
|
||||
} else {
|
||||
h3.innerText = "These target the guest in slot "+guestid+ " (if you are director)";
|
||||
}
|
||||
container.appendChild(h3);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "transfer popup";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "forward");};
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "transfer to 'room321'";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "forward", 'room321');};
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "scene 1";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "addScene");}; /// SCENE 1 or specify a custom scene name as a value
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "mute in scene";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "muteScene");};
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "mute everywhere";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "mic");};
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "hang up";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "hangup");};
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "solo chat";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "soloChat");};
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "remote speaker";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "speaker");};
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "remote display";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "display");};
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "rainbow puke fix";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "forceKeyframe");};
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "highlight";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "soloVideo");};
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "scene 2";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "addScene", 2);};
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "scene 3";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "addScene", 3);};
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "scene 4";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "addScene", 4);};
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "scene 5";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "addScene", 5);};
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "scene 6";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "addScene", 6);};
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = " scene 7";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "addScene", 7);};
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "scene 8";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "addScene", 8);};
|
||||
container.appendChild(button);
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "scene 'test'";
|
||||
button.onclick = function(){sendGuestCommand(guestid, "addScene", 'test');}; // specifying a custom scene; it needs to be active for this to work..
|
||||
container.appendChild(button);
|
||||
|
||||
|
||||
var input = document.createElement("label");
|
||||
input.innerHTML = "mic volume:";
|
||||
container.appendChild(input);
|
||||
var input = document.createElement("input");
|
||||
input.type = "range";
|
||||
input.title = "volume";
|
||||
input.min = 0;
|
||||
input.max = 200;
|
||||
input.value = 100;
|
||||
input.onchange = function(){sendGuestCommand(guestid, "volume", this.value);};
|
||||
container.appendChild(input);
|
||||
|
||||
}
|
||||
|
||||
function sendGuestCommand(target, action, value=null){ //
|
||||
iframe.contentWindow.postMessage({"target":target, "action":action, "value":value}, '*'); //
|
||||
//sendMessage(JSON.stringify({"target":target, "action":action, "value":value})); // if using the Companion API..
|
||||
}
|
||||
|
||||
function sendSelfCommand(action, value=null){
|
||||
iframe.contentWindow.postMessage({"target":null, "action":action, "value":value}, '*');
|
||||
//sendMessage(JSON.stringify({"target":target, "action":action, "value":value})); // if using the Companion API..
|
||||
}
|
||||
|
||||
loadSelfCommands();
|
||||
loadGuestCommands(1);
|
||||
loadGuestCommands(2);
|
||||
loadGuestCommands(3);
|
||||
var randomGuest = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 10);
|
||||
loadGuestCommands(randomGuest, true);
|
||||
|
||||
}
|
||||
|
||||
@ -407,8 +618,8 @@ function printValues( obj) {
|
||||
|
||||
<input placeholder="Enter an VDO.Ninja View URL here" id="viewlink" />
|
||||
<button onclick="loadIframe();">ADD</button>
|
||||
<input type="checkbox" id="clean" checked>Clean Output
|
||||
<input type="checkbox" id="transparent" checked>Transparent
|
||||
<input type="checkbox" id="clean" >Clean Output
|
||||
<input type="checkbox" id="transparent">Transparent
|
||||
<input type="checkbox" id="hidemenu">Hide Menu
|
||||
<div id="container">
|
||||
|
||||
|
||||
109
index.html
109
index.html
@ -22,7 +22,7 @@
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="./media/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="./media/favicon-16x16.png" />
|
||||
<link rel="icon" href="./media/favicon.ico" />
|
||||
<link itemprop="thumbnailUrl" href="./media/obsNinja_logo_full.png" />
|
||||
<link itemprop="thumbnailUrl" href="./media/vdoNinja_logo_full.png" />
|
||||
<!-- Primary Meta Tags -->
|
||||
<title>VDO.Ninja</title>
|
||||
<meta name="title" content="VDO.Ninja" />
|
||||
@ -34,8 +34,8 @@
|
||||
<meta property="og:url" content="https://vdo.ninja/" />
|
||||
<meta property="og:title" content="VDO.Ninja" />
|
||||
<meta property="og:description" content="Bring live video from your smartphone, computer, or friends directly into Studio. 100% free." />
|
||||
<meta property="og:image" itemprop="image" content="https://vdo.ninja/media/obsNinja_logo_full.png" />
|
||||
<meta name="msapplication-TileImage" content="./media/obsNinja_logo_full.png" />
|
||||
<meta property="og:image" itemprop="image" content="https://vdo.ninja/media/vdoNinja_logo_full.png" />
|
||||
<meta name="msapplication-TileImage" content="./media/vdoNinja_logo_full.png" />
|
||||
<meta property="og:image:type" content="image/png" />
|
||||
<meta property="og:image:width" content="1200" />
|
||||
<meta property="og:image:height" content="630" />
|
||||
@ -44,7 +44,7 @@
|
||||
<meta property="twitter:url" content="https://vdo.ninja/" />
|
||||
<meta property="twitter:title" content="VDO.Ninja" />
|
||||
<meta property="twitter:description" content="Bring live video from your smartphone, computer, or friends directly into OBS Studio. 100% free." />
|
||||
<meta property="twitter:image" content="./media/obsNinja_logo_full.png" />
|
||||
<meta property="twitter:image" content="./media/vdoNinja_logo_full.png" />
|
||||
<meta name="msapplication-TileColor" content="#da532c" />
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
<style>
|
||||
@ -54,18 +54,17 @@
|
||||
transition: opacity .1s linear;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="./lineawesome/css/line-awesome.min.css" />
|
||||
<link rel="stylesheet" href="./main.css?ver=78" />
|
||||
<link rel="stylesheet" href="./main.css?ver=124" />
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/adapter.min.js"></script>
|
||||
<style id="lightbox-animations" type="text/css"></style>
|
||||
</head>
|
||||
<body id="main" class="hidden">
|
||||
<span itemprop="image" itemscope itemtype="image/png">
|
||||
<link itemprop="url" href="./media/obsNinja_logo_full.png" />
|
||||
<link itemprop="url" href="./media/vdoNinja_logo_full.png" />
|
||||
</span>
|
||||
<link itemprop="thumbnailUrl" href="./media/obsNinja_logo_full.png" />
|
||||
<link itemprop="thumbnailUrl" href="./media/vdoNinja_logo_full.png" />
|
||||
<span itemprop="thumbnail" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<link itemprop="url" href="./media/obsNinja_logo_full.png" />
|
||||
<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=291"></script>
|
||||
@ -273,7 +272,7 @@
|
||||
</tr><tr>
|
||||
<th></th>
|
||||
<th style="text-align:right;">
|
||||
<button onclick="createRoom()" class="gobutton" style="float: left;" alt="Enter the room as the group's director" title="You'll enter as the room's director">
|
||||
<button onclick="createRoom()" class="gobutton" style="float: left;width:100%;" alt="Enter the room as the group's director" title="You'll enter as the room's director">
|
||||
<span data-translate="enter-the-rooms-control">Enter the Room's Control Center</span>
|
||||
</button>
|
||||
<br /><br />
|
||||
@ -381,14 +380,14 @@
|
||||
</ul>
|
||||
</div>
|
||||
<br />
|
||||
<span id="headphonesDiv" style="text-align:left; margin:17px 0 0 0; max-width: 550px; min-width: 420px; background-color: #f3f3f3; display: none; padding: 10px 10px; border: 1px solid #ccc; vertical-align: middle;">
|
||||
<span id="headphonesDiv" class="audioMenu">
|
||||
<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;" type="button">Test</button></div>
|
||||
<select id="outputSource" ></select>
|
||||
|
||||
</span>
|
||||
<div id="effectsDiv" style="user-select: none; font-size:100%; text-align:left; margin: 17px auto; max-width:450px; min-width: 420px; background-color: #f3f3f3; display: none; padding: 10px 10px; border: 1px solid #ccc; vertical-align: middle;">
|
||||
<div id="effectsDiv">
|
||||
<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>
|
||||
@ -397,6 +396,9 @@
|
||||
<option value="3" data-translate="blurred-background">Blurred background</option>
|
||||
<option value="4" data-translate="digital-greenscreen">Digital greenscreen</option>
|
||||
<option value="5" data-translate="virtual-background">Virtual background</option>
|
||||
<option class="advanced" value="6" data-translate="face-mesh">Face mesh (slow load)</option>
|
||||
<option class="advanced" value="anon" data-translate="anonymous-mask">Anonymous mask</option>
|
||||
<option class="advanced" value="dog" data-translate="dog-face">Dog ears and nose</option>
|
||||
</select>
|
||||
<span data-warnSimdNotice="true" style='display:none; font-size: 140%; margin-left:10px; vertical-align: middle; cursor:pointer' title="Improve performance and quality with this tip" onclick="warnUser(`For improved performance, use Chrome v87 or newer with SIMD support enabled.<br />Enable SIMD here: <a href='chrome://flags/#enable-webassembly-simd' target='_blank' onclick='copyFunction(this,event)' >chrome://flags/#enable-webassembly-simd</a>`);">
|
||||
<i class="las la-info-circle"></i>
|
||||
@ -415,19 +417,7 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<span id="addPasswordBasic" style="width: 450px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
border-bottom: 0;
|
||||
display: block;
|
||||
text-align: left;
|
||||
margin: 17px auto 0 auto;
|
||||
max-width: 450px;
|
||||
min-width: 420px;
|
||||
background-color: #f3f3f3;
|
||||
padding: 10px 10px;
|
||||
border: 1px solid #ccc;
|
||||
vertical-align: middle;">
|
||||
<span id="addPasswordBasic" >
|
||||
<i class="las la-key"></i><span data-translate="add-a-password"> Add a Password:</span>
|
||||
<input type="text" id="passwordBasicInput" placeholder="optional" style="border: solid 1px #AAA;
|
||||
padding: 4px 6px;
|
||||
@ -556,54 +546,60 @@
|
||||
<div class="invite_setting_item">
|
||||
<input type="checkbox" id="invite_bitrate" />
|
||||
<label for="invite_bitrate">
|
||||
<span data-translate="unlock-video-bitrate" title="Ideal for 1080p60 gaming, if your computer and upload are up for it" >Unlock Video Bitrate (20mbps)</span>
|
||||
<span data-translate="unlock-video-bitrate" title="Ideal for 1080p60 gaming, if your computer and upload are up for it" >Unlock the video bitrate (20mbps)</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="invite_setting_item">
|
||||
<input type="checkbox" id="invite_vp9" />
|
||||
<label for="invite_vp9">
|
||||
<span data-translate="force-vp9-video-codec" title="Better video compression and quality at the cost of increased CPU encoding load">Force VP9 Video Codec</span>
|
||||
<span data-translate="force-vp9-video-codec" title="Better video compression and quality at the cost of increased CPU encoding load">Use the VP9 video codec</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="invite_setting_item">
|
||||
<input type="checkbox" id="invite_stereo" />
|
||||
<label for="invite_stereo">
|
||||
<span data-translate="enable-stereo-and-pro" title="Disable digital audio-effects and increase audio bitrate">Enable Stereo and Pro HD Audio</span>
|
||||
<span data-translate="enable-stereo-and-pro" title="Disable digital audio-effects and increase audio bitrate">Enable stereo and pro HD audio</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="invite_setting_item">
|
||||
<label for="invite_quality" data-translate="video-resolution">Video Resolution: </label>
|
||||
<label for="invite_quality" data-translate="video-resolution">Video resolution: </label>
|
||||
<select id="invite_quality" name="invite_quality">
|
||||
<option value="-1" selected>User Selectable</option>
|
||||
<option value="0">Maximum Resolution</option>
|
||||
<option value="-1" selected>User selectable</option>
|
||||
<option value="0">Maximum resolution</option>
|
||||
<option value="1">Balanced</option>
|
||||
<option value="2">Smooth and Cool</option>
|
||||
<option value="2">Smooth and cool</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="invite_setting_group">
|
||||
<div class="invite_setting_item">
|
||||
<input type="checkbox" id="invite_effects" />
|
||||
<label for="invite_effects">
|
||||
<span data-translate="allow-effects-invite" title="The guest will be able to select digital video effects to apply.">Allow video effects to be used</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="invite_setting_item">
|
||||
<input type="checkbox" id="invite_automic" />
|
||||
<label for="invite_automic">
|
||||
<span data-translate="hide-mic-selection" title="The guest will not have a choice over audio-options">Force Default Microphone</span>
|
||||
<span data-translate="hide-mic-selection" title="The guest will not have a choice over audio-options">Force select the default microphone</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="invite_setting_item">
|
||||
<input type="checkbox" id="invite_hidescreen" />
|
||||
<label for="invite_hidescreen">
|
||||
<span data-translate="hide-screen-share" title="The guest will only be able to select their webcam as an option">Hide Screenshare Option</span>
|
||||
<span data-translate="hide-screen-share" title="The guest will only be able to select their webcam as an option">Hide the screenshare option</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="invite_setting_item">
|
||||
<input type="checkbox" id="invite_remotecontrol" />
|
||||
<label for="invite_remotecontrol">
|
||||
<span data-translate="allow-remote-control" title="Hold CTRL and the mouse wheel to zoom in and out remotely of compatible video streams">Remote Control Camera Zoom (android)</span>
|
||||
<span data-translate="allow-remote-control" title="Hold CTRL and the mouse wheel to zoom in and out remotely of compatible video streams">Remote control of zoom (android)</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="invite_setting_item">
|
||||
<input type="checkbox" id="invite_obfuscate" />
|
||||
<label for="invite_obfuscate">
|
||||
<span data-translate="obfuscate_url" title="Encode the URL so that it's harder for a guest to modify the settings.">Obfuscate the Invite URL</span>
|
||||
<span data-translate="obfuscate_url" title="Encode the URL so that it's harder for a guest to modify the settings.">Obfuscate the invite URL</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="invite_setting_item">
|
||||
@ -687,15 +683,11 @@
|
||||
<input type="text" autocorrect="off" id="iframeURL" autocapitalize="none" style="margin:10px; border:2px solid; padding:10px; width:400px;" title="Enter an HTTPS URL" multiple/><br />
|
||||
<button onclick="previewIframe(getById('iframeURL').value);" >Preview</button>
|
||||
<button onclick="this.innerHTML = 'Update'; session.publishIFrame(getById('iframeURL').value);" >Share</button><br />
|
||||
<div class="message-card info">
|
||||
<h1>Usage information</h1>
|
||||
<p></p>
|
||||
<ul style="text-align: left;">
|
||||
<small class="iframeblob">
|
||||
<li>Not all websites will work with this feature as some sites disallow embedding.</li>
|
||||
<li>The site will try to auto-optimize standard Youtube or Twitch links.</li>
|
||||
<li>Remote websites must be CORS/IFrame compatible with full SSL-encryption enabled.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</small>
|
||||
<div id="iFramePreview" style=" width: 1280px; height: 720px; margin: auto; padding: 10px;"></div>
|
||||
</div>
|
||||
<div class="outer close">
|
||||
@ -753,7 +745,7 @@
|
||||
👋 👀 Welcome to VDO Ninja! We've rebranded! 📼 Nothing else is changing and we're staying 100% free.
|
||||
</h4>
|
||||
<br />
|
||||
🎁 Site Updated September 1st 🎈🎈 The <a href="https://docs.vdo.ninja/release-notes/v19">v19.0 release notes are here</a>. If new issues occur, the previous version can be <a href="https://vdo.ninja/v183/">found here</a>.
|
||||
🎁 Site updated September 7th. The <a href="https://docs.vdo.ninja/release-notes/v19">v19.0 release notes are here</a>. If new issues occur, the previous version can be <a href="https://vdo.ninja/v183/">found here</a>.
|
||||
|
||||
<br />
|
||||
<br />
|
||||
@ -769,14 +761,7 @@
|
||||
<input type="submit" />
|
||||
</form>
|
||||
<div id="credits" class="credits">
|
||||
Icons made by
|
||||
<a href="https://www.flaticon.com/authors/lucy-g" >Lucy G</a> from
|
||||
<a href="https://www.flaticon.com/" >www.flaticon.com</a> is licensed by
|
||||
|
||||
<a href="https://creativecommons.org/licenses/by/3.0/" title="Creative Commons BY 3.0" target="_blank">CC 3.0 BY</a> and by
|
||||
|
||||
<a href="https://www.flaticon.com/authors/gregor-cresnar">Gregor Cresnar</a> from
|
||||
<a href="https://www.flaticon.com/" >www.flaticon.com</a>
|
||||
<a href='https://github.com/steveseguin/vdoninja'>VDO.Ninja, by Steve Seguin</a>
|
||||
</div>
|
||||
</div>
|
||||
<span id="electronDragZone" style="pointer-events: none; z-index:-10; position:absolute;top:0;left:0;width:100%;height:5%;-webkit-app-region: drag;min-height:33px;"></span>
|
||||
@ -1466,14 +1451,14 @@
|
||||
|
||||
<br />
|
||||
|
||||
<div class="form-group multiselect" alt="tip: Hold CTRL (command) to select Multiple" title="tip: Hold CTRL (command) to select Multiple" style="padding: 10px; background-color:#f3f3f3;">
|
||||
<div class="form-group multiselect" alt="tip: Hold CTRL (command) to select Multiple" title="tip: Hold CTRL (command) to select Multiple" >
|
||||
<a id="multiselect-trigger3" class="form-control multiselect-trigger" >
|
||||
<div id="audioTitle2" class="title">
|
||||
<i class="las la-microphone-alt"></i><span data-translate="select-audio-source"> Audio Source(s) </span>
|
||||
<i id="chevarrow2" class="chevron bottom" aria-hidden="true"></i>
|
||||
</div>
|
||||
</a>
|
||||
<ul id="audioSource3" style="background-color:white;" class="multiselect-contents">
|
||||
<ul id="audioSource3" class="multiselect-contents">
|
||||
<li>
|
||||
</li>
|
||||
</ul>
|
||||
@ -1496,6 +1481,9 @@
|
||||
<option value="3" data-translate="blurred-background">Blurred background</option>
|
||||
<option value="4" data-translate="digital-greenscreen">Digital greenscreen</option>
|
||||
<option value="5" data-translate="virtual-background">Virtual background</option>
|
||||
<option class="advanced" value="6" data-translate="face-mesh">Face mesh (slow load)</option>
|
||||
<option class="advanced" value="anon" data-translate="anonymous-mask">Anonymous mask</option>
|
||||
<option class="advanced" value="dog" data-translate="dog-face">Dog ears and nose</option>
|
||||
</select>
|
||||
<span data-warnSimdNotice="true" style='display:none; font-size: 140%; margin-left:10px; vertical-align: middle; cursor:pointer' title="Improve performance and quality with this tip" onclick="warnUser(`For improved performance, use Chrome v87 or newer with SIMD support enabled.<br />Enable SIMD here: <a href='chrome://flags/#enable-webassembly-simd' onclick='copyFunction(this,event)' target='_blank'>chrome://flags/#enable-webassembly-simd</a>`);">
|
||||
<i class="las la-info-circle"></i>
|
||||
@ -1547,6 +1535,12 @@
|
||||
<span data-translate="copy-to-clipboard" >Copy to clipboard</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="context-menu__item">
|
||||
<a href="#" class="context-menu__link" data-action="Edit">
|
||||
<i class="las la-pen"></i>
|
||||
<span data-translate="edit-url" >Edit URL manually</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<nav id="context-menu-video" class="context-menu">
|
||||
@ -1715,12 +1709,13 @@
|
||||
<li><a onclick="changeLg('nl');toggle(document.getElementById('languages'));" style="cursor: pointer;" data-tz="Europe/Amsterdam">Dutch</a></li>
|
||||
<li><a onclick="changeLg('tr');toggle(document.getElementById('languages'));" style="cursor: pointer;" data-tz="Europe/Istanbul">Turkish</a></li>
|
||||
<li><a onclick="changeLg('ja');toggle(document.getElementById('languages'));" style="cursor: pointer;" data-tz="Asia/Tokyo">Japanese</a></li>
|
||||
<li><a onclick="changeLg('cn');toggle(document.getElementById('languages'));" style="cursor: pointer;" data-tz="Asia/China">Chinese (中文)</a></li>
|
||||
<li><a onclick="changeLg('cs');toggle(document.getElementById('languages'));" style="cursor: pointer;" data-tz="Europe/Prague">Czech</a></li>
|
||||
<li><a onclick="changeLg('uk');toggle(document.getElementById('languages'));" style="cursor: pointer;" data-tz="Europe/Ukraine">Ukrainian</a></li>
|
||||
<li><a onclick="changeLg('pig');toggle(document.getElementById('languages'));" style="cursor: pointer;">Pig Latin</a></li>
|
||||
</ul>
|
||||
<br />
|
||||
<a href="https://github.com/steveseguin/vdoninja/tree/master/translations" target="_blank" rel="noopener noreferrer" data-translate='add-more-here'>Add More Here!</a>
|
||||
<a href="https://github.com/steveseguin/vdoninja/tree/master/translations" style='color:#333;font-style: italic;' target="_blank" rel="noopener noreferrer" data-translate='add-more-here'>Add More Here!</a>
|
||||
<br />
|
||||
</div>
|
||||
<div id="calendar" class="popup-message" style="display: none; right: 0; padding-left:5px; bottom: 25px; position: absolute;">
|
||||
@ -1749,7 +1744,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 = "19.0";
|
||||
session.version = "19.1";
|
||||
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
|
||||
@ -1826,11 +1821,11 @@
|
||||
// session.title // "zzzz"
|
||||
</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=59"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="lib-js" src="./lib.js?ver=66"></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=249"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="main-js" src="./main.js?ver=251"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
400
main.css
400
main.css
@ -12,6 +12,7 @@
|
||||
--fadein-speed: 0;
|
||||
--video-margin: 0px;
|
||||
--video-rounded: 0px;
|
||||
--color-mode: light;
|
||||
}
|
||||
|
||||
* {
|
||||
@ -36,7 +37,11 @@ table {
|
||||
font-size:80%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
#audioSource3{
|
||||
background-color: #FFF;
|
||||
}
|
||||
|
||||
#bigPlayButton {
|
||||
margin:0 auto;
|
||||
background-color: #0000;
|
||||
@ -314,6 +319,7 @@ button.white:active {
|
||||
right: 0;
|
||||
z-index: -1;
|
||||
font-size: 80%;
|
||||
margin-right:100px;
|
||||
}
|
||||
|
||||
.credits>a {
|
||||
@ -1424,27 +1430,27 @@ img {
|
||||
background-repeat: no-repeat;
|
||||
background-size: 80px;
|
||||
background-position: 50% 65%;
|
||||
background-image: url(data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAxMjkgMTI5IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMjkgMTI5IiB3aWR0aD0iNTEycHgiIGhlaWdodD0iNTEycHgiPgogIDxnPgogICAgPGc+CiAgICAgIDxwYXRoIGQ9Im0xMC41LDU4LjloNDQuM2MyLjMsMCA0LjEtMS44IDQuMS00LjF2LTQ0LjNjMC0yLjMtMS44LTQuMS00LjEtNC4xaC00NC4zYy0yLjMsMC00LjEsMS44LTQuMSw0LjF2NDQuM2MwLDIuMiAxLjksNC4xIDQuMSw0LjF6bTQuMS00NC4zaDM2LjF2MzYuMWgtMzYuMXYtMzYuMXoiIGZpbGw9IiMwMDAwMDAiLz4KICAgICAgPHBhdGggZD0ibTEyMi42LDEwLjVjMC0yLjMtMS44LTQuMS00LjEtNC4xaC00NC4zYy0yLjMsMC00LjEsMS44LTQuMSw0LjF2NDQuM2MwLDIuMyAxLjgsNC4xIDQuMSw0LjFoNDQuM2MyLjMsMCA0LjEtMS44IDQuMS00LjF2LTQ0LjN6bS04LjIsNDAuMmgtMzYuMXYtMzYuMWgzNi4xdjM2LjF6IiBmaWxsPSIjMDAwMDAwIi8+CiAgICAgIDxwYXRoIGQ9Im0xMC41LDEyMi42aDQ0LjNjMi4zLDAgNC4xLTEuOCA0LjEtNC4xdi00NC4zYzAtMi4zLTEuOC00LjEtNC4xLTQuMWgtNDQuM2MtMi4zLDAtNC4xLDEuOC00LjEsNC4xdjQ0LjNjMCwyLjIgMS45LDQuMSA0LjEsNC4xem00LjEtNDQuM2gzNi4xdjM2LjFoLTM2LjF2LTM2LjF6IiBmaWxsPSIjMDAwMDAwIi8+CiAgICAgIDxwYXRoIGQ9Im0xMTguNSw3MC4xaC00NC4zYy0yLjMsMC00LjEsMS44LTQuMSw0LjF2NDQuM2MwLDIuMyAxLjgsNC4xIDQuMSw0LjFoNDQuM2MyLjMsMCA0LjEtMS44IDQuMS00LjF2LTQ0LjNjMC0yLjItMS45LTQuMS00LjEtNC4xem0tNC4xLDQ0LjNoLTM2LjF2LTM2LjFoMzYuMXYzNi4xeiIgZmlsbD0iIzAwMDAwMCIvPgogICAgPC9nPgogIDwvZz4KPC9zdmc+Cg==)
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='342.728' height='325.878' viewBox='0 0 90.68 86.222' fill='none' stroke='%23000' stroke-width='5.6' stroke-linejoin='round' stroke-dashoffset='22.7149601' xmlns:v='https://vecta.io/nano'%3E%3Cpath d='M3.15 3.15h37.378v35.24H3.15zm47.002 0H87.53v35.24H50.152zM3.15 47.832h37.378v35.24H3.15zm47.002 0H87.53v35.24H50.152z'/%3E%3C/svg%3E");
|
||||
}
|
||||
#container-2 {
|
||||
background-repeat: no-repeat;
|
||||
background-size: 80px;
|
||||
background-position: 50% 65%;
|
||||
background-image: url(data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAxMjkgMTI5IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMjkgMTI5IiB3aWR0aD0iNTEycHgiIGhlaWdodD0iNTEycHgiPgogIDxnPgogICAgPHBhdGggZD0ibTExOC41LDEwLjVoLTEwOGMtMi4zLDAtNC4xLDEuOC00LjEsNC4xdjUxLjcgMjEuMWMwLDIuMyAxLjgsNC4xIDQuMSw0LjFoNDkuOXYxOC44aC0yMi45Yy0yLjMsMC00LjEsMS44LTQuMSw0LjFzMS44LDQuMSA0LjEsNC4xaDU0YzIuMywwIDQuMS0xLjggNC4xLTQuMXMtMS44LTQuMS00LjEtNC4xaC0yMi45di0xOC44aDQ5LjljMi4zLDAgNC4xLTEuOCA0LjEtNC4xdi0yMS4xLTUxLjdjMC0yLjMtMS44LTQuMS00LjEtNC4xem0tNC4xLDcyLjhoLTk5Ljh2LTEzaDk5Ljh2MTN6bTAtMjEuMWgtOTkuOHYtNDMuNWg5OS44djQzLjV6IiBmaWxsPSIjMDAwMDAwIi8+CiAgPC9nPgo8L3N2Zz4K)
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='347.569' height='278.797' viewBox='0 0 91.961 73.765' fill='none' stroke='%23000' xmlns:v='https://vecta.io/nano'%3E%3Cpath d='M3.02 3.02h85.921v54.399H3.02z' stroke-width='6.04' stroke-linejoin='round' stroke-dashoffset='22.7149601'/%3E%3Cg stroke-width='6.3'%3E%3Cpath d='M35.607 70.527l21.839.071' stroke-linecap='round' paint-order='markers fill stroke'/%3E%3Cpath d='M46.404 73.517l.142-15.596' paint-order='markers fill stroke'/%3E%3C/g%3E%3C/svg%3E");
|
||||
}
|
||||
#container-3 {
|
||||
background-repeat: no-repeat;
|
||||
background-size: 80px;
|
||||
background-size: 90px;
|
||||
transition: background-image 0.3s ease-in-out;
|
||||
-webkit-transition: background-image 0.3s ease-in-out;
|
||||
background-position: 50% 65%;
|
||||
background-image: url(data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAxMjkgMTI5IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMjkgMTI5IiB3aWR0aD0iNTEycHgiIGhlaWdodD0iNTEycHgiPgogIDxnPgogICAgPHBhdGggZD0ibTk2LjYsMjYuOGgtODYuMWMtMi4yLDAtNC4xLDEuOC00LjEsNC4xdjY3LjJjMCwyLjIgMS44LDQuMSA0LjEsNC4xaDg2LjFjMi4yLDAgNC4xLTEuOCA0LjEtNC4xdi0xOS40bDE0LjksMTQuOWMwLjgsMC44IDEuOCwxLjIgMi45LDEuMiAwLjUsMCAxLjEtMC4xIDEuNi0wLjMgMS41LTAuNiAyLjUtMi4xIDIuNS0zLjh2LTUyLjVjMC0xLjYtMS0zLjEtMi41LTMuOC0xLjUtMC42LTMuMy0wLjMtNC40LDAuOWwtMTQuOSwxNC45di0xOS4zYy0wLjEtMi4zLTEuOS00LjEtNC4yLTQuMXptLTQuMSwzMy4zdjguOCAyNS4yaC03OHYtNTkuMmg3OHYyNS4yem0yMS45LTEydjMyLjlsLTEzLjctMTMuN3YtNS40bDEzLjctMTMuOHoiIGZpbGw9IiMwMDAwMDAiLz4KICA8L2c+Cjwvc3ZnPgo=)
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='347.184' height='187.007' viewBox='0 0 91.859 49.479' fill='none' stroke='%23000' stroke-width='5' stroke-linejoin='round' xmlns:v='https://vecta.io/nano'%3E%3Cpath d='M3.15 3.15h65.569v43.179H3.15z' stroke-dashoffset='22.7149601' paint-order='markers fill stroke'/%3E%3Cpath d='M68.919 28.837L88.709 44.73V7.148L69.019 22.341z'/%3E%3C/svg%3E");
|
||||
}
|
||||
#container-4 {
|
||||
background-repeat: no-repeat;
|
||||
background-size: 80px;
|
||||
background-position: 50% 65%;
|
||||
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJDYXBhXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgNDkwLjI4MiA0OTAuMjgyIiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA0OTAuMjgyIDQ5MC4yODI7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxnPg0KCTxwYXRoIGQ9Ik0wLjA0MywyNDUuMTk3YzAuNiwxMC4xLDcuMywxOC42LDE3LDIxLjVsMTc5LjYsNTQuM2w2LjYsMTIzLjhjMC4zLDQuOSwzLjYsOS4yLDguMywxMC44YzEuMywwLjUsMi43LDAuNyw0LDAuNw0KCQljMy41LDAsNi44LTEuNCw5LjItNC4xbDYzLjUtNzAuM2w5MCw2Mi4zYzQsMi44LDguNyw0LjMsMTMuNiw0LjNjMTEuMywwLDIxLjEtOCwyMy41LTE5LjJsNzQuNy0zODAuN2MwLjktNC40LTAuOC05LTQuMi0xMS44DQoJCWMtMy41LTIuOS04LjItMy42LTEyLjQtMS45bC00NTksMTg2LjhDNS4xNDMsMjI1Ljg5Ny0wLjU1NywyMzUuMDk3LDAuMDQzLDI0NS4xOTd6IE0yMjYuMDQzLDQxNC4wOTdsLTQuMS03OC4xbDQ2LDMxLjgNCgkJTDIyNi4wNDMsNDE0LjA5N3ogTTM5MS40NDMsNDIzLjU5N2wtMTYzLjgtMTEzLjRsMjI5LjctMjIyLjJMMzkxLjQ0Myw0MjMuNTk3eiBNNDMyLjE0Myw3OC4xOTdsLTIyNy4xLDIxOS43bC0xNzkuNC01NC4yDQoJCUw0MzIuMTQzLDc4LjE5N3oiLz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjwvc3ZnPg0K)
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='303.594' height='274.946' viewBox='0 0 80.326 72.746' fill='none' stroke='%23000' stroke-width='4.6' stroke-linejoin='round' stroke-dashoffset='6.01000023' xmlns:v='https://vecta.io/nano'%3E%3Cpath d='M2 51.27L78.326 2l-8.03 63.359-37.093-12.414z'/%3E%3Cpath d='M33.047 70.746l.157-17.802L78.326 2 33.203 52.944l10.314 3.39z'/%3E%3C/svg%3E");
|
||||
}
|
||||
#container-5 {
|
||||
background-repeat: no-repeat;
|
||||
@ -1926,15 +1932,10 @@ audio.fileshare::-webkit-media-controls-play-button, video.fileshare::-webkit-me
|
||||
vertical-align: middle;
|
||||
}
|
||||
#headphonesDiv {
|
||||
text-align: left;
|
||||
margin: 17px 0;
|
||||
width: 450px;
|
||||
background-color: #f3f3f3;
|
||||
padding: 10px 10px;
|
||||
border: 1px solid #ccc;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#effectSelector3{
|
||||
background-color: #FFF;
|
||||
display: inline-block;
|
||||
@ -1944,7 +1945,19 @@ audio.fileshare::-webkit-media-controls-play-button, video.fileshare::-webkit-me
|
||||
max-width: 100%;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
#effectsDiv {
|
||||
user-select: none;
|
||||
font-size:100%;
|
||||
text-align:left;
|
||||
margin: 17px auto;
|
||||
max-width:450px;
|
||||
min-width: 420px;
|
||||
background-color: #f3f3f3;
|
||||
display: none;
|
||||
padding: 10px 10px;
|
||||
border: 1px solid #ccc;
|
||||
vertical-align: middle;
|
||||
}
|
||||
#effectsDiv3 {
|
||||
text-align: left;
|
||||
width: 450px;
|
||||
@ -2027,7 +2040,6 @@ audio.fileshare::-webkit-media-controls-play-button, video.fileshare::-webkit-me
|
||||
font-size: 90%;
|
||||
}
|
||||
#videoSource3 {
|
||||
background-color: #FFF;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
padding: 3px;
|
||||
@ -2035,7 +2047,6 @@ audio.fileshare::-webkit-media-controls-play-button, video.fileshare::-webkit-me
|
||||
max-width: 370px;
|
||||
}
|
||||
#outputSource {
|
||||
background-color: #FFF;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
padding: 4px;
|
||||
@ -2043,13 +2054,28 @@ audio.fileshare::-webkit-media-controls-play-button, video.fileshare::-webkit-me
|
||||
max-width: 100%;
|
||||
}
|
||||
#outputSource3 {
|
||||
background-color: #FFF;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
padding: 3px;
|
||||
font-size: 93%;
|
||||
max-width: 100%;
|
||||
}
|
||||
#addPasswordBasic {
|
||||
width: 450px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
border-bottom: 0;
|
||||
display: block;
|
||||
text-align: left;
|
||||
margin: 17px auto 0 auto;
|
||||
max-width: 450px;
|
||||
min-width: 420px;
|
||||
background-color: #f3f3f3;
|
||||
padding: 10px 10px;
|
||||
border: 1px solid #ccc;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.videoMenu {
|
||||
background-color: #f3f3f3;
|
||||
width: 450px;
|
||||
@ -2060,6 +2086,18 @@ audio.fileshare::-webkit-media-controls-play-button, video.fileshare::-webkit-me
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.audioMenu{
|
||||
text-align: left;
|
||||
margin: 17px 0px 0px;
|
||||
max-width: 550px;
|
||||
min-width: 420px;
|
||||
background-color: rgb(243, 243, 243);
|
||||
display: inline-block;
|
||||
padding: 10px;
|
||||
border: 1px solid rgb(204, 204, 204);
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div.multiselect {
|
||||
width: 450px;
|
||||
white-space: nowrap;
|
||||
@ -2071,6 +2109,10 @@ div.multiselect {
|
||||
padding: 4px 10px 10px 10px;
|
||||
background-color: #f3f3f3;
|
||||
}
|
||||
.form-group .multiselect {
|
||||
padding: 10px;
|
||||
background-color:#f3f3f3;
|
||||
}
|
||||
.multiselect .multiselect-contents {
|
||||
display: block;
|
||||
margin: 0;
|
||||
@ -3132,4 +3174,330 @@ input:checked + .slider:before {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@font-face {
|
||||
font-family: 'Line Awesome Free';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
font-display: auto;
|
||||
src: url("./lineawesome/fonts/la-solid-900.eot");
|
||||
src: url("./lineawesome/fonts/la-solid-900.eot?#iefix") format("embedded-opentype"), url("./lineawesome/fonts/la-solid-900.woff2") format("woff2"), url("./lineawesome/fonts/la-solid-900.woff") format("woff"), url("./lineawesome/fonts/la-solid-900.ttf") format("truetype"), url("./lineawesome/fonts/la-solid-900.svg#lineawesome") format("svg"); }
|
||||
.las {
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
display: inline-block;
|
||||
font-style: normal;
|
||||
font-variant: normal;
|
||||
text-rendering: auto;
|
||||
line-height: 1; }
|
||||
.las {
|
||||
font-family: 'Line Awesome Free';
|
||||
font-weight: 900; }
|
||||
.la-bell:before {
|
||||
content: "\f0f3"; }
|
||||
.la-bell-slash:before {
|
||||
content: "\f1f6"; }
|
||||
.la-long-arrow-alt-right:before {
|
||||
content: "\f30b"; }
|
||||
.la-paperclip:before {
|
||||
content: "\f0c6"; }
|
||||
.la-window-close:before {
|
||||
content: "\f410"; }
|
||||
.la-stream:before {
|
||||
content: "\f550"; }
|
||||
.la-file-upload:before {
|
||||
content: "\f574"; }
|
||||
.la-comment-alt:before {
|
||||
content: "\f27a"; }
|
||||
.la-tv:before {
|
||||
content: "\f26c"; }
|
||||
.la-volume-up:before {
|
||||
content: "\f028"; }
|
||||
.la-comment-dots:before {
|
||||
content: "\f4ad"; }
|
||||
.la-microphone:before {
|
||||
content: "\f130"; }
|
||||
.la-microphone-alt:before {
|
||||
content: "\f3c9"; }
|
||||
.la-video:before {
|
||||
content: "\f03d"; }
|
||||
.la-desktop:before {
|
||||
content: "\f108"; }
|
||||
.la-tv:before {
|
||||
content: "\f26c"; }
|
||||
.la-window-maximize:before {
|
||||
content: "\f2d0"; }
|
||||
.la-sync-alt:before {
|
||||
content: "\f2f1"; }
|
||||
.la-users-cog:before {
|
||||
content: "\f509"; }
|
||||
.la-cog:before {
|
||||
content: "\f013"; }
|
||||
.la-phone:before {
|
||||
content: "\f095"; }
|
||||
.la-skull-crossbones:before {
|
||||
content: "\f714"; }
|
||||
.la-hand-paper:before {
|
||||
content: "\f256"; }
|
||||
.la-dot-circle:before {
|
||||
content: "\f192"; }
|
||||
.la-bug:before {
|
||||
content: "\f188"; }
|
||||
.la-question-circle:before {
|
||||
content: "\f059"; }
|
||||
.la-language:before {
|
||||
content: "\f1ab"; }
|
||||
.la.la-calendar:before {
|
||||
content: "\f073"; }
|
||||
.la-exclamation-circle:before {
|
||||
content: "\f06a"; }
|
||||
.la-plug:before {
|
||||
content: "\f1e6"; }
|
||||
.la-ethernet:before {
|
||||
content: "\f796"; }
|
||||
.la-headphones:before {
|
||||
content: "\f025"; }
|
||||
.la-robot:before {
|
||||
content: "\f544"; }
|
||||
.la-info-circle:before {
|
||||
content: "\f05a"; }
|
||||
.la.la-hdd-o:before {
|
||||
content: "\f0a0"; }
|
||||
.la-key:before {
|
||||
content: "\f084"; }
|
||||
.la-broadcast-tower:before {
|
||||
content: "\f519"; }
|
||||
.la-clock:before {
|
||||
content: "\f017"; }
|
||||
.la-tachometer-alt:before {
|
||||
content: "\f3fd"; }
|
||||
.la-book-open:before {
|
||||
content: "\f518"; }
|
||||
.la-caret-down:before {
|
||||
content: "\f0d7"; }
|
||||
.la-caret-right:before {
|
||||
content: "\f0da"; }
|
||||
.la-copy:before {
|
||||
content: "\f0c5"; }
|
||||
.la-tools:before {
|
||||
content: "\f7d9"; }
|
||||
.la-th-large:before {
|
||||
content: "\f009"; }
|
||||
.la-user-circle:before {
|
||||
content: "\f2bd"; }
|
||||
.la-paper-plane:before {
|
||||
content: "\f1d8"; }
|
||||
.la-envelope:before {
|
||||
content: "\f0e0"; }
|
||||
.la-sign-out-alt:before {
|
||||
content: "\f2f5"; }
|
||||
.la-angle-right:before {
|
||||
content: "\f105"; }
|
||||
.la-angle-left:before {
|
||||
content: "\f104"; }
|
||||
.la-plus-square:before {
|
||||
content: "\f0fe"; }
|
||||
.la-microphone-slash:before {
|
||||
content: "\f131"; }
|
||||
.la-user:before {
|
||||
content: "\f007"; }
|
||||
.la-video-slash:before {
|
||||
content: "\f4e2"; }
|
||||
.la-volume-off:before {
|
||||
content: "\f026"; }
|
||||
.la-eye-slash:before {
|
||||
content: "\f070"; }
|
||||
.la-minus:before {
|
||||
content: "\f068"; }
|
||||
.la-plus:before {
|
||||
content: "\f067"; }
|
||||
.la-sync:before {
|
||||
content: "\f021"; }
|
||||
.la-circle:before {
|
||||
content: "\f111"; }
|
||||
.la-binoculars:before {
|
||||
content: "\f1e5"; }
|
||||
.la-stop-circle:before {
|
||||
content: "\f28d"; }
|
||||
.la-redo-alt:before {
|
||||
content: "\f2f9"; }
|
||||
.la-sliders-h:before {
|
||||
content: "\f1de"; }
|
||||
.la-compress-arrows-alt:before {
|
||||
content: "\f78c"; }
|
||||
.la-spinner:before {
|
||||
content: "\f110"; }
|
||||
.la.la-external-link:before {
|
||||
content: "\f35d"; }
|
||||
.la-pen:before {
|
||||
content: "\f304"; }
|
||||
.la-external-link-alt:before {
|
||||
content: "\f35d"; }
|
||||
.la-times:before {
|
||||
content: "\f00d"; }
|
||||
.la-volume-mute:before {
|
||||
content: "\f6a9"; }
|
||||
.la-plug:before {
|
||||
content: "\f1e6"; }
|
||||
.la-reply:before {
|
||||
content: "\f3e5"; }
|
||||
.la-headset:before {
|
||||
content: "\f590"; }
|
||||
.la-check:before {
|
||||
content: "\f00c"; }
|
||||
.la-exclamation:before {
|
||||
content: "\f12a"; }
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--color-mode: dark;
|
||||
--background-color: #02050c;
|
||||
}
|
||||
}
|
||||
|
||||
body.darktheme .container-inner{
|
||||
background-color: #40444E
|
||||
}
|
||||
body.darktheme .card{
|
||||
background-color: #40444E
|
||||
}
|
||||
body.darktheme input{
|
||||
background-color: #ccc;
|
||||
}
|
||||
body.darktheme .column>h2{
|
||||
color: #b6b6b6;
|
||||
}
|
||||
body.darktheme .multiselect .multiselect-contents {
|
||||
background-color:unset;
|
||||
}
|
||||
body.darktheme .directorsgrid .vidcon > .las {
|
||||
background-color: #646464;
|
||||
}
|
||||
body.darktheme .form-group .multiselect {
|
||||
background-color: #949494;
|
||||
padding: 10px; background-color:#f3f3f3;
|
||||
}
|
||||
body.darktheme h2 {
|
||||
color: #DDD;
|
||||
}
|
||||
body.darktheme button {
|
||||
filter: brightness(0.70);
|
||||
}
|
||||
body.darktheme .las {
|
||||
filter: brightness(0.85);
|
||||
}
|
||||
body.darktheme label {
|
||||
filter: brightness(0.85);
|
||||
}
|
||||
body.darktheme #roomHeader{
|
||||
filter: brightness(0.85);
|
||||
}
|
||||
body.darktheme div.multiselect {
|
||||
background-color: #949494;
|
||||
}
|
||||
body.darktheme .videoMenu {
|
||||
background-color: #949494;
|
||||
}
|
||||
body.darktheme .audioMenu{
|
||||
background-color: #949494;
|
||||
}
|
||||
body.darktheme #headphonesDiv{
|
||||
background-color: #949494;
|
||||
}
|
||||
body.darktheme #headphonesDiv3{
|
||||
background-color: #949494;
|
||||
}
|
||||
body.darktheme select{
|
||||
background-color: #949494;
|
||||
}
|
||||
body.darktheme .white {
|
||||
filter: brightness(0.85);
|
||||
}
|
||||
body.darktheme .directorsgrid .vidcon {
|
||||
background-color: #2b2b2bdd;
|
||||
color: #978c8c;
|
||||
}
|
||||
body.darktheme .promptModalInner{
|
||||
filter: brightness(0.65);
|
||||
}
|
||||
body.darktheme .infoblob{
|
||||
color: #CCC;
|
||||
}
|
||||
body.darktheme #addPasswordBasic{
|
||||
background-color: #949494;
|
||||
}
|
||||
body.darktheme #effectsDiv{
|
||||
background-color: #949494;
|
||||
}
|
||||
body.darktheme #effectsDiv3{
|
||||
background-color: #949494;
|
||||
}
|
||||
body.darktheme .outMessage{
|
||||
background-color: #7f89a7;
|
||||
}
|
||||
body.darktheme .inMessage {
|
||||
background-color: #b1b1b1;
|
||||
}
|
||||
body.darktheme #chatInput{
|
||||
background-color:#ccc;
|
||||
}
|
||||
body.darktheme .popup-message{
|
||||
background-color: #9b9b9b !important;
|
||||
}
|
||||
body.darktheme #audioScreenShare1{
|
||||
background-color: #949494;
|
||||
}
|
||||
body.darktheme #webcamstats2{
|
||||
background-color: #949494;
|
||||
}
|
||||
body.darktheme #audioSourceScreenshare{
|
||||
background-color: #AAA;
|
||||
}
|
||||
body.darktheme #headphonesDiv2{
|
||||
background-color: #949494;
|
||||
}
|
||||
body.darktheme #outputSourceScreenshare{
|
||||
background-color: #AAA;
|
||||
}
|
||||
body.darktheme #audioSource{
|
||||
background-color: #AAA;
|
||||
}
|
||||
body.darktheme #outputSource{
|
||||
background-color: #AAA;
|
||||
}
|
||||
body.darktheme #videoSourceSelect{
|
||||
background-color: #AAA;
|
||||
}
|
||||
body.darktheme #videoSettings{
|
||||
background-color: #949494;
|
||||
}
|
||||
body.darktheme #effectSelector{
|
||||
background-color: #AAA;
|
||||
}
|
||||
body.darktheme #effectSelector3{
|
||||
background-color: #AAA;
|
||||
}
|
||||
body.darktheme #audioSource3{
|
||||
background-color: #AAA;
|
||||
}
|
||||
body.darktheme #videoSource3{
|
||||
background-color: #AAA;
|
||||
}
|
||||
body.darktheme #outputSource3{
|
||||
background-color: #AAA;
|
||||
}
|
||||
body.darktheme #videoSettings3{
|
||||
background-color: #949494;
|
||||
}
|
||||
body.darktheme .promptModalInner{
|
||||
background-color: #ccc;
|
||||
}
|
||||
body.darktheme .alertModal{
|
||||
background-color: #ccc;
|
||||
filter:brightness(0.85);
|
||||
}
|
||||
body.darktheme .directorContainer{
|
||||
filter: brightness(0.85);
|
||||
}
|
||||
|
||||
49
main.js
49
main.js
@ -64,7 +64,9 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
} catch (e) {}
|
||||
}
|
||||
try {
|
||||
changeLg("blank");
|
||||
if (!ln_template){
|
||||
changeLg("blank");
|
||||
}
|
||||
//getById("mainmenu").style.opacity = 1;
|
||||
if (session.label === false) {
|
||||
document.title = location.hostname;
|
||||
@ -170,6 +172,10 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
if (urlParams.has('nospeakerbutton') || urlParams.has('nsb')) {
|
||||
getById("mutespeakerbutton").style.setProperty("display", "none", "important");
|
||||
}
|
||||
|
||||
if (urlParams.has('pusheffectsdata') ) {
|
||||
session.pushEffectsData=true;
|
||||
}
|
||||
|
||||
if (iOS || iPad) {
|
||||
session.mobile = true;
|
||||
@ -1125,7 +1131,35 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
} catch(e){errorlog("variable css failed");}
|
||||
|
||||
}
|
||||
|
||||
|
||||
var darkmode=false;
|
||||
try {
|
||||
if (urlParams.has("darkmode") || urlParams.has("nightmode")){
|
||||
darkmode = urlParams.get("darkmode") || urlParams.get("nightmode") || null;
|
||||
if ((darkmode===null) || (darkmode === "")){
|
||||
darkmode=true;
|
||||
} else if ((darkmode=="false") || (darkmode == "0") || (darkmode == 0) || (darkmode == "off")){
|
||||
darkmode=false;
|
||||
}
|
||||
} else if (urlParams.has("lightmode") || urlParams.has("lightmode")){
|
||||
darkmode = false;
|
||||
} else {
|
||||
darkmode = getComputedStyle(document.querySelector(':root')).getPropertyValue('--color-mode').trim();
|
||||
if (darkmode == "dark"){
|
||||
darkmode = true;
|
||||
} else {
|
||||
darkmode = false;
|
||||
}
|
||||
}
|
||||
if (darkmode){
|
||||
document.body.classList.add("darktheme");
|
||||
document.querySelector(':root').style.setProperty('--background-color',"#02050c" );
|
||||
} else {
|
||||
document.body.classList.remove("darktheme");
|
||||
document.querySelector(':root').style.setProperty('--background-color',"#141926" );
|
||||
}
|
||||
} catch(e){errorlog(e);}
|
||||
|
||||
if (urlParams.has("videodevice") || urlParams.has("vdevice") || urlParams.has('vd') || urlParams.has('device') || urlParams.has('d')) {
|
||||
|
||||
session.videoDevice = urlParams.get("videodevice") || urlParams.get("vdevice") || urlParams.get("vd") || urlParams.get("device") || urlParams.get("d");
|
||||
@ -2594,7 +2628,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
if ("keyframe" in e.data) {
|
||||
session.sendKeyFrameScenes();
|
||||
}
|
||||
|
||||
|
||||
if ("mute" in e.data) {
|
||||
if (e.data.mute === true) { // unmute
|
||||
session.speakerMuted = true; // set
|
||||
@ -2833,7 +2867,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.pushEffectsData = e.data.getEffectsData; // which effect do you want the data from? it won't enable the effect necessarily; just the ML pipeline
|
||||
|
||||
//parent.postMessage({
|
||||
// "effectsData": loudness,
|
||||
// "effectsData": effectsData,
|
||||
// "effectsID": session.pushEffectsData
|
||||
//}, "*");
|
||||
|
||||
@ -2876,7 +2910,6 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ("automixer" in e.data) {
|
||||
if (e.data.automixer == true) {
|
||||
session.manual = false;
|
||||
@ -2888,7 +2921,9 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
}
|
||||
|
||||
if ("target" in e.data) {
|
||||
if (("action" in e.data) && (e.data.action!="null")) { /////////////// reuse the Companion API
|
||||
processMessage(e.data); // reuse the companion API
|
||||
} else if ("target" in e.data) {
|
||||
log(e.data);
|
||||
for (var i in session.rpcs) {
|
||||
try {
|
||||
@ -2911,7 +2946,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.rpcs[i].videoElement.parentNode.parentNode.removeChild(session.rpcs[i].videoElement.parentNode);
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
errorlog(e);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user