mirror of
https://github.com/eliasstepanik/vdo.ninja.git
synced 2026-01-10 05:08:28 +00:00
v23.5 updates
This commit is contained in:
parent
49c7590123
commit
ed1716c23c
167
fileshare.html
Normal file
167
fileshare.html
Normal file
@ -0,0 +1,167 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>WebRTC File Sharing</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
/* Container Styles */
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
max-width: 600px;
|
||||
padding: 20px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0px 0px 5px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
/* Header Styles */
|
||||
h1 {
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
font-weight: normal;
|
||||
font-size: 36px;
|
||||
color: #333333;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* File Selector Styles */
|
||||
#file-selector {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
#file-selector label {
|
||||
font-size: 20px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#file-selector input[type="file"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#file-selector button {
|
||||
font-size: 16px;
|
||||
padding: 10px 20px;
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
#file-selector button:hover {
|
||||
background-color: #3e8e41;
|
||||
}
|
||||
|
||||
/* Progress Container Styles */
|
||||
#progress-container {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
#progress-bar {
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
background-color: #f1f1f1;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#progress-bar-inner {
|
||||
height: 100%;
|
||||
background-color: #4CAF50;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
color: white;
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
#status {
|
||||
font-size: 16px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#connections {
|
||||
font-size: 14px;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
/* Input Styles */
|
||||
input[type="file"] {
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #dddddd;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* Button Styles */
|
||||
button {
|
||||
font-size: 16px;
|
||||
padding: 10px 20px;
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #3e8e41;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>WebRTC File Sharing</h1>
|
||||
|
||||
<div id="file-selector">
|
||||
<label for="file-input">Select a file:</label>
|
||||
<input type="file" id="file-input" />
|
||||
<button id="share-button">Share</button>
|
||||
</div>
|
||||
|
||||
<div id="progress-container" style="display:none">
|
||||
<div id="progress-bar">
|
||||
<div id="progress-bar-inner"></div>
|
||||
</div>
|
||||
<div id="status">Connecting...</div>
|
||||
<div id="connections">0 connections</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var fileInput = document.getElementById("file-input");
|
||||
var shareButton = document.getElementById("share-button");
|
||||
var progressContainer = document.getElementById("progress-container");
|
||||
var progressBarInner = document.getElementById("progress-bar-inner");
|
||||
var status = document.getElementById("status");
|
||||
var connections = document.getElementById("connections");
|
||||
var connectionCount = 0;
|
||||
|
||||
shareButton.addEventListener("click", function() {
|
||||
if (fileInput.files.length > 0) {
|
||||
// Display progress bar and status message
|
||||
progressContainer.style.display = "block";
|
||||
status.innerText = "Connecting...";
|
||||
|
||||
// TODO: Use WebRTC to share the file with other users
|
||||
|
||||
// Update progress bar and status messages
|
||||
progressBarInner.style.width = "100%";
|
||||
status.innerText = "File shared successfully.";
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: Use WebRTC to display the number of connections, progress, and speed
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
117
main.css
117
main.css
@ -1165,9 +1165,7 @@ hr {
|
||||
margin: 0;
|
||||
}
|
||||
.queueNotification {
|
||||
position: relative;
|
||||
top: -40px;
|
||||
right: -33px;
|
||||
|
||||
padding: 2px 0;
|
||||
border-radius: 50%;
|
||||
background: #335c3a;
|
||||
@ -1284,6 +1282,22 @@ button#press2talk{
|
||||
position: relative;
|
||||
}
|
||||
|
||||
button.btnArmTransferRoom{
|
||||
width:auto;
|
||||
margin-left: 2px;
|
||||
height:38px;
|
||||
border-radius: 15px;
|
||||
}
|
||||
button.btnArmTransferRoom i{
|
||||
margin-right:3px;
|
||||
}
|
||||
button.btnArmTransferRoom:hover{
|
||||
background-color: var(--green-accent)!important;
|
||||
}
|
||||
|
||||
button.btnArmTransferRoom.selected{
|
||||
background-color: #840000!important;
|
||||
}
|
||||
|
||||
#container.vidcon {
|
||||
height:100%;
|
||||
@ -1354,22 +1368,6 @@ button#press2talk{
|
||||
100% { transform: translate(1px, -2px) rotate(-1deg); }
|
||||
}
|
||||
|
||||
button.btnArmTransferRoom{
|
||||
width:auto;
|
||||
margin-left: 2px;
|
||||
height:38px;
|
||||
border-radius: 15px;
|
||||
}
|
||||
button.btnArmTransferRoom i{
|
||||
margin-right:3px;
|
||||
}
|
||||
button.btnArmTransferRoom:hover{
|
||||
background-color: var(--green-accent);
|
||||
}
|
||||
|
||||
button.btnArmTransferRoom.selected{
|
||||
background-color: #840000;
|
||||
}
|
||||
|
||||
@media only screen and (max-height: 540px){
|
||||
#gridlayout>#container.vidcon {
|
||||
@ -1602,7 +1600,7 @@ body.darktheme{
|
||||
.gowebcam:enabled {
|
||||
background-color: #26e726 !important;
|
||||
background: radial-gradient(#26e726, #2EeF2E);
|
||||
color: black;
|
||||
color: black!important;
|
||||
font-weight: bold !important;
|
||||
box-shadow: 0 0 31px 0px #244e1c44;
|
||||
animation: pulsate 2s ease-out infinite;
|
||||
@ -1725,7 +1723,7 @@ input[type=range]::-webkit-slider-thumb {
|
||||
box-shadow: 1px 1px 1px #000,0 0 1px #0d0d0d;
|
||||
border: 1px solid #000;
|
||||
height: 24px;
|
||||
width: 14px;
|
||||
width: 24px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
-webkit-appearance: none;
|
||||
@ -1737,7 +1735,7 @@ input[type=range]::-moz-range-thumb {
|
||||
box-shadow: 1px 1px 1px #000,0 0 1px #0d0d0d;
|
||||
border: 1px solid #000;
|
||||
height: 24px;
|
||||
width: 14px;
|
||||
width: 24px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
background-color: var(--lighttheme-2);
|
||||
@ -1747,7 +1745,7 @@ input[type=range]::-ms-thumb {
|
||||
box-shadow: 1px 1px 1px #000,0 0 1px #0d0d0d;
|
||||
border: 1px solid #000;
|
||||
height: 24px;
|
||||
width: 14px;
|
||||
width: 24px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
background-color: var(--lighttheme-2);
|
||||
@ -1848,7 +1846,7 @@ div#chatBody a {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
max-width: min(500px, 100vh);
|
||||
max-width: min(500px, 100vw);
|
||||
z-index: 3;
|
||||
margin-bottom: 65px;
|
||||
gap: 0px 5px;
|
||||
@ -1857,11 +1855,11 @@ div#chatBody a {
|
||||
#chatInput {
|
||||
color: #000;
|
||||
background-color: #FFFE;
|
||||
width: 70%;
|
||||
width: calc(100% - 160px);
|
||||
padding: 3px;
|
||||
}
|
||||
.chatBarInputButton {
|
||||
width: calc(30% - 5px);
|
||||
width: 50px;
|
||||
margin: unset;
|
||||
}
|
||||
|
||||
@ -3426,10 +3424,12 @@ div#roomnotes2 {
|
||||
}
|
||||
.directorBlue{
|
||||
background-color: #5c7785 !important;
|
||||
display: var(--show-codirectors) !important;
|
||||
|
||||
}
|
||||
.directorBox{
|
||||
background-color: #606383 !important;
|
||||
display: var(--show-codirectors) !important;
|
||||
}
|
||||
/* ---- DIRECTORS PAGE - Guest Controls Box ---- */
|
||||
.controlsGrid {
|
||||
@ -3946,6 +3946,7 @@ a#reshare {
|
||||
border-radius: 2vh;
|
||||
pointer-events:none;
|
||||
border: 1px black solid;
|
||||
z-Index: 2;
|
||||
}
|
||||
|
||||
.video-meter-2 {
|
||||
@ -3962,6 +3963,7 @@ a#reshare {
|
||||
border-radius: 5px;
|
||||
pointer-events:none;
|
||||
border: 5px green solid;
|
||||
z-Index: 2;
|
||||
}
|
||||
|
||||
.video-meter-director {
|
||||
@ -3984,6 +3986,7 @@ a#reshare {
|
||||
pointer-events:none;
|
||||
border: 1px black solid;
|
||||
transition: height 0.1s ease, background-color 0.1s ease;
|
||||
z-Index: 2;
|
||||
}
|
||||
|
||||
|
||||
@ -4028,6 +4031,7 @@ a#reshare {
|
||||
border-radius: 2vh;
|
||||
background-color:#b11313;
|
||||
padding: 2px 2px 2px 1px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.video-mute-state-userlist {
|
||||
@ -4300,6 +4304,23 @@ input:checked + .slider:before {
|
||||
overflow: hidden;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
#publishSettings{
|
||||
position: absolute;
|
||||
background-color: #ddddddee;
|
||||
box-shadow: 0 0 30px 10px #0000005c;
|
||||
color: black;
|
||||
font-size: 1.0em;
|
||||
bottom: calc(50% - 130px);
|
||||
left: 50%;
|
||||
transform: translate(-50%, 0%);
|
||||
border-radius: 10px;
|
||||
font-weight: bold;
|
||||
z-index:31;
|
||||
width:550px;
|
||||
max-width:100%;
|
||||
overflow: hidden;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
.largeTextEntry {
|
||||
width: 90%;
|
||||
margin: 10px 5%;
|
||||
@ -4953,12 +4974,12 @@ button:hover {
|
||||
button i {
|
||||
font-size: 130%;
|
||||
}
|
||||
.darktheme button {
|
||||
.darktheme :not(.promptModalInner) > button {
|
||||
background-color: var(--discord-grey-5);
|
||||
border: 1px solid var(--discord-grey-8);
|
||||
color: var(--discord-text);
|
||||
}
|
||||
.darktheme button:hover {
|
||||
.darktheme :not(.promptModalInner) > button:hover {
|
||||
filter: brightness(1.05);
|
||||
}
|
||||
|
||||
@ -5080,13 +5101,13 @@ input[type='checkbox'], input[type='radio'] {
|
||||
}
|
||||
|
||||
|
||||
.darktheme input {
|
||||
.darktheme :not(.promptModalInner) > input {
|
||||
border: 1px solid var(--discord-grey-8);
|
||||
color: var(--near-black);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.darktheme input::placeholder {
|
||||
.darktheme :not(.promptModalInner) > input::placeholder {
|
||||
color: var(--discord-grey-8) !important;
|
||||
}
|
||||
|
||||
@ -5105,7 +5126,6 @@ input[type='checkbox'], input[type='radio'] {
|
||||
.container-inner {
|
||||
display: none;
|
||||
background-color: var(--lighttheme-3);
|
||||
max-height: 100%;
|
||||
min-height: calc(100% - 100px);
|
||||
margin-bottom:30px;
|
||||
}
|
||||
@ -5224,41 +5244,6 @@ input[type='checkbox'], input[type='radio'] {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* Buttons to disable due to them being a director */
|
||||
.directorBoxColor button[data-action-type="hangup"],
|
||||
.directorBoxColor button[data-action-type="toggle-remote-speaker"],
|
||||
.directorBoxColor button[data-action-type="toggle-remote-display"],
|
||||
.directorBoxColor button[data-action-type="mute-video-guest"],
|
||||
.directorBoxColor button[data-action-type="advanced-camera-settings"],
|
||||
.directorBoxColor button[data-action-type="advanced-audio-settings"],
|
||||
.directorBoxColor button[data-action-type="order-down"],
|
||||
.directorBoxColor button[data-action-type="order-up"],
|
||||
.directorBoxColor button[data-action-type="toggle-group"],
|
||||
.directorBoxColor button[data-action-type="mute-guest"],
|
||||
.directorBoxColor .tooltip {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.directorBoxColor {
|
||||
border: 2px solid var(--director-box);
|
||||
box-shadow: 0px 0px 15px var(--director-box);
|
||||
display: var(--show-codirectors) !important;
|
||||
}
|
||||
|
||||
.darktheme .codirectorBoxColor {
|
||||
border: 2px solid var(--codirector-dark-box);
|
||||
box-shadow: 0px 0px 15px var(--codirector-dark-box);
|
||||
display: var(--show-codirectors) !important;
|
||||
}
|
||||
|
||||
.codirectorBoxColor {
|
||||
border: 2px solid var(--codirector-box);
|
||||
box-shadow: 0px 0px 15px var(--codirector-box);
|
||||
display: var(--show-codirectors) !important;
|
||||
}
|
||||
|
||||
.darktheme .invite_setting_group {
|
||||
color: var(--discord-text);
|
||||
}
|
||||
|
||||
166
main.js
166
main.js
@ -293,17 +293,28 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
|
||||
if (urlParams.has('whippush') || urlParams.has('whipout') || urlParams.has('pushwhip')) { // URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
||||
let whippush = urlParams.get('whippush') || urlParams.get('whipout') || urlParams.get('pushwhip');
|
||||
if (whippush){
|
||||
session.whipOutput = urlParams.get('whippush') || urlParams.get('whipout') || urlParams.get('pushwhip') || null;
|
||||
if (session.whipOutput){
|
||||
try {
|
||||
session.whipOutput = decodeURIComponent(whippush);
|
||||
if (session.whipOutput == 'twitch'){
|
||||
session.whipOutput = "https://g.webrtc.live-video.net:4443/v2/offer";
|
||||
query("#publishOutToken input[type='password']").placeholder = "Twitch stream token here";
|
||||
} else {
|
||||
session.whipOutput = decodeURIComponent(session.whipOutput);
|
||||
}
|
||||
} catch(e){
|
||||
errorlog(e);
|
||||
}
|
||||
} else {
|
||||
getById("publishOutURL").classList.remove("hidden");
|
||||
}
|
||||
|
||||
}
|
||||
if (urlParams.has('whippushtoken') || urlParams.has('whipouttoken') || urlParams.has('pushwhiptoken')) {// URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
||||
session.whipOutputToken = urlParams.get('whippushtoken') || urlParams.get('whipouttoken') || urlParams.get('pushwhiptoken') || false;
|
||||
if (!session.whipOutputToken){
|
||||
getById("publishOutToken").classList.remove("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
if (urlParams.has('whepplay')) { // URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
||||
@ -328,6 +339,17 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (urlParams.has('whepplaytoken')) { // URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
||||
if (urlParams.get('whepplaytoken')){
|
||||
try {
|
||||
session.whepInputToken = urlParams.get('whepplaytoken')
|
||||
} catch(e){
|
||||
errorlog(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (urlParams.has('nomouseevents') || urlParams.has('nme')) {
|
||||
session.disableMouseEvents = true;
|
||||
}
|
||||
@ -415,6 +437,25 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
|
||||
|
||||
if (urlParams.has('broadcasttransfer') || urlParams.has('bct')) {
|
||||
log("Broadcast transfer flag set");
|
||||
session.broadcastTransfer = urlParams.get('broadcasttransfer') || urlParams.get('bct') || null;
|
||||
if (session.broadcastTransfer === "false") {
|
||||
session.broadcastTransfer = false;
|
||||
} else if (session.broadcastTransfer=== "0") {
|
||||
session.broadcastTransfer = false;
|
||||
} else if (session.broadcastTransfer === "no") {
|
||||
session.broadcastTransfer = false;
|
||||
} else if (session.broadcastTransfer === "off") {
|
||||
session.broadcastTransfer = false;
|
||||
} else {
|
||||
session.broadcastTransfer = true;
|
||||
}
|
||||
if (transferSettings){
|
||||
transferSettings.broadcast = session.broadcastTransfer;
|
||||
}
|
||||
}
|
||||
|
||||
if (urlParams.has('broadcast') || urlParams.has('bc')) {
|
||||
log("Broadcast flag set");
|
||||
session.broadcast = urlParams.get('broadcast') || urlParams.get('bc') || null;
|
||||
@ -567,6 +608,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
|
||||
if (urlParams.has('showdirector') || urlParams.has('sd')) {
|
||||
session.showDirector = parseInt(urlParams.get('showdirector')) || parseInt(urlParams.get('sd')) || true; // if 2, video only allowed. True or 1 will be video + audio allowed.
|
||||
// fyi, true is the same as 1 when == is used, so assert(1==true) is true.
|
||||
}
|
||||
|
||||
if (urlParams.has('bitratecutoff') || urlParams.has('bitcut')) {
|
||||
@ -623,6 +665,11 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
document.addEventListener('fullscreenchange', event => {
|
||||
log("full screen change event");
|
||||
log(event);
|
||||
|
||||
if (document.getElementById("previewWebcam")){
|
||||
return;
|
||||
}
|
||||
|
||||
if (session.orientation && session.mobile){
|
||||
if (document.fullscreenElement) {
|
||||
document.exitFullscreen();
|
||||
@ -751,6 +798,8 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
getById("container-5").classList.add("skip-animation");
|
||||
getById("container-5").classList.remove('pointer');
|
||||
|
||||
getById("sharefilebutton").style.display = "flex";
|
||||
|
||||
if (SafariVersion){
|
||||
getById("safari_warning_fileshare").classList.remove('hidden');
|
||||
} else if (!Firefox){
|
||||
@ -812,6 +861,10 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.displaySurface = urlParams.get('displaysurface') || "monitor";
|
||||
}
|
||||
|
||||
if (urlParams.has('locksize')){ // browser, window, or monitor (which is default selected)
|
||||
session.lockWindowSize = urlParams.get('locksize') || true;
|
||||
}
|
||||
|
||||
if (urlParams.has('intro') || urlParams.has('ib')) {
|
||||
session.introButton = true;
|
||||
}
|
||||
@ -1118,12 +1171,24 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
getById("mutetoggle").style.top = "unset";
|
||||
|
||||
}
|
||||
|
||||
if (urlParams.has('nosettings')){
|
||||
session.nosettings = true;
|
||||
getById("settingsbutton").classList.add("hidden");
|
||||
}
|
||||
|
||||
if (urlParams.has('publish')){
|
||||
session.publish = true;
|
||||
getById("publishSettings").style.display = "block";
|
||||
}
|
||||
|
||||
if (urlParams.has('nopush') || urlParams.has('noseed') || urlParams.has('viewonly') || urlParams.has('viewmode')) { // this is like a scene; Seeding is disabled. Can be used with &showall to show all videos on load
|
||||
session.doNotSeed=true;
|
||||
session.scene = null; // not a scene, but sorta. false vs null makes a difference here.
|
||||
session.videoDevice = 0;
|
||||
session.audioDevice = 0;
|
||||
|
||||
if (session.scene===false){
|
||||
session.scene = null; // not a scene, but sorta. false vs null makes a difference here.
|
||||
}
|
||||
|
||||
session.dataMode = true; // thios will let us connect
|
||||
// session.showall = true; // this can be used to SHOW the videos. (&showall)
|
||||
}
|
||||
@ -1167,8 +1232,12 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
|
||||
if (session.dataMode){
|
||||
session.videoDevice = 0;
|
||||
session.audioDevice = 0;
|
||||
|
||||
if (!(session.meshcast || (session.whipOutput!==false) || session.screenshare)){
|
||||
session.videoDevice = 0;
|
||||
session.audioDevice = 0;
|
||||
}
|
||||
|
||||
getById("mainmenu").classList.add("hidden");
|
||||
//session.autohide = true;
|
||||
//session.autostart = true;
|
||||
@ -2255,6 +2324,15 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}, session.forceRetry*1000);
|
||||
}
|
||||
|
||||
session.dbx = false;
|
||||
if (urlParams.get('dropbox')){
|
||||
loadScript("https://cdnjs.cloudflare.com/ajax/libs/dropbox.js/10.34.0/Dropbox-sdk.min.js", ()=>{
|
||||
log("Loaded dropbox SDK");
|
||||
var accessToken = urlParams.get('dropbox');
|
||||
session.dbx = new Dropbox.Dropbox({ accessToken: accessToken });
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
if (urlParams.has("darkmode") || urlParams.has("nightmode")){
|
||||
session.darkmode = urlParams.get("darkmode") || urlParams.get("nightmode") || null;
|
||||
@ -2542,6 +2620,10 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.slots = parseInt(urlParams.get('slots')) || 4;
|
||||
}
|
||||
|
||||
if (urlParams.has('alpha')) {
|
||||
session.alpha = true;
|
||||
}
|
||||
|
||||
if (urlParams.has('chunked')) {
|
||||
session.chunked = parseInt(urlParams.get('chunked')) || 2500; // sender side; enables to allows.
|
||||
// session.alpha = true;
|
||||
@ -3107,7 +3189,10 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
log("max channels is 32; channels offset");
|
||||
session.audioEffects = true;
|
||||
}
|
||||
|
||||
if (urlParams.get('playchannel')) { // must be loaded before channelOffset
|
||||
session.playChannel = parseInt(urlParams.get('playchannel')); // for audio output ; not input. see: &channelcount instead.
|
||||
session.audioEffects = true;
|
||||
}
|
||||
if (urlParams.has('enhance')) {
|
||||
//if (parseInt(urlParams.get('enhance')>0){
|
||||
session.enhance = true; //parseInt(urlParams.get('enhance'));
|
||||
@ -4070,6 +4155,28 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.screenShareLabel = session.screenShareLabel.replace(/_/g, " ")
|
||||
}
|
||||
|
||||
if (urlParams.has('whepshare') || urlParams.has('whepsrc')) { // URL or data:base64 image. Becomes local to this viewer only. This is like &avatar, but slightly different. Just CSS in this case
|
||||
try {
|
||||
|
||||
session.whepSrc = urlParams.get('whepshare') || urlParams.get('whepsrc') || false;
|
||||
console.log(session.whepSrc);
|
||||
if (!session.whepSrc){
|
||||
session.whepSrc = await promptAlt("Enter the WHEP source as a URL");
|
||||
} else {
|
||||
session.whepSrc = decodeURIComponent(session.whepSrc, true);
|
||||
}
|
||||
getById("container-6").classList.remove('hidden');
|
||||
getById("container-6").classList.add("skip-animation");
|
||||
getById("container-6").classList.remove('pointer');
|
||||
|
||||
if (session.whepSrc){
|
||||
delayedStartupFuncs.push([shareWebsite, session.whepSrc]);
|
||||
}
|
||||
} catch(e){
|
||||
errorlog(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (session.roomid!==false){
|
||||
if (!(session.cleanOutput)) {
|
||||
if (session.roomid === "test") {
|
||||
@ -4476,6 +4583,10 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
getById("gridlayout").classList.add("nocontrolbar");
|
||||
}
|
||||
|
||||
if (urlParams.has('experimental')) {
|
||||
session.experimental = true;
|
||||
}
|
||||
|
||||
if (urlParams.has('flagship')) {
|
||||
session.flagship = true;
|
||||
}
|
||||
@ -5540,38 +5651,45 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
});
|
||||
|
||||
window.addEventListener("online", function (e) {
|
||||
|
||||
log("Back ONLINE");
|
||||
closeModal();
|
||||
|
||||
if (!session.onceConnected){ // never connected to websockets before. Let's not trigger retryWatchInterval if we don't have to.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!session.retryWatchInterval()){ // ask for the streams again to watch
|
||||
session.ping(); // if no streams requested, let's ping instead.
|
||||
}
|
||||
});
|
||||
|
||||
function updateConnectionStatus() {
|
||||
/* function updateConnectionStatus() { // no longer works in chrome.
|
||||
|
||||
try{
|
||||
if (!session.stats){
|
||||
return;
|
||||
}
|
||||
|
||||
log("Connection type changed from " + session.stats.network_type + " to " + Connection.type);
|
||||
|
||||
if (session.stats.network_type && (session.stats.network_type !== Connection.type)){
|
||||
var miniInfo = {};
|
||||
miniInfo.con = Connection.type;
|
||||
session.sendMessage({"miniInfo":miniInfo});
|
||||
if (Connection.type){
|
||||
log("Connection type changed from " + session.stats.network_type + " to " + Connection.type);
|
||||
|
||||
if (!session.retryWatchInterval()){ // ask for the streams again to watch
|
||||
if (session.stats.network_type && (session.stats.network_type !== Connection.type)){
|
||||
var miniInfo = {};
|
||||
miniInfo.con = Connection.type;
|
||||
session.sendMessage({"miniInfo":miniInfo});
|
||||
|
||||
if (!session.retryWatchInterval()){ // ask for the streams again to watch
|
||||
session.ping(); // if no streams requested, let's ping instead.
|
||||
}
|
||||
|
||||
} else { // connection state changed, but doesn't seem like it actually changed...
|
||||
session.ping(); // if no streams requested, let's ping instead.
|
||||
}
|
||||
|
||||
} else { // connection state changed, but doesn't seem like it actually changed...
|
||||
session.ping(); // if no streams requested, let's ping instead.
|
||||
session.stats.network_type = Connection.type;
|
||||
}
|
||||
|
||||
session.stats.network_type = Connection.type;
|
||||
|
||||
} catch(e){warnlog(e);}
|
||||
|
||||
}
|
||||
@ -5579,10 +5697,12 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
try {
|
||||
var Connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
|
||||
if (Connection){
|
||||
session.stats.network_type = Connection.type
|
||||
if (Connection.type){
|
||||
session.stats.network_type = Connection.type
|
||||
}
|
||||
Connection.addEventListener('change', updateConnectionStatus);
|
||||
}
|
||||
} catch (e) {log(e);} // effectiveType is not yet supported by Firefox or Safari; 2021
|
||||
} catch (e) {log(e);} // effectiveType is not yet supported by Firefox or Safari; 2021 */
|
||||
|
||||
|
||||
setInterval(function() {
|
||||
|
||||
13
mixer.html
13
mixer.html
@ -2399,6 +2399,19 @@
|
||||
document.getElementById("sources").appendChild(a);
|
||||
|
||||
|
||||
var button = document.createElement("button");
|
||||
button.innerHTML = "Publish to Twitch";
|
||||
button.id = "publishTwitch";
|
||||
button.onclick = function(){
|
||||
var URL = window.location.href.replace("/mixer","");
|
||||
URL+="/?scene=0&layout&remote&room="+roomname+additional;
|
||||
URL+="&clean&chroma=000&ssar=landscape&nosettings&prefercurrenttab&selfbrowsersurface=include&displaysurface=browser&np&nopush&publish&whippush=twitch&whippushtoken";
|
||||
var win = window.open( URL ,'targetWindow', 'toolbar=no,location=no,status=no,scaling=no,menubar=no,scrollbars=no,resizable=no,width=1280,height=720');
|
||||
win.focus();
|
||||
win.resizeTo(1280,720);
|
||||
};
|
||||
document.getElementById("sources").appendChild(button);
|
||||
|
||||
var slots = document.getElementById("col1").children;
|
||||
for (var i=0;i<slots.length;i++){
|
||||
slots[i].style.backgroundColor = colors[i];
|
||||
|
||||
376
publish.html
Normal file
376
publish.html
Normal file
@ -0,0 +1,376 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<link rel="stylesheet" href="./lineawesome/css/line-awesome.min.css" />
|
||||
<style>
|
||||
html {
|
||||
border:0;
|
||||
margin:0;
|
||||
outline:0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
video {
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
cursor: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=), none;
|
||||
user-select: none;
|
||||
|
||||
}
|
||||
body {
|
||||
padding: 0 0px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: -webkit-linear-gradient(to top, #363644, 50%, #151b29); /* Chrome 10-25, Safari 5.1-6 */
|
||||
background: linear-gradient(to top, #363644, 50%, #151b29); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
|
||||
font-size: 2em;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
border:0;
|
||||
margin:0;
|
||||
outline:0;
|
||||
}
|
||||
|
||||
button.glyphicon-button:focus,
|
||||
button.glyphicon-button:active:focus,
|
||||
button.glyphicon-button.active:focus,
|
||||
button.glyphicon-button.focus,
|
||||
button.glyphicon-button:active.focus,
|
||||
button.glyphicon-button.active.focus {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
.gobutton {
|
||||
font-size:14px;
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
background: #6aab23;
|
||||
display: flex;
|
||||
border-radius: 0px;
|
||||
border-top-right-radius: 10px;
|
||||
border-bottom-right-radius: 10px;
|
||||
box-shadow: 0 12px 15px -10px #5ca70b, 0 2px 0px #6aab23;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
padding: 0 1em;
|
||||
}
|
||||
.details{
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
border: none;
|
||||
background: #555;
|
||||
display: flex;
|
||||
border-radius: 0px;
|
||||
border-top-right-radius: 10px;
|
||||
border-bottom-right-radius: 10px;
|
||||
box-shadow: 0 12px 15px -10px #444, 0 2px 0px #555;
|
||||
color: white;
|
||||
box-sizing: border-box;
|
||||
align-items: center;
|
||||
padding: 0 1em;
|
||||
}
|
||||
#header{
|
||||
width:100%;
|
||||
background-color: #101520;
|
||||
}
|
||||
input.changeText {
|
||||
font-size: 1em;
|
||||
align-self: center;
|
||||
width: 100%;
|
||||
padding: 1em;
|
||||
font-weight: bold;
|
||||
background: white;
|
||||
border: 4px solid white;
|
||||
box-shadow: 0px 30px 40px -32px #6aab23, 0 2px 0px #6aab23;
|
||||
border-top-left-radius: 10px;
|
||||
border-bottom-left-radius: 10px;
|
||||
transition: all 0.2s linear;
|
||||
box-sizing: border-box;
|
||||
border-bottom-right-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
input.changeText:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.container{
|
||||
font-size: min(14px, 2vh);
|
||||
align-self:center;
|
||||
max-width: 100%;
|
||||
width: 720px;
|
||||
margin: auto auto;
|
||||
}
|
||||
label {
|
||||
font: white;
|
||||
font-size: 1em;
|
||||
color: white;
|
||||
}
|
||||
input[type='checkbox'] {
|
||||
-webkit-appearance:none;
|
||||
width:30px;
|
||||
height:30px;
|
||||
background:white;
|
||||
border-radius:5px;
|
||||
border:2px solid #555;
|
||||
cursor: pointer;
|
||||
}
|
||||
input[type='checkbox']:checked {
|
||||
background: #1A1;
|
||||
}
|
||||
#audioOutput, #lastUrls {
|
||||
font-size: calc(16px + 0.3vw);
|
||||
width: 730px;
|
||||
height: 100%;
|
||||
flex: 20;
|
||||
border-radius: 10px;
|
||||
padding: 1em;
|
||||
background: #eaeaea;
|
||||
cursor:pointer;
|
||||
}
|
||||
label[for="audioOutput"] {
|
||||
font-size: 3em;
|
||||
color: #FE53BB;
|
||||
text-shadow: 0px 0px 30px #fe53bb;
|
||||
padding-right: 10px;
|
||||
}
|
||||
label[for="changeText"] {
|
||||
font-size: 3em;
|
||||
color: #00F6FF;
|
||||
text-shadow: 0px 0px 30px #00f6ff;
|
||||
padding-top: 5px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
label[for="lastUrls"] {
|
||||
font-size: 3em;
|
||||
color: #1a1;
|
||||
text-shadow: 0px 0px 30px #1a1;
|
||||
padding-right: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div#audioOutputContainer, #history {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: center;
|
||||
margin: 4em;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1030px) {
|
||||
body{
|
||||
zoom: 0.9;
|
||||
-moz-transform: scale(0.9);
|
||||
-moz-transform-origin: 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
#messageDiv {
|
||||
font-size: .7em;
|
||||
color: #DDD;
|
||||
transition: all 0.5s linear;
|
||||
font-style: italic;
|
||||
opacity: 0;
|
||||
text-align: center;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
div.urlInput {
|
||||
padding: 0 0 4vh 0;
|
||||
}
|
||||
@media only screen and (max-width: 940px) {
|
||||
body{
|
||||
zoom: 0.74;
|
||||
-moz-transform: scale(0.74);
|
||||
-moz-transform-origin: 0 0;
|
||||
|
||||
}
|
||||
.container{
|
||||
max-width:99%;
|
||||
}
|
||||
div.urlInput {
|
||||
}
|
||||
div#audioOutputContainer, #history {
|
||||
margin: 2em;
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width: 840px) {
|
||||
body{
|
||||
zoom: 0.64;
|
||||
-moz-transform: scale(0.64);
|
||||
-moz-transform-origin: 0 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media only screen and (max-height: 639px) {
|
||||
div.urlInput {
|
||||
}
|
||||
div#audioOutputContainer, #history {
|
||||
margin: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 767px) {
|
||||
|
||||
div.urlInput {
|
||||
}
|
||||
div#audioOutputContainer, #history {
|
||||
margin: 2em 1em;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-height: 380px) {
|
||||
div.urlInput {
|
||||
}
|
||||
div#audioOutputContainer, #history {
|
||||
margin: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
label[for="audioOutput"], label[for="lastUrls"] {
|
||||
font-size: 3em;
|
||||
}
|
||||
|
||||
#warning4mac, #electronVersion {
|
||||
background: #8500f7;
|
||||
box-shadow: 0px 0px 50px 10px #8500f7ab, inset 0px 0px 10px 2px #8d08ffba;
|
||||
border: 2px solid #8500f7;
|
||||
border-radius: 10px;
|
||||
width: 90%;
|
||||
padding:1em;
|
||||
margin:0 auto;
|
||||
color:white;
|
||||
font-size:1.3em;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#warning4mac a, #electronVersion a {
|
||||
color:white;
|
||||
}
|
||||
|
||||
ul#lastUrls {
|
||||
list-style: none;
|
||||
background: #101520;
|
||||
color: white;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
ul#lastUrls li {
|
||||
padding: 5px 0px;
|
||||
}
|
||||
ul#lastUrls li:nth-child(even) {
|
||||
background-color: #182031;
|
||||
}
|
||||
|
||||
.inputCombo {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
flex-grow: 1;
|
||||
}
|
||||
#version{
|
||||
margin: 0 auto;
|
||||
font-size: 30%;
|
||||
display: inline-block;
|
||||
color: #000A;
|
||||
}
|
||||
h3 {
|
||||
color: #b0e3ff;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="header" style="-webkit-app-region: drag; color:#6f6f6f;font-size:20px; line-height: 20px; padding: 5px 10px; letter-spacing: 3; font-weight: bold;">Publish VDO.Ninja video mix to Twitch</div>
|
||||
|
||||
<div class="container">
|
||||
<div id="urlInput1" class="urlInput" title="Put the link you want to load here">
|
||||
|
||||
<h3>Publish a video from VDO.Ninja Scene or View link to Twitch directly</h3>
|
||||
|
||||
<div class="inputCombo" id="inputCombo1">
|
||||
<label for="changeText">
|
||||
<i class="las la-upload"></i>
|
||||
</label>
|
||||
<input type="text" id="changeText1" class="inputfield changeText" placeholder="VDO.Ninja scene link to publish" />
|
||||
<button onclick="gohere1();" class="gobutton" id="gobutton1">GO</button>
|
||||
</div>
|
||||
<div class="inputCombo" style="width:350px;margin:10 0 10 auto;">
|
||||
<input type="password" id="changeText1a" class="inputfield changeText" placeholder="Authentication Bearer Token (optional)" />
|
||||
<div class="details">⚙️</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
var domain = "./";
|
||||
|
||||
document.querySelector("#changeText1").value = localStorage.getItem('changeText1') || "";
|
||||
document.querySelector("#changeText1a").value = localStorage.getItem('changeText1a') || "";
|
||||
function gohere1(){
|
||||
localStorage.setItem('changeText1', document.getElementById('changeText1').value);
|
||||
localStorage.setItem('changeText1a', document.getElementById('changeText1a').value);
|
||||
|
||||
var URL = document.getElementById('changeText1').value;
|
||||
URL+="&clean&chroma=000&ssar=landscape&nosettings&prefercurrenttab&selfbrowsersurface=include&displaysurface=browser&np&nopush&publish&whippush=https%3A%2F%2Fg.webrtc.live-video.net%3A4443%2Fv2%2Foffer&whippushtoken="+document.querySelector("#changeText1a").value;
|
||||
var win = window.open( URL ,'targetWindow', 'toolbar=no,location=no,status=no,scaling=no,menubar=no,scrollbars=no,resizable=no,width=1280,height=720');
|
||||
win.focus();
|
||||
win.resizeTo(1280,720);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function resetHistory(){
|
||||
localStorage.clear();
|
||||
document.querySelector("#changeText1").value = "";
|
||||
document.querySelector("#changeText1a").value = "";
|
||||
}
|
||||
|
||||
(function (w) {
|
||||
w.URLSearchParams = w.URLSearchParams || function (searchString) {
|
||||
var self = this;
|
||||
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 urlParams = new URLSearchParams(window.location.search);
|
||||
|
||||
function enterPressed(event, callback){
|
||||
if (event.keyCode === 13){ // Number 13 is the "Enter" key on the keyboard
|
||||
event.preventDefault(); // Cancel the default action, if needed
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var isMobile = false;
|
||||
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)){ // does not detect iPad Pros.
|
||||
isMobile=true; // if iOS, default to H264? meh. let's not.
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -308,7 +308,7 @@
|
||||
<button onclick="gohere1();" class="gobutton" id="gobutton1">GO</button>
|
||||
</div>
|
||||
<div class="inputCombo" style="width:350px;margin:10 0 10 auto;">
|
||||
<input type="text" id="changeText1a" class="inputfield changeText" placeholder="Authentication Bearer Token (optional)" />
|
||||
<input type="password" id="changeText1a" class="inputfield changeText" placeholder="Authentication Bearer Token (optional)" />
|
||||
<div class="details">⚙️</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -321,7 +321,7 @@
|
||||
<label for="changeText">
|
||||
<i class="las la-upload"></i>
|
||||
</label>
|
||||
<input type="text" id="changeText1t" class="inputfield changeText" placeholder="Enter your Twitch stream token here" />
|
||||
<input type="password" id="changeText1t" class="inputfield changeText" placeholder="Enter your Twitch stream token here" />
|
||||
<button onclick="gohere1t();" class="gobutton" id="gobutton1t">GO</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -396,7 +396,7 @@ function gohere1(){
|
||||
function gohere1t(){
|
||||
if (document.getElementById('changeText1t').value){
|
||||
localStorage.setItem('changeText1t', document.getElementById('changeText1t').value);
|
||||
window.location = domain + "?push&whippush=https%3A%2F%2Ftwitch.vdo.ninja%2F"+ document.getElementById('changeText1t').value;
|
||||
window.location = domain + "?push&whippush=https%3A%2F%2Fg.webrtc.live-video.net%3A4443%2Fv2%2Foffer&whippushtoken="+ document.getElementById('changeText1t').value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user