mirror of
https://github.com/eliasstepanik/vdo.ninja.git
synced 2026-01-11 13:48:38 +00:00
v24.b ; cloudflare as meshcast support; motiondetection
This commit is contained in:
parent
7154b90c03
commit
883bd18410
148
index.html
148
index.html
@ -1,4 +1,4 @@
|
||||
<html>
|
||||
<html lang='en'>
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
// MS Internet Explorer must not be given a chance to fail before I can give the user an error message.
|
||||
@ -57,8 +57,8 @@
|
||||
<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/vdoNinja_logo_full.png" />
|
||||
<meta name="msapplication-TileColor" content="#da532c" />
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
<link rel="stylesheet" href="./main.css?ver=361" />
|
||||
<meta name="theme-color" content="#0f131d" />
|
||||
<link rel="stylesheet" href="./main.css?ver=363" />
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/adapter.js"></script>
|
||||
<style id="lightbox-animations" type="text/css"></style>
|
||||
|
||||
@ -92,7 +92,7 @@
|
||||
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/CodecsHandler.js?ver=49"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/aes.js"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./webrtc.js?ver=686"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./webrtc.js?ver=693"></script>
|
||||
<input id="zoomSlider" type="range" style="display: none;" />
|
||||
<span id="electronDragZone" style="pointer-events: none; z-index:-10; position:absolute;top:0;left:0;width:100%;height:2%;-webkit-app-region: drag;min-height:20px;"></span>
|
||||
<div id="header">
|
||||
@ -103,8 +103,8 @@
|
||||
</span>
|
||||
</a>
|
||||
<div id="head1">
|
||||
<input type="text" autocorrect="off" autocapitalize="none" id="joinroomID" name="joinroomID" size="22" placeholder="Join by Room Name here" alt="Enter a room name to join" title="Enter a room name to quick join" onkeyup="jumptoroom(event)"/>
|
||||
<button onclick="jumptoroom();" id='jumptoroomButton' role="button" aria-pressed="false" alt="Join room" title="Join room" >GO</button>
|
||||
<input type="text" autocorrect="off" autocapitalize="none" id="joinroomID" name="joinroomID" tabindex="1" size="22" placeholder="Join by Room Name here" alt="Enter a room name to join" title="Enter a room name to quick join" onkeyup="jumptoroom(event)"/>
|
||||
<button onclick="jumptoroom();" id='jumptoroomButton' role="button" aria-pressed="false" tabindex="1" alt="Join room" title="Join room" >GO</button>
|
||||
</div>
|
||||
<div id="head1a" class="hidden">
|
||||
<input type="text" autocorrect="off" autocapitalize="none" id="joinbyURL" name="joinbyURL" size="22" placeholder="Load a website URL" alt="Enter the URL to load" title="Enter the URL to load"/>
|
||||
@ -112,7 +112,7 @@
|
||||
</div>
|
||||
<div id="head5" class="hidden"></div>
|
||||
<div id="head3" style="display: inline-block;" class="hidden">
|
||||
<span style="color: #888;" id="copythisurl">
|
||||
<span style="color: #888;" id="copythisurl" tabindex="1" >
|
||||
<span data-translate="copy-this-url">Copy this URL into an OBS "Browser Source"</span> <i style="color: #CCC;" class="las la-long-arrow-alt-right"></i>
|
||||
</span>
|
||||
</div>
|
||||
@ -161,100 +161,100 @@
|
||||
</div>
|
||||
<div id="subControlButtons">
|
||||
|
||||
<div id="mediafileshare" onmousedown="event.preventDefault(); event.stopPropagation();" title="Stream a media file" aria-label="Stream a media file" alt="Stream a media file to others" onclick="getById('fileselector2').click();" tabindex="21" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden" style="cursor: pointer;">
|
||||
<div id="mediafileshare" onmousedown="event.preventDefault(); event.stopPropagation();" title="Stream a media file" aria-label="Stream a media file" alt="Stream a media file to others" onclick="getById('fileselector2').click();" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden" style="cursor: pointer;">
|
||||
<i id="mediafilesharetoggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-file-video"></i>
|
||||
<input id="fileselector2" class="hidden" onchange="session.changePublishFile(this,event);" type="file" accept="video/*,audio/*" alt="Hold CTRL (or CMD) to select multiple files" title="Hold CTRL (or CMD) to select multiple files" multiple/>
|
||||
</div>
|
||||
|
||||
<div id="blindAllGuests" title="Blind all guests in room (toggle)" alt="Blind all guests in room (toggle)" aria-label="Blind all guests in room" onmousedown="event.preventDefault(); event.stopPropagation();" onclick="blindAllGuests(this, event)" tabindex="16" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;" >
|
||||
<div id="blindAllGuests" title="Blind all guests in room (toggle)" alt="Blind all guests in room (toggle)" aria-label="Blind all guests in room" onmousedown="event.preventDefault(); event.stopPropagation();" onclick="blindAllGuests(this, event)" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;" >
|
||||
<i class="toggleSize las la-eye"></i>
|
||||
</div>
|
||||
|
||||
<div id="queuebutton" title="Load the next guest in queue" alt="Load the next guest in queue" aria-label="Load next guest in queue" onmousedown="event.preventDefault(); event.stopPropagation();" onclick="nextQueue()" tabindex="16" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;" >
|
||||
<div id="queuebutton" title="Load the next guest in queue" alt="Load the next guest in queue" aria-label="Load next guest in queue" onmousedown="event.preventDefault(); event.stopPropagation();" onclick="nextQueue()" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;" >
|
||||
<i id="queuetoggle" class="toggleSize las la-stream"></i>
|
||||
<div id="queueNotification"></div>
|
||||
</div>
|
||||
<div id="sharefilebutton" title="Transfer any file to the group" alt="Transfer any file to the group" aria-label="Select file to transfer" onmousedown="event.preventDefault(); event.stopPropagation();" onclick="toggleFileshare()" tabindex="16" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden" style="cursor: pointer;display:none!important;" >
|
||||
<div id="sharefilebutton" title="Transfer any file to the group" alt="Transfer any file to the group" aria-label="Select file to transfer" onmousedown="event.preventDefault(); event.stopPropagation();" onclick="toggleFileshare()" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden" style="cursor: pointer;display:none!important;" >
|
||||
<i id="filesharetoggle" class="toggleSize las la-file-upload"></i>
|
||||
<div id="transferNotification"></div>
|
||||
</div>
|
||||
<div id="chatbutton" title="Toggle the Chat" alt="Toggle the Chat" aria-label="Text chat" onmousedown="event.preventDefault(); event.stopPropagation();" onclick="toggleChat()" tabindex="16" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;" >
|
||||
<div id="chatbutton" title="Toggle the Chat" alt="Toggle the Chat" aria-label="Text chat" onmousedown="event.preventDefault(); event.stopPropagation();" onclick="toggleChat()" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;" >
|
||||
<i id="chattoggle" class="toggleSize las la-comment-alt"></i>
|
||||
<div id="chatNotification"></div>
|
||||
</div>
|
||||
<div id="mutespeakerbutton" onmousedown="event.preventDefault(); event.stopPropagation();" alt="Toggle the speaker output." aria-label="Mute Speaker output" title="Mute the Speaker" onclick="toggleSpeakerMute()" tabindex="17" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;" >
|
||||
<div id="mutespeakerbutton" onmousedown="event.preventDefault(); event.stopPropagation();" alt="Toggle the speaker output." aria-label="Mute Speaker output" title="Mute the Speaker" onclick="toggleSpeakerMute()" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;" >
|
||||
<i id="mutespeakertoggle" class="toggleSize las la-volume-up" style="position: relative; top: 0.5px;"></i>
|
||||
</div>
|
||||
<div id="mutebutton" onmousedown="toggleMute(false, event);event.preventDefault(); event.stopPropagation();" alt="Mute the Mic" aria-label="Mute Microphone" title="Mute the Mic" ontouchstart="toggleMute(false, event);event.preventDefault(); event.stopPropagation();" tabindex="18" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;">
|
||||
<div id="mutebutton" onmousedown="toggleMute(false, event);event.preventDefault(); event.stopPropagation();" alt="Mute the Mic" aria-label="Mute Microphone" title="Mute the Mic" ontouchstart="toggleMute(false, event);event.preventDefault(); event.stopPropagation();" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;">
|
||||
<i id="mutetoggle" class="toggleSize las la-microphone" style="position: relative; top: 0.5px;"></i>
|
||||
</div>
|
||||
<div id="mutevideobutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Disable the Camera" alt="Disable the Camera" aria-label="Mute Camera" onclick="toggleVideoMute()" tabindex="19" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;">
|
||||
<div id="mutevideobutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Disable the Camera" alt="Disable the Camera" aria-label="Mute Camera" onclick="toggleVideoMute()" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="hidden float" style="cursor: pointer;">
|
||||
<i id="mutevideotoggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-video"></i>
|
||||
</div>
|
||||
<div id="screensharebutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Share a Screen with others" alt="Share a Screen with others" aria-label="Share a screen" onclick="screenshareTypeDecider(1)" tabindex="20" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden task" data-menu="context-menu-screen-share" style="cursor: pointer;">
|
||||
<div id="screensharebutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Share a Screen with others" alt="Share a Screen with others" aria-label="Share a screen" onclick="screenshareTypeDecider(1)" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden task" data-menu="context-menu-screen-share" style="cursor: pointer;">
|
||||
<i id="screensharetoggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-desktop"></i>
|
||||
</div>
|
||||
<div id="screenshare2button" onmousedown="event.preventDefault(); event.stopPropagation();" title="Add a Screen Share" alt="Add a Screen Share" aria-label="Share a screen" onclick="screenshareTypeDecider(2)" tabindex="20" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden task" data-menu="context-menu-screen-share" style="cursor: pointer;">
|
||||
<div id="screenshare2button" onmousedown="event.preventDefault(); event.stopPropagation();" title="Add a Screen Share" alt="Add a Screen Share" aria-label="Share a screen" onclick="screenshareTypeDecider(2)" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden task" data-menu="context-menu-screen-share" style="cursor: pointer;">
|
||||
<i id="screenshare2toggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-tv"></i>
|
||||
</div>
|
||||
<div id="screenshare3button" onmousedown="event.preventDefault(); event.stopPropagation();" title="Share a Screen with others" alt="Add a Screen Share" aria-label="Share a screen" onclick="screenshareTypeDecider(3)" tabindex="20" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden task" data-menu="context-menu-screen-share" style="cursor: pointer;">
|
||||
<div id="screenshare3button" onmousedown="event.preventDefault(); event.stopPropagation();" title="Share a Screen with others" alt="Add a Screen Share" aria-label="Share a screen" onclick="screenshareTypeDecider(3)" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden task" data-menu="context-menu-screen-share" style="cursor: pointer;">
|
||||
<i id="screenshare3toggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-tv"></i>
|
||||
</div>
|
||||
<div id="websitesharebutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Share a website with your guests (IFRAME)" aria-label="Share a website" alt="Share a website with your guests (IFRAME)" onclick="shareWebsite(false, event)" tabindex="21" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden" style="cursor: pointer;">
|
||||
<div id="websitesharebutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Share a website with your guests (IFRAME)" aria-label="Share a website" alt="Share a website with your guests (IFRAME)" onclick="shareWebsite(false, event)" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden" style="cursor: pointer;">
|
||||
<i id="websitesharetoggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-window-maximize"></i>
|
||||
</div>
|
||||
<div id="websitesharebutton2" onmousedown="event.preventDefault(); event.stopPropagation();" title="Hold CTRL (or CMD) and click to spotlight this video" alt="Share a website as an embedded iFRAME" aria-label="Share a website" onclick="shareWebsite(false, event)" tabindex="21" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float2 orange shake hidden" style="cursor: pointer;max-width: 200px;margin: auto;padding: 0 10px;">
|
||||
<div id="websitesharebutton2" onmousedown="event.preventDefault(); event.stopPropagation();" title="Hold CTRL (or CMD) and click to spotlight this video" alt="Share a website as an embedded iFRAME" aria-label="Share a website" onclick="shareWebsite(false, event)" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float2 orange shake hidden" style="cursor: pointer;max-width: 200px;margin: auto;padding: 0 10px;">
|
||||
<i onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-window-close" style="display: inline-block;"></i>
|
||||
<div style="display: inline-block;width: 85px;line-height: 1; font-size: 0.9em; background-color: unset;box-shadow: unset;">
|
||||
Stop Sharing Website
|
||||
</div>
|
||||
</div>
|
||||
<div id="fullscreenPage" onmousedown="event.preventDefault(); event.stopPropagation();" title="Full-screen the page" alt="Full-screen the page" aria-label="Full screen" onclick="fullscreenPageToggle()" tabindex="21" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden" style="cursor: pointer;">
|
||||
<div id="fullscreenPage" onmousedown="event.preventDefault(); event.stopPropagation();" title="Full-screen the page" alt="Full-screen the page" aria-label="Full screen" onclick="fullscreenPageToggle()" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden" style="cursor: pointer;">
|
||||
<i id="fullscreenPageToggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-expand-arrows-alt"></i>
|
||||
</div>
|
||||
<div id="PictureInPicturePage" onmousedown="event.preventDefault(); event.stopPropagation();" title="Picture-in-Picture the video mix" alt="Picture-in-Picture the page" aria-label="Picture-in-Picture" onclick="PictureInPicturePageToggle()" tabindex="21" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden" style="cursor: pointer;">
|
||||
<div id="PictureInPicturePage" onmousedown="event.preventDefault(); event.stopPropagation();" title="Picture-in-Picture the video mix" alt="Picture-in-Picture the page" aria-label="Picture-in-Picture" onclick="PictureInPicturePageToggle()" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="float hidden" style="cursor: pointer;">
|
||||
<i id="PictureInPicturePageToggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-external-link-square-alt"></i>
|
||||
</div>
|
||||
<div id="flipcamerabutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Cycle the Cameras" onclick="cycleCameras()" class="hidden float" tabindex="21" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" aria-label="Cycle Cameras" alt="Cycle the Cameras">
|
||||
<div id="flipcamerabutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Cycle the Cameras" onclick="cycleCameras()" class="hidden float" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" aria-label="Cycle Cameras" alt="Cycle the Cameras">
|
||||
<i id="settingstoggle" class="toggleSize las la-sync-alt"></i>
|
||||
</div>
|
||||
|
||||
<div id="obscontrolbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="OBS Remote Controller; start/stop and change scenes." onclick="toggleOBSControls();" class="hidden float" tabindex="22" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" aria-label="Remote OBS control menu" alt="Toggle the Remote OBS Controls Menu">
|
||||
<div id="obscontrolbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="OBS Remote Controller; start/stop and change scenes." onclick="toggleOBSControls();" class="hidden float" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" aria-label="Remote OBS control menu" alt="Toggle the Remote OBS Controls Menu">
|
||||
<i id="obscontroltoggle" class="toggleSize las la-gamepad"></i>
|
||||
</div>
|
||||
|
||||
<div id="roomsettingsbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Room Settings" onclick="toggleRoomSettings();" class="hidden float" tabindex="22" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" alt="Toggle the Room Settings Menu" aria-label="Room settings menu">
|
||||
<div id="roomsettingsbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Room Settings" onclick="toggleRoomSettings();" class="hidden float" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" alt="Toggle the Room Settings Menu" aria-label="Room settings menu">
|
||||
<i id="roomsettingstoggle" class="toggleSize las la-users-cog"></i>
|
||||
</div>
|
||||
|
||||
<div id="settingsbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Your audio and video Settings" onclick="toggleSettings()" class="hidden float" tabindex="22" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" alt="Toggle Settings Menu" aria-label="Settings menu">
|
||||
<div id="settingsbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Your audio and video Settings" onclick="toggleSettings()" class="hidden float" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" alt="Toggle Settings Menu" aria-label="Settings menu">
|
||||
<i id="settingstoggle" class="toggleSize las la-cog"></i>
|
||||
</div>
|
||||
|
||||
<div id="hangupbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Hangup the Call" aria-label="Hang up" alt="Hangup the Call" onclick="hangup()" class="hidden float" tabindex="23" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" >
|
||||
<div id="hangupbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Hangup the Call" aria-label="Hang up" alt="Hangup the Call" onclick="hangup()" class="hidden float" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" >
|
||||
<i class="toggleSize las la-phone rotate225" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div id="raisehandbutton" onmousedown="event.preventDefault(); event.stopPropagation();" data-raised="0" title="Alert the host you want to speak" aria-label="Raise hand" alt="Alert the host you want to speak" tabindex="24" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" onclick="raisehand()" class="hidden float" style="cursor: pointer;">
|
||||
<div id="raisehandbutton" onmousedown="event.preventDefault(); event.stopPropagation();" data-raised="0" title="Alert the host you want to speak" aria-label="Raise hand" alt="Alert the host you want to speak" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" onclick="raisehand()" class="hidden float" style="cursor: pointer;">
|
||||
<i class="toggleSize las la-hand-paper" style="position: relative; right: 1px;" aria-hidden="true"></i>
|
||||
</div>
|
||||
|
||||
<div id="pptbackbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Go back a slide" aria-label="Back a slide" alt="Go back a slide" tabindex="25" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" onclick="gobackSlide()" class="hidden float red" style="cursor: pointer;">
|
||||
<div id="pptbackbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Go back a slide" aria-label="Back a slide" alt="Go back a slide" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" onclick="gobackSlide()" class="hidden float red" style="cursor: pointer;">
|
||||
<i class="toggleSize las la-chevron-left" style="position: relative; right: 1px;" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div id="pptnextbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Next slide" aria-label="Next slide" alt="Next slide" tabindex="25" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" onclick="nextSlide()" class="hidden float" style="cursor: pointer;">
|
||||
<div id="pptnextbutton" onmousedown="event.preventDefault(); event.stopPropagation();" title="Next slide" aria-label="Next slide" alt="Next slide" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" onclick="nextSlide()" class="hidden float" style="cursor: pointer;">
|
||||
<i class="toggleSize las la-chevron-right" style="position: relative; right: 1px;" aria-hidden="true"></i>
|
||||
</div>
|
||||
|
||||
<div id="recordLocalbutton" onmousedown="event.preventDefault(); event.stopPropagation();" data-state="0" title="Record your stream to disk" aria-label="Record your stream to disk" alt="Record your stream to disk" tabindex="25" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" onclick="recordLocalVideoToggle();" class="hidden float" style="cursor: pointer;">
|
||||
<div id="recordLocalbutton" onmousedown="event.preventDefault(); event.stopPropagation();" data-state="0" title="Record your stream to disk" aria-label="Record your stream to disk" alt="Record your stream to disk" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" onclick="recordLocalVideoToggle();" class="hidden float" style="cursor: pointer;">
|
||||
<i class="toggleSize las la-dot-circle" style="position: relative;" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div id="recordLocalScreenbutton" onmousedown="event.preventDefault(); event.stopPropagation();" data-state="0" title="Stop screen share recording" aria-label="Stop screen share recording" alt="Stop screen recording" tabindex="25" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" onclick="recordLocalScreenStopRecord();" class="hidden float" style="cursor: pointer;">
|
||||
<div id="recordLocalScreenbutton" onmousedown="event.preventDefault(); event.stopPropagation();" data-state="0" title="Stop screen share recording" aria-label="Stop screen share recording" alt="Stop screen recording" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" onclick="recordLocalScreenStopRecord();" class="hidden float" style="cursor: pointer;">
|
||||
<small>Stop<br>Screen<br>Record</small>
|
||||
</div>
|
||||
<span id="miniPerformer" style="pointer-events: auto;" class="hidden"></span>
|
||||
<span id="rooms" class="hidden" style="padding-top:3px;padding-left:6px;pointer-events: auto;color:#fff;"></span>
|
||||
<span id="groups" class="hidden" style="padding-top:3px;padding-left:6px;pointer-events: auto;color:#fff;text-align: center;"></span>
|
||||
<div id="hangupbutton2" onmousedown="event.preventDefault(); event.stopPropagation();" title="Cancel the Director's Video/Audio" onclick="hangup2()" class="hidden float" tabindex="26" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" aria-label="stop publishing audio and video" alt="Disconnect Direcotor's cam">
|
||||
<div id="hangupbutton2" onmousedown="event.preventDefault(); event.stopPropagation();" title="Cancel the Director's Video/Audio" onclick="hangup2()" class="hidden float" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" style="cursor: pointer;" aria-label="stop publishing audio and video" alt="Disconnect Direcotor's cam">
|
||||
<i class="toggleSize las la-phone rotate225" aria-hidden="true"></i>
|
||||
</div>
|
||||
</div>
|
||||
@ -270,27 +270,31 @@
|
||||
onclick="submitDebugLog();"
|
||||
style="cursor: pointer;z-index:3;display:none;"
|
||||
class="hidden"
|
||||
role="button"
|
||||
tabindex="3"
|
||||
>
|
||||
<i style="cursor: pointer; color: #d9e4eb; padding: 2px; margin: 2px 2px 0 0; font-size: 140%;" class="las la-bug" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span
|
||||
id="helpbutton"
|
||||
title="Show Help Info"
|
||||
title="Show help contact info"
|
||||
onclick="warnUser('For support, please browse https://reddit.com/r/vdoninja or join the live chat on Discord at https://discord.vdo.ninja.\n\nThe Docs also contains many help guides and advanced settings, located at https://docs.vdo.ninja.\n\nTo access the video stats menu, hold CTRL (command) and Left-Click on a video. Most video issues can be fixed by using Wired Internet instead of Wi-Fi.')"
|
||||
style="cursor: pointer; display:none;"
|
||||
alt="How to Use This with OBS"
|
||||
role="button"
|
||||
tabindex="3"
|
||||
>
|
||||
<i style="cursor: pointer; color: #d9e4eb; padding: 2px; margin: 2px 2px 0 0; font-size: 140%;" class="las la-question-circle" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span title="Language Options" onclick="toggle(document.getElementById('languages'));" aria-label="language options" aria-pressed="false" id="translateButton">
|
||||
<span title="Language options" onclick="toggle(document.getElementById('languages'));" tabindex="3" role="button" aria-label="language options" aria-pressed="false" id="translateButton">
|
||||
<i style="cursor: pointer;color: #d9e4eb; padding: 2px; margin: 2px 2px 0 0; font-size: 140%;" class="las la-language" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span title="Add to Calendar" onclick="toggle(document.getElementById('calendar'));" id="calendarButton">
|
||||
<span title="Add to Calendar" onclick="toggle(document.getElementById('calendar'));" tabindex="3" role="button" id="calendarButton">
|
||||
<i style="cursor: pointer; color: #d9e4eb; padding: 2px; margin: 2px 2px 0 0; font-size: 140%;" class="las la-calendar" aria-hidden="true"></i>
|
||||
</span>
|
||||
</span>
|
||||
<div id="mainmenu" class="row" style="opacity: 0;">
|
||||
<div id="container-1" title="Add Group Chat to OBS" alt="Add Group Chat to OBS" tabindex="2" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="column columnfade pointer rounded card" style=" overflow-y: auto;">
|
||||
<div id="container-1" title="Add Group Chat to OBS" alt="Add Group Chat to OBS" tabindex="1" role="button" aria-pressed="false" onkeyup="enterPressedClick(event,this);" class="column columnfade pointer rounded card" style=" overflow-y: auto;">
|
||||
|
||||
<h2>
|
||||
<span data-translate="add-group-chat">Create a Room</span>
|
||||
@ -413,21 +417,21 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="container-3" title="Add your Camera to OBS" onkeyup="enterPressedClick(event,this);" alt="Add your Camera to OBS" tabindex="3" role="button" aria-pressed="false" class="column columnfade pointer rounded card" onclick="previewWebcam()" style=" overflow-y: auto;">
|
||||
<div id="container-3" title="Add your Camera to OBS" onkeyup="enterPressedClick(event,this);" alt="Add your Camera to OBS" tabindex="1" role="button" aria-pressed="false" class="column columnfade pointer rounded card" onclick="previewWebcam()" style=" overflow-y: auto;">
|
||||
<h2 id="add_camera">
|
||||
<span data-translate="add-your-camera">Add your Camera to OBS</span>
|
||||
</h2>
|
||||
<div class="container-inner" id="add_camera_inner">
|
||||
<br />
|
||||
<p>
|
||||
<video id="previewWebcam" class="previewWebcam task" title="Right-click this video for additional options" data-menu="context-menu-video" oncanplay="updateStats();" controlsList="nodownload" muted autoplay playsinline ></video>
|
||||
<video id="previewWebcam" class="previewWebcam task" aria-hidden="true" title="Right-click this video for additional options" data-menu="context-menu-video" oncanplay="updateStats();" controlsList="nodownload" muted autoplay playsinline ></video>
|
||||
</p>
|
||||
<div id="infof"></div>
|
||||
<button onclick="this.disabled=true;setTimeout(function(){requestBasicPermissions();},20);" id="getPermissions" style="display:none;" data-ready="false" >
|
||||
<span data-translate="ask-for-permissions">Allow Access to Camera/Microphone</span>
|
||||
</button>
|
||||
<span style="display:block;">
|
||||
<button onclick="publishWebcam(this)" title="start streaming" aria-label="Start streaming" aria-pressed="false" tabindex="15" id="gowebcam" class="gowebcam" alt="Start Streaming" disabled data-audioready="false" data-ready="false" >
|
||||
<button onclick="publishWebcam(this)" title="start streaming" aria-label="Start streaming" role="button" aria-pressed="false" tabindex="1" id="gowebcam" class="gowebcam" alt="Start Streaming" disabled data-audioready="false" data-ready="false" >
|
||||
<span data-translate="waiting-for-camera">Waiting for Camera to Load</span>
|
||||
</button>
|
||||
</span>
|
||||
@ -435,18 +439,18 @@
|
||||
<i class="las la-exclamation-circle"></i>
|
||||
<p><span data-translate="privacy-disabled">Privacy warning: The director will be able to remotely change your camera, microphone, and URL.</span></p>
|
||||
</div>
|
||||
<div id="guestTips" style="display:none">
|
||||
<div id="guestTips" style="display:none" aria-hidden="true">
|
||||
<p data-translate="for-the-best-possible-experience-make-sure">For the best possible experience, make sure</p>
|
||||
<span><i class="las la-plug"></i><span data-translate="your-device-is-powered">Your device is powered</span></span>
|
||||
<span><i class="las la-ethernet"></i><span data-translate="your-connection-is-hardwired-instead-of-wifi">Your connection is hardwired instead of wifi</span></span>
|
||||
<span><i class="las la-headphones"></i><span data-translate="you-are-using-headphones-earphones">You are using headphones / earphones</span></span>
|
||||
</div>
|
||||
<div id="videoMenu" class="videoMenu">
|
||||
<div id="videoMenu" class="videoMenu" aria-hidden="true">
|
||||
<div class="title">
|
||||
<i class="las la-video"></i><span data-translate="video-source"> Video Source </span>
|
||||
</div>
|
||||
<span style="display:inline-block;padding-top: 5px;">
|
||||
<select id="videoSourceSelect" alt="Video source list"></select>
|
||||
<select id="videoSourceSelect" tabindex="1" title="Video source list"></select>
|
||||
<span id="gear_webcam" onclick="toggle(document.getElementById('videoSettings'));">
|
||||
<i class="las la-cog" style="font-size: 140%; vertical-align: middle;" aria-hidden="true"></i>
|
||||
</span>
|
||||
@ -458,7 +462,7 @@
|
||||
</div>
|
||||
<br />
|
||||
<center>
|
||||
<div id="videoSettings" style="display: none;">
|
||||
<div id="videoSettings" style="display: none;" aria-hidden="true">
|
||||
<form id="webcamquality">
|
||||
<input type="radio" id="fullhd" alt="1080p60 video capture" name="resolution" value="0" />
|
||||
<label for="fullhd">
|
||||
@ -478,7 +482,7 @@
|
||||
</form>
|
||||
</div>
|
||||
</center>
|
||||
<div id="audioMenu" class="form-group multiselect" alt="tip: Hold CTRL (command) to select Multiple" title="tip: Hold CTRL (command) to select Multiple">
|
||||
<div id="audioMenu" class="form-group multiselect" alt="tip: Hold CTRL (command) to select Multiple" title="tip: Hold CTRL (command) to select Multiple" aria-hidden="true">
|
||||
<span class='gear_microphone hidden'>
|
||||
<input type="checkbox" id='micStereoMonoInput' alt="Mono microphone audio" onchange="toggleMonoStereoMic(this);">Mono
|
||||
</span>
|
||||
@ -503,9 +507,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<br style="line-height: 0;" />
|
||||
<div id="headphonesDiv" class="audioMenu">
|
||||
<div id="headphonesDiv" class="audioMenu" aria-hidden="true">
|
||||
<div class="title">
|
||||
<i class="las la-headphones"></i><span data-translate="select-output-source"> Audio Output Destination</span><button onclick="playtone()" class="testtonebutton" type="button">Test</button>
|
||||
<i class="las la-headphones"></i><span data-translate="select-output-source"> Audio Output Destination</span><button onclick="playtone()" title="Play a sound out of the selected audio playback device" class="testtonebutton" type="button">Test</button>
|
||||
</div>
|
||||
<select id="outputSource" alt="Audio output device" ></select>
|
||||
<div id="headphoneTip1" class="cameraTip hidden">
|
||||
@ -514,7 +518,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<br style="line-height: 0;" />
|
||||
<div id="avatarDiv" class="hidden">
|
||||
<div id="avatarDiv" class="hidden" aria-hidden="true">
|
||||
<div class="title">
|
||||
<i class="las la-robot"></i><span data-translate="select-avatar-image"> Default Avatar / Placeholder Image </span>
|
||||
</div>
|
||||
@ -531,7 +535,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<br style="line-height: 0;" />
|
||||
<div id="effectsDiv">
|
||||
<div id="effectsDiv" aria-hidden="true">
|
||||
<div class="title">
|
||||
<i class="las la-robot"></i><span data-translate="select-digital-effect"> Digital Video Effects </span>
|
||||
</div>
|
||||
@ -565,25 +569,25 @@
|
||||
</div>
|
||||
<br style="line-height: 0;" />
|
||||
<div id="addPasswordBasic">
|
||||
<div class="title">
|
||||
<div class="title" title="Add an optional password">
|
||||
<i class="las la-key"></i><span data-translate="add-a-password"> Add a Password</span>
|
||||
</div>
|
||||
<input type="text" id="passwordBasicInput" placeholder="optional"/>
|
||||
<input type="text" id="passwordBasicInput" title="Enter an optional password here" placeholder="optional"/>
|
||||
</div>
|
||||
|
||||
<div id="SafariWarning" class="startupWarning hidden">
|
||||
<div id="SafariWarning" class="startupWarning hidden" aria-hidden="true" title="Consider using Chrome instead of Safari">
|
||||
<i class="las la-exclamation-circle"></i>
|
||||
<p><span data-translate="use-chrome-instead">Consider using a Chromium-based browser instead.<br />
|
||||
Safari is more prone to having audio issues</span></p>
|
||||
</div>
|
||||
|
||||
<div id="oldiOSWarning" class="startupWarning hidden">
|
||||
<div id="oldiOSWarning" class="startupWarning hidden" title="Please update your version of iOS for best performance">
|
||||
<i class="las la-exclamation-circle"></i>
|
||||
<p><span data-translate="update-your-device">We've detected that you are using an old version of Apple iOS, which is known to have many issues.<br /><br />Please consider updating.</span></p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="outer close">
|
||||
<div class="outer close" role="button" aria-pressed="false" title="Go back">
|
||||
<div class="inner">
|
||||
<label class="labelclass">
|
||||
<span data-translate="back">Back</span>
|
||||
@ -591,11 +595,11 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="container-3a" title="Add your Microphone to OBS" onkeyup="enterPressedClick(event,this);" alt="Add your Microphone to OBS" tabindex="3" role="button" aria-pressed="false" class="microphoneBackground column columnfade pointer rounded card hidden" onclick="previewWebcam(true)" style=" overflow-y: auto;">
|
||||
<div id="container-3a" title="Add your Microphone to OBS" onkeyup="enterPressedClick(event,this);" alt="Add your Microphone to OBS" tabindex="1" role="button" aria-pressed="false" class="microphoneBackground column columnfade pointer rounded card hidden" onclick="previewWebcam(true)" style=" overflow-y: auto;">
|
||||
<h2 id="add_microphone">
|
||||
<span data-translate="add-your-microphone">Add your Microphone to OBS</span>
|
||||
</h2>
|
||||
<div class="outer close">
|
||||
<div class="outer close" role="button" aria-pressed="false" title="Go back">
|
||||
<div class="inner">
|
||||
<label class="labelclass">
|
||||
<span data-translate="back">Back</span>
|
||||
@ -603,7 +607,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="container-2" title="Remote Screenshare into OBS" onkeyup="enterPressedClick(event,this);" alt="Remote Screenshare into OBS" tabindex="4" role="button" aria-pressed="false" class="column columnfade pointer rounded card" style=" overflow-y: auto;">
|
||||
<div id="container-2" title="Remote Screenshare into OBS" onkeyup="enterPressedClick(event,this);" alt="Remote Screenshare into OBS" tabindex="1" role="button" aria-pressed="false" class="column columnfade pointer rounded card" style=" overflow-y: auto;">
|
||||
<h2 id="add_screen">
|
||||
<span data-translate="remote-screenshare-obs">Remote Screenshare into OBS</span>
|
||||
</h2>
|
||||
@ -676,7 +680,7 @@
|
||||
<div id="audioScreenCaptureDocs2" data-translate="1080p-screen-capture-guide">For achieving 1080p60 game-capture, <a href='https://docs.vdo.ninja/guides/how-to-screen-share-in-1080p' target="_blank">see here</a></div>
|
||||
|
||||
</div>
|
||||
<div class="outer close">
|
||||
<div class="outer close" title="Go back">
|
||||
<div class="inner">
|
||||
<label class="labelclass">
|
||||
<span data-translate="back">Back</span>
|
||||
@ -684,7 +688,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="container-4" tabindex="5" alt="Create Reusable Invite" onkeyup="enterPressedClick(event,this);" onclick="loadQR();" title="Create Reusable Invite" role="button" aria-pressed="false" class="column columnfade pointer rounded card" style=" overflow-y: auto;">
|
||||
<div id="container-4" tabindex="1" alt="Create Reusable Invite" onkeyup="enterPressedClick(event,this);" onclick="loadQR();" title="Create Reusable Invite" role="button" aria-pressed="false" class="column columnfade pointer rounded card" style=" overflow-y: auto;">
|
||||
<h2>
|
||||
<span data-translate="create-reusable-invite">Create Reusable Invite</span>
|
||||
</h2>
|
||||
@ -802,7 +806,7 @@
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
<div class="outer close">
|
||||
<div class="outer close" role="button" aria-pressed="false">
|
||||
<div class="inner">
|
||||
<label class="labelclass">
|
||||
<span data-translate="back">Back</span>
|
||||
@ -811,7 +815,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="dropButton" onclick="dropDownButtonAction()" title="More Options"><i class="las la-chevron-down" ></i></div>
|
||||
<div id="dropButton" onclick="dropDownButtonAction()" title="More Options" aria-hidden="true"><i class="las la-chevron-down" ></i></div>
|
||||
|
||||
<div id="container-5" class="column columnfade pointer rounded card hidden" style=" overflow-y: auto;">
|
||||
<h2><span data-translate="share-local-video-file">Stream Media File</span></h2>
|
||||
@ -976,27 +980,27 @@
|
||||
<br />
|
||||
<li>Youtube video
|
||||
<i class="lab la-youtube"></i>
|
||||
<a href="https://www.youtube.com/watch?v=QaA_6aOP9z8&list=PLWodc2tCfAH1l_LDvEyxEqFf42hOBKqQM&index=1" alt="Youtube video demoing VDO.Ninja">Demoing it here</a>
|
||||
<a title="Open a YouTube video demoing the basics of VDO.Ninja" href="https://www.youtube.com/watch?v=QaA_6aOP9z8&list=PLWodc2tCfAH1l_LDvEyxEqFf42hOBKqQM&index=1" alt="Youtube video demoing VDO.Ninja">Demoing it here</a>
|
||||
</li>
|
||||
|
||||
<br />
|
||||
<i>
|
||||
<a href="https://docs.vdo.ninja/common-errors-and-known-issues/known-issues" title="For more known issues, click here" target="_blank"><span style="color: red;">Known issues:</span></a>
|
||||
<a href="https://docs.vdo.ninja/common-errors-and-known-issues/known-issues" title="For a list of common or known issues, click here" target="_blank"><span style="color: red;">Known issues:</span></a>
|
||||
</i>
|
||||
<br />
|
||||
<li>
|
||||
If the video fails to load in OBS Studio, where the browser source remains blank, try disabling hardware-acceleration or
|
||||
<a href='https://docs.vdo.ninja/common-errors-and-known-issues/obs.ninja-doesnt-show-up-in-obs-or-is-choppy' title="link out to the vdo.ninja help guide for OBS Studio" target="_blank">refer to this help guide</a> for more.
|
||||
<a href='https://docs.vdo.ninja/common-errors-and-known-issues/obs.ninja-doesnt-show-up-in-obs-or-is-choppy' title="Click to link out to the VDO.Ninja help guide for common OBS Studio problems" target="_blank">refer to this help guide</a> for more.
|
||||
</li>
|
||||
<li>
|
||||
Samsung smartphones (A-series) may fail to publish video with some mobile browsers; try using Firefox Mobile or the native <a href='https://docs.vdo.ninja/getting-started/native-mobile-app-versions#android-download-link'>Android app</a> in these cases.
|
||||
Samsung smartphones (A-series) may fail to publish video with some mobile browsers; try using Firefox Mobile or the native <a href='https://docs.vdo.ninja/getting-started/native-mobile-app-versions#android-download-link' title="Info on the native app versions of VDO.Ninja">Android app</a> in these cases.
|
||||
</li>
|
||||
<br />
|
||||
<h4>
|
||||
<span style="color:#daad09;">Welcome to VDO Ninja! We've rebranded! Nothing else is changing and we're staying 100% free.</span>
|
||||
</h4>
|
||||
<br />
|
||||
🌻 Site last updated on July 25th. Development <a target="_blank" href='https://updates.vdo.ninja/'>updates are here.</a>
|
||||
🌻 Site last updated on July 25th. Development <a target="_blank" title="Open a page with recent VDO.Ninja development and feature updates" href='https://updates.vdo.ninja/'>updates are here.</a>
|
||||
<br />
|
||||
<br />
|
||||
<h3>
|
||||
@ -1007,11 +1011,11 @@
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
||||
<form method="post" onsubmit="setFormSubmitting()" style="display: none;">
|
||||
<form method="post" onsubmit="setFormSubmitting()" style="display: none;" aria-hidden="true">
|
||||
<input type="submit" />
|
||||
</form>
|
||||
<div id="credits" class="credits">
|
||||
<a href='https://github.com/steveseguin/vdoninja'>VDO.Ninja, by Steve Seguin</a>
|
||||
<div id="credits" class="credits" aria-hidden="true">
|
||||
<a href='https://github.com/steveseguin/vdoninja' aria-hidden="true">VDO.Ninja, by Steve Seguin</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="directorlayout" class="hidden directorsgrid">
|
||||
@ -2328,7 +2332,7 @@
|
||||
<input style="margin:0 10px;display:inline-block;padding: 8px 10px 6px 10px;" placeholder="Enter the remote OBS password here" />
|
||||
</div>
|
||||
<small style="margin: 20px 0 0 0;display:block;" >
|
||||
See the <a href="https://docs.vdo.ninja/advanced-settings/upcoming-parameters/and-obs" style="color:#314350; cursor:pointer;" target="_blank">documentation</a> for help on using the remote OBS controller
|
||||
See the <a href="https://docs.vdo.ninja/advanced-settings/upcoming-parameters/and-obs" style="cursor:pointer;" target="_blank">documentation</a> for help on using the remote OBS controller
|
||||
</small>
|
||||
<div id="debugRemoteOBSControl" class="hidden">
|
||||
</div>
|
||||
@ -2626,11 +2630,11 @@
|
||||
// session.hidehome = true; // If used, 'hide home' will make the landing page inaccessible, along with hiding a few go-home elements.
|
||||
// session.record = false; // uncomment to block users from being able to record via vdo.ninja's built in recording function
|
||||
</script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="lib-js" src="./lib.js?ver=897"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="lib-js" src="./lib.js?ver=904"></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=715"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="main-js" src="./main.js?ver=725"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
196
lib.js
196
lib.js
@ -1461,6 +1461,7 @@ session.sceneSync = function(UUID){
|
||||
}
|
||||
}
|
||||
|
||||
var TriggerOnNewDetails = false;
|
||||
session.obsStateSync = function(data2send=false, uid=false){
|
||||
if (session.disableOBS){return;}
|
||||
if (!window.obsstudio){return;} // this isn't OBS
|
||||
@ -1468,6 +1469,15 @@ session.obsStateSync = function(data2send=false, uid=false){
|
||||
|
||||
log(data2send);
|
||||
|
||||
if (data2send && (data2send == "sourceActive") && session.obsState.sourceActive){
|
||||
TriggerOnNewDetails = true;
|
||||
} else if (data2send && (data2send == "details") && session.obsState.sourceActive && TriggerOnNewDetails){
|
||||
if (session.obsState.details && session.obsState.details.currentScene && session.obsState.details.currentScene.name){
|
||||
session.obsState.details.thisScene = session.obsState.details.currentScene.name;
|
||||
TriggerOnNewDetails = false;
|
||||
}
|
||||
}
|
||||
|
||||
var needOptimize = false;
|
||||
if (session.obsState.visibility!==null){
|
||||
if (session.obsState.visibility===false){ /////////////////// I need to change tis to .state or whatever, anc catch/handle these events to update the buttons in the pop up menu
|
||||
@ -1575,7 +1585,7 @@ session.getOBSOptimization = function(msg, UUID){
|
||||
return msg;
|
||||
}
|
||||
|
||||
function getOBSDetails(){
|
||||
function getOBSDetails(callbackname = "details"){
|
||||
if (session.disableOBS){return false;}
|
||||
if (!window.obsstudio){return;}
|
||||
|
||||
@ -1609,7 +1619,7 @@ function getOBSDetails(){
|
||||
session.obsState.details[shortkey] = out;
|
||||
delete promises[key]
|
||||
if (!Object.keys(promises).length){
|
||||
session.obsStateSync("details");
|
||||
session.obsStateSync(callbackname);
|
||||
}
|
||||
});
|
||||
} catch(e){
|
||||
@ -1631,7 +1641,7 @@ function getOBSDetails(){
|
||||
});
|
||||
delete promises.main;
|
||||
if (!Object.keys(promises).length){
|
||||
session.obsStateSync("details");
|
||||
session.obsStateSync(callbackname);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1797,8 +1807,10 @@ function manageSceneState(data, UUID){ // incoming obs details
|
||||
|
||||
if (control >= 4){
|
||||
if (session.director || !session.roomid){
|
||||
if (session.obsControls!==false){
|
||||
getById("obscontrolbutton").classList.remove("hidden"); // so they get a tip.
|
||||
if (session.pcs[UUID].remote){
|
||||
if (session.obsControls!==false){
|
||||
getById("obscontrolbutton").classList.remove("hidden"); // so they get a tip.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2819,9 +2831,9 @@ function changeSceneLowBandwidth(state){
|
||||
if (!session.lowBitrateSceneChange){return;}
|
||||
if (!session.obsState){return;}
|
||||
try {
|
||||
if (session.obsState.visibility && session.obsState.details && session.obsState.details.currentScene){
|
||||
if (session.obsState.sourceActive && session.obsState.details && session.obsState.details.currentScene){
|
||||
changeSceneLowBandwidthRevert = session.obsState.details.currentScene.name || false;
|
||||
} else if (("visibility" in session.obsState) && !session.obsState.visibilit && session.obsState.details && session.obsState.details.currentScene){
|
||||
} else if (("sourceActive" in session.obsState) && !session.obsState.sourceActive && session.obsState.details && session.obsState.details.currentScene){
|
||||
if (session.obsState.details.currentScene.name !== session.lowBitrateSceneChange){
|
||||
return; // not the FML scene, nor are we visible, so we're not going to switch back. Assume the user has overtaken the setup.
|
||||
}
|
||||
@ -2955,6 +2967,9 @@ function setupIncomingScreenTracking(v, UUID){ // SCREEN element.
|
||||
if (document.getElementById("mainmenu")){
|
||||
var m = getById("mainmenu");
|
||||
m.remove();
|
||||
document.querySelectorAll(".hidden2").forEach(ele2=>{
|
||||
ele2.classList.remove("hidden2");
|
||||
});
|
||||
}
|
||||
|
||||
if (session.director){
|
||||
@ -3334,6 +3349,9 @@ function setupIncomingVideoTracking(v, UUID){ // video element.
|
||||
if (document.getElementById("mainmenu")){
|
||||
var m = getById("mainmenu");
|
||||
m.remove();
|
||||
document.querySelectorAll(".hidden2").forEach(ele2=>{
|
||||
ele2.classList.remove("hidden2");
|
||||
});
|
||||
}
|
||||
|
||||
if (session.director){
|
||||
@ -4325,7 +4343,6 @@ function updateMixerRun(e=false){ // this is the main auto-mixing code. It's a
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var i = null;
|
||||
var countOrder = 0;
|
||||
try{
|
||||
@ -7166,6 +7183,64 @@ function drawFrameMirrored(mirror=true, flip=false) {
|
||||
session.canvasCtx.restore();
|
||||
}
|
||||
|
||||
function motionDetection(video, threshold = 15, sensitivity=75){
|
||||
var targetSize = 16;
|
||||
|
||||
if (!video.motionDetector){
|
||||
video.motionDetector = {};
|
||||
video.motionDetector.canvas = document.createElement("canvas");
|
||||
video.motionDetector.canvas.width = targetSize;
|
||||
video.motionDetector.canvas.height = targetSize;
|
||||
try {
|
||||
video.motionDetector.ctx = video.motionDetector.canvas.getContext("2d", { willReadFrequently: true });
|
||||
} catch(e){
|
||||
video.motionDetector.ctx = video.motionDetector.canvas.getContext("2d");
|
||||
}
|
||||
video.motionDetector.previous = [];
|
||||
for (var y = 0; y < targetSize; y++) {
|
||||
for (var x = 0; x < targetSize; x++) {
|
||||
video.motionDetector.previous.push(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
var motionDetector = video.motionDetector;
|
||||
|
||||
motionDetector.ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight, 0, 0, targetSize, targetSize);
|
||||
var data = motionDetector.ctx.getImageData(0, 0, targetSize, targetSize).data;
|
||||
var matches = 0;
|
||||
for (var y = 0; y < targetSize; y++) {
|
||||
for (var x = 0; x < targetSize; x++) {
|
||||
var pos = y*targetSize+x;
|
||||
var pos2 = pos*3;
|
||||
var value = data[pos2] + data[pos2+1] + data[pos2+2]; // convert to to greyscale
|
||||
if (motionDetector.previous[pos] && Math.abs(motionDetector.previous[pos] - value) > sensitivity) {
|
||||
matches+=1;
|
||||
}
|
||||
motionDetector.previous[pos] = value;
|
||||
}
|
||||
}
|
||||
if (matches >= threshold){
|
||||
log("MOTION DETECTED: "+matches);
|
||||
if (window.obsstudio && window.obsstudio["setCurrentScene"]){
|
||||
if (!changeSceneEnabled){ // the bit cut scene change is already active.
|
||||
if (session.obsState && session.obsState.details && session.obsState.details.thisScene && session.obsState.details.currentScene){
|
||||
if (session.obsState.details.thisScene !== session.obsState.details.currentScene.name){ // don't trigger it multiple times; makes it hard to prep next scene
|
||||
window.obsstudio["setCurrentScene"](session.obsState.details.thisScene);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pokeIframeAPI('motion-detected', true, video.dataset.UUID || true);
|
||||
|
||||
if (session.infocus!==(video.dataset.UUID || true)){
|
||||
if (!session.layout){
|
||||
session.infocus = video.dataset.UUID || true;
|
||||
updateMixer();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setupCanvas() {
|
||||
log("SETUP CANVAS");
|
||||
if (session.canvas === null) {
|
||||
@ -11955,7 +12030,7 @@ function hangup2() {
|
||||
getById("screensharebutton").ariaPressed = "false";
|
||||
|
||||
|
||||
if (session.showDirector == false) {
|
||||
if (!session.showDirector) {
|
||||
getById("miniPerformer").innerHTML = '<button id="press2talk" onmousedown="event.preventDefault(); event.stopPropagation();" class="float" onclick="press2talk(true);" title="You can also enable the director`s Video Output afterwards by clicking the Setting`s button"><i class="las la-headset"></i><span data-translate="push-to-talk-enable"> enable director`s microphone or video<br />(only guests can see this feed)</span></button>';
|
||||
miniTranslate(getById("miniPerformer"));
|
||||
} else {
|
||||
@ -12336,7 +12411,7 @@ function getDetailedState(sid=false){
|
||||
} else {
|
||||
item.featured = false;
|
||||
}
|
||||
} else if (session.infocus && session.infocus===session.rpcs[UUID].streamID){
|
||||
} else if (session.infocus && session.infocus===UUID){
|
||||
item.featured = true;
|
||||
} else {
|
||||
item.featured = false;
|
||||
@ -12447,13 +12522,13 @@ function getDetailedState(sid=false){
|
||||
|
||||
|
||||
if (session.director){
|
||||
let featured = query("#highlightDirector[data-action-type='solo-video'], #container_director [data-action-type='solo-video']");
|
||||
let featured = document.querySelector("#highlightDirector[data-action-type='solo-video'], #container_director [data-action-type='solo-video']");
|
||||
if (featured && parseInt(featured.value)){
|
||||
streamList[session.streamID].featured = true;
|
||||
} else {
|
||||
streamList[session.streamID].featured = false;
|
||||
}
|
||||
} else if (session.infocus && session.infocus===session.streamID){
|
||||
} else if (session.infocus && session.infocus===true){
|
||||
streamList[session.streamID].featured = true;
|
||||
} else {
|
||||
streamList[session.streamID].featured = false;
|
||||
@ -16656,7 +16731,7 @@ async function toggleCoDirector(ele){
|
||||
if (session.password===false){
|
||||
getById("codirectorSettings_invite").value += "&password=false";
|
||||
} else{
|
||||
getById("codirectorSettings_invite").value += "&password";
|
||||
getById("codirectorSettings_invite").value += "&password="+session.password;
|
||||
}
|
||||
}
|
||||
|
||||
@ -16826,9 +16901,13 @@ async function createRoomCallback(passAdd, passAdd2) {
|
||||
|
||||
|
||||
formSubmitting = false;
|
||||
|
||||
var m = getById("mainmenu");
|
||||
m.remove();
|
||||
try {
|
||||
var m = getById("mainmenu");
|
||||
m.remove();
|
||||
document.querySelectorAll(".hidden2").forEach(ele2=>{
|
||||
ele2.classList.remove("hidden2");
|
||||
});
|
||||
} catch(e){}
|
||||
|
||||
getById("head1").className = 'hidden';
|
||||
getById("head2").className = 'hidden';
|
||||
@ -16869,7 +16948,7 @@ async function createRoomCallback(passAdd, passAdd2) {
|
||||
if (session.password==false){
|
||||
getById("codirectorSettings_invite").value += "&password=false";
|
||||
} else{
|
||||
getById("codirectorSettings_invite").value += "&password";
|
||||
getById("codirectorSettings_invite").value += "&password="+session.password;
|
||||
}
|
||||
}
|
||||
|
||||
@ -16956,12 +17035,12 @@ async function createRoomCallback(passAdd, passAdd2) {
|
||||
getById("roomsettingsbutton").classList.remove("hidden");
|
||||
}
|
||||
|
||||
if (session.showDirector == false) {
|
||||
if (!session.showDirector) { // if null or false, we want to show the solo link, since the director won't have their control box. The director will be visible in their solo link
|
||||
getById("miniPerformer").innerHTML = '<button id="press2talk" onmousedown="event.preventDefault(); event.stopPropagation();" class="float" onclick="press2talk(true);" title="You can also enable the director`s Video Output afterwards by clicking the Setting`s button"><i class="las la-headset"></i><span data-translate="push-to-talk-enable"> enable director`s microphone or video<br />(only guests can see this feed)</span></button>';
|
||||
miniTranslate(getById("miniPerformer"));
|
||||
getById("grabDirectorSoloLink").dataset.raw = "https://" + location.host + location.pathname + "?solo&sd&r=" + session.roomid + "&v="+session.streamID + passAdd2 + wss + token;
|
||||
getById("grabDirectorSoloLink").href = "https://" + location.host + location.pathname + "?solo&sd&r=" + session.roomid + "&v="+session.streamID + passAdd2 + wss + token;
|
||||
getById("grabDirectorSoloLink").innerText = "https://" + location.host + location.pathname + "?solo&sd&r=" + session.roomid + "&v="+session.streamID + passAdd2 + wss + token;
|
||||
getById("grabDirectorSoloLink").dataset.raw = "https://" + location.host + location.pathname + "?solo&r=" + session.roomid + "&v="+session.streamID + passAdd2 + wss + token;
|
||||
getById("grabDirectorSoloLink").href = "https://" + location.host + location.pathname + "?solo&r=" + session.roomid + "&v="+session.streamID + passAdd2 + wss + token;
|
||||
getById("grabDirectorSoloLink").innerText = "https://" + location.host + location.pathname + "?solo&r=" + session.roomid + "&v="+session.streamID + passAdd2 + wss + token;
|
||||
getById("grabDirectorSoloLinkParent").classList.remove("hidden");
|
||||
} else {
|
||||
getById("miniPerformer").innerHTML = '<button id="press2talk" onmousedown="event.preventDefault(); event.stopPropagation();" class="float" onclick="press2talk(true);" title="You can also enable the director`s Video Output afterwards by clicking the Setting`s button"><i class="las la-headset"></i><span data-translate="push-to-talk-enable-2"> enable director`s microphone or video</span></button>';
|
||||
@ -22078,6 +22157,7 @@ async function grabVideo(quality = 0, eleName = 'previewWebcam', selector = "sel
|
||||
document.getElementById("gowebcam").disabled = false;
|
||||
//document.getElementById("gowebcam").innerHTML = getTranslation("start");
|
||||
miniTranslate(document.getElementById("gowebcam"),"start");
|
||||
document.getElementById("gowebcam").focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -22461,6 +22541,7 @@ async function grabVideo(quality = 0, eleName = 'previewWebcam', selector = "sel
|
||||
document.getElementById("gowebcam").disabled = false;
|
||||
//document.getElementById("gowebcam").innerHTML = getTranslation("start");
|
||||
miniTranslate(document.getElementById("gowebcam"),"start");
|
||||
document.getElementById("gowebcam").focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -23625,6 +23706,7 @@ function senderAudioUpdate(callback=false, tracks=false){
|
||||
if (document.getElementById("gowebcam").dataset.ready && (document.getElementById("gowebcam").dataset.ready=="true")){
|
||||
document.getElementById("gowebcam").disabled = false;
|
||||
miniTranslate(document.getElementById("gowebcam"),"start");
|
||||
document.getElementById("gowebcam").focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24980,6 +25062,9 @@ function updateReshareLink(){
|
||||
try{
|
||||
var m = getById("mainmenu");
|
||||
m.remove();
|
||||
document.querySelectorAll(".hidden2").forEach(ele2=>{
|
||||
ele2.classList.remove("hidden2");
|
||||
});
|
||||
} catch (e){}
|
||||
|
||||
var added = "";
|
||||
@ -29508,6 +29593,7 @@ function setupWebcamSelection(miconly=false) {
|
||||
miniTranslate(document.getElementById("gowebcam"),"start");
|
||||
document.getElementById("gowebcam").dataset.audioready = "true";
|
||||
document.getElementById("gowebcam").dataset.ready = "true";
|
||||
document.getElementById("gowebcam").focus();
|
||||
setTimeout(function(){updateForceRotate();},1000);
|
||||
|
||||
if (session.autostart) {
|
||||
@ -29535,6 +29621,7 @@ function setupWebcamSelection(miconly=false) {
|
||||
if (document.getElementById("gowebcam").dataset.audioready == "true"){
|
||||
document.getElementById("gowebcam").disabled = false;
|
||||
miniTranslate(document.getElementById("gowebcam"),"start");
|
||||
document.getElementById("gowebcam").focus();
|
||||
//document.getElementById("gowebcam").innerHTML = getTranslation("start");
|
||||
}
|
||||
}
|
||||
@ -30019,6 +30106,7 @@ function previewWebcam(miconly=false) {
|
||||
document.getElementById("gowebcam").disabled = false;
|
||||
//document.getElementById("gowebcam").innerHTML = getTranslation("start");
|
||||
miniTranslate(document.getElementById("gowebcam"),"start");
|
||||
document.getElementById("gowebcam").focus();
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -33416,7 +33504,7 @@ session.onTrack = function(event, UUID){
|
||||
} else {
|
||||
updateIncomingVideoElement(UUID, false, true);
|
||||
}
|
||||
updateIncomingVideoElement(UUID); // session.rpcs[UUID].videoElement.srcObject = session.rpcs[UUID].streamSrc;
|
||||
// updateIncomingVideoElement(UUID); // session.rpcs[UUID].videoElement.srcObject = session.rpcs[UUID].streamSrc;
|
||||
setTimeout(function(){updateMixer();},1);
|
||||
} catch(e){}
|
||||
};
|
||||
@ -33588,6 +33676,15 @@ function updateIncomingVideoElement(UUID, video=true, audio=true){
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (session.motionSwitch && !session.rpcs[UUID].motionDetectionInterval){
|
||||
session.rpcs[UUID].motionDetectionInterval = setTimeout(function(){
|
||||
setInterval(function(){
|
||||
motionDetection(session.rpcs[UUID].videoElement, session.motionSwitch);
|
||||
},400);
|
||||
},2000);
|
||||
}
|
||||
|
||||
}
|
||||
if (audio){
|
||||
updateIncomingAudioElement(UUID) // do the same for audio now.
|
||||
@ -36319,6 +36416,7 @@ async function whepIn(whepInput=false,whepInputToken=false, UUID=false){ // PLAY
|
||||
session.rpcs[UUID].lockedVideoBitrate = false; // doesn't do anything
|
||||
session.rpcs[UUID].lockedAudioBitrate = false;
|
||||
session.rpcs[UUID].manualBandwidth = false; // doesn't do anything, except maybe help keep track of pause/play states
|
||||
session.rpcs[UUID].motionDetectionInterval = false;
|
||||
}
|
||||
var config = {...session.configuration};
|
||||
|
||||
@ -37181,28 +37279,40 @@ function setupCommands(){
|
||||
updateMixer();
|
||||
return true;
|
||||
} else if (session.layouts && session.layouts[value]){
|
||||
session.layout = session.layouts[value];
|
||||
pokeIframeAPI("layout-updated", session.layout);
|
||||
pokeIframeAPI("layout-index", value+1);
|
||||
if (session.director){
|
||||
var combined = {};
|
||||
for (var i=0;i<session.layout.length;i++){
|
||||
if (!session.layout[i]){continue;}
|
||||
if (!("slot" in session.layout[i])){
|
||||
continue;
|
||||
}
|
||||
var slot = document.querySelector("div.slotsbar[data-slot='"+(parseInt(session.layout[i].slot)+1)+"']") || false
|
||||
if (!slot){continue;}
|
||||
var streamID = slot.dataset.sid;
|
||||
combined[streamID] = session.layout[i];
|
||||
try {
|
||||
console.log(session.layouts);
|
||||
session.layout = session.layouts[value];
|
||||
pokeIframeAPI("layout-updated", session.layout);
|
||||
pokeIframeAPI("layout-index", value+1);
|
||||
if (session.director){
|
||||
var combined = {};
|
||||
for (var i=0;i<session.layout.length;i++){
|
||||
if (!session.layout[i]){continue;}
|
||||
if (!("slot" in session.layout[i])){
|
||||
continue;
|
||||
}
|
||||
var slot = document.querySelector("div.slotsbar[data-slot='"+(parseInt(session.layout[i].slot)+1)+"']") || false
|
||||
if (!slot){
|
||||
console.error("Slot target not found?");
|
||||
continue;
|
||||
}
|
||||
var streamID = slot.dataset.sid;
|
||||
combined[streamID] = session.layout[i];
|
||||
|
||||
}
|
||||
session.layout = combined;
|
||||
console.log("issuing layout:");
|
||||
console.log(session.layout);
|
||||
issueLayout(session.layout, "0");
|
||||
}
|
||||
session.layout = combined;
|
||||
issueLayout(combined, "0");
|
||||
} catch(e){
|
||||
console.error(e);
|
||||
}
|
||||
updateMixer();
|
||||
return true;
|
||||
} else {
|
||||
console.error("no layout found");
|
||||
console.log(session.layouts);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -37680,6 +37790,11 @@ addEventToAll(".column", 'click', function(e, ele) {
|
||||
});
|
||||
addEventToAll(".close", 'click', function(e, ele) {
|
||||
cleanupMediaTracks();
|
||||
|
||||
document.querySelectorAll(".hidden2").forEach(ele2=>{
|
||||
ele2.classList.remove("hidden2");
|
||||
});
|
||||
|
||||
ele.style.display = "none";
|
||||
mapToAll(".container-inner", function(target) {
|
||||
target.style.display = "none";
|
||||
@ -37699,6 +37814,11 @@ addEventToAll(".column", 'animationend', function(e, ele) {
|
||||
mapToAll(".close", function(target) {
|
||||
target.style.display = "block";
|
||||
}, ele);
|
||||
document.querySelectorAll("#header, #miniTaskBarm, #credits, .columnfade").forEach(ele2=>{
|
||||
if (ele2!==ele){
|
||||
ele2.classList.add("hidden2");
|
||||
}
|
||||
});
|
||||
mapToAll(".container-inner", function(target) {
|
||||
target.style.display = "block";
|
||||
}, ele);
|
||||
|
||||
11
main.css
11
main.css
@ -808,6 +808,7 @@ hr {
|
||||
#gridlayout, #directorlayout {
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
justify-items: stretch;
|
||||
border: 0;
|
||||
@ -1537,6 +1538,9 @@ body {
|
||||
opacity: 1;
|
||||
transition: opacity .1s linear;
|
||||
scrollbar-color:#666 #201c29;
|
||||
display:flex;
|
||||
flex-direction: column;
|
||||
position: fixed;
|
||||
}
|
||||
body.darktheme{
|
||||
background-color: var(--dark-background-color);
|
||||
@ -3151,6 +3155,13 @@ video::-webkit-media-controls-panel {
|
||||
height: 0px;
|
||||
opacity: 0;
|
||||
}
|
||||
.hidden2 {
|
||||
display: none !important;
|
||||
visibility: hidden;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
opacity: 0;
|
||||
}
|
||||
.grabLinks a:visited {
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
36
main.js
36
main.js
@ -744,6 +744,11 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.lowBitrateCutoff = parseInt(urlParams.get('bitratecutoff')) || parseInt(urlParams.get('bitcut')) || 300; // low bitrate cut off.
|
||||
}
|
||||
|
||||
if (urlParams.has('motionswitch') || urlParams.has('motiondetection')) { // switch OBS to this scene when there is motion, and "solo view" this video in the VDO.Ninja auto-mixer, if used
|
||||
session.motionSwitch = parseInt(urlParams.get('motionswitch')) || parseInt(urlParams.get('motiondetection')) || 15; // threshold of motion needed to trigger
|
||||
}
|
||||
|
||||
|
||||
if (urlParams.has('locked')) {
|
||||
session.locked = urlParams.get('locked');
|
||||
|
||||
@ -771,6 +776,19 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.rotate = parseInt(session.rotate);
|
||||
}
|
||||
|
||||
if (urlParams.has("rotatewindow") || urlParams.has("rotatepage")){
|
||||
let rotateThis = parseInt(urlParams.get("rotatewindow")) || parseInt(urlParams.get("rotatepage")) || 90;
|
||||
if (rotateThis==270){
|
||||
document.body.setAttribute( "style", "transform: rotate(270deg);position: absolute;top: 100vh;left: 0;height: 100vw;width: 100vh;transform-origin: 0 0;");
|
||||
} else if (rotateThis==90){
|
||||
document.body.setAttribute( "style", "transform: rotate(90deg);position: absolute;top: 0;left: 100vw;height: 100vw;width: 100vh;transform-origin: 0 0;");
|
||||
} else if (rotateThis==180){
|
||||
document.body.setAttribute( "style", "transform: rotate(180deg);position: absolute;top: 100vh;left: 100vw;height: 100vh;width: 100vw;transform-origin: 0 0;");
|
||||
} else {
|
||||
document.body.setAttribute( "style", "");
|
||||
}
|
||||
}
|
||||
|
||||
if (urlParams.has('facing') ) {
|
||||
session.facingMode = urlParams.get('facing') || false;
|
||||
}
|
||||
@ -1065,6 +1083,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
|
||||
if (urlParams.has('layout')) {
|
||||
session.accept_layouts = true;
|
||||
try {
|
||||
session.layout = JSON.parse(decodeURIComponent(urlParams.get('layout'))) || JSON.parse(urlParams.get('layout')) || {};
|
||||
} catch(e){
|
||||
@ -2467,6 +2486,10 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
if (urlParams.has('chroma')) {
|
||||
log("Chroma ENABLED");
|
||||
getById("main").style.backgroundColor = "#" + (urlParams.get('chroma') || "0F0");
|
||||
//try {
|
||||
// document.querySelector('meta[name="theme-color"]')?.setAttribute('content', "#" + (urlParams.get('chroma') || "0F0")); .. meh
|
||||
//} catch(e){}
|
||||
//const ogColor = document.querySelector('meta[name="theme-color"]')?.getAttribute('content');
|
||||
} // else if (window.obsstudio || (navigator.userAgent.toLowerCase().indexOf(' electron/') > -1)){
|
||||
// getById("main").style.backgroundColor = "rgba(0,0,0,0)";
|
||||
//}
|
||||
@ -4086,6 +4109,14 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.wss = "wss://" + session.wss;
|
||||
}
|
||||
}
|
||||
} else if (urlParams.has('wss2')) {
|
||||
session.wssSetViaUrl = true;
|
||||
if (urlParams.get('wss2')) {
|
||||
session.wss = urlParams.get('wss2');
|
||||
if (!session.wss.startsWith("wss://")){
|
||||
session.wss = "wss://" + session.wss;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (urlParams.has("bypass")){
|
||||
@ -4735,6 +4766,11 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
if (urlParams.get('auth')) {
|
||||
session.auth = urlParams.get('auth');
|
||||
}
|
||||
|
||||
if (urlParams.has('waitimage')){
|
||||
session.waitImage = urlParams.get('waitimage') || false;
|
||||
}
|
||||
|
||||
@ -2610,9 +2610,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (e.data.action === "layout-updated"){
|
||||
console.log(e.data);
|
||||
}
|
||||
|
||||
if (e.data.action === "layout-index"){
|
||||
if ("value" in e.data){
|
||||
console.log(e.data);
|
||||
var idx = parseInt(e.data.value) || 0;
|
||||
if (!idx){
|
||||
var ele = document.getElementById("automix");
|
||||
|
||||
@ -317,10 +317,88 @@
|
||||
</div>
|
||||
<script>
|
||||
|
||||
|
||||
var domain = "./";
|
||||
var urlParams = new URLSearchParams(window.location.search);
|
||||
var iframe = document.createElement("iframe");
|
||||
|
||||
|
||||
function changeParam(url, paramName, paramValue) {
|
||||
paramName = paramName.replace("?", "");
|
||||
var qind = url.indexOf('?');
|
||||
url = url.replace("?", "&");
|
||||
var params = url.substring(qind + 1).split('&');
|
||||
var query = '';
|
||||
var match = false;
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var tokens = params[i].split('=');
|
||||
var name = tokens[0];
|
||||
var value = "";
|
||||
if (tokens.length > 1 && tokens[1] !== '') {
|
||||
value = tokens[1];
|
||||
}
|
||||
|
||||
if (name == paramName) {
|
||||
if (match) {
|
||||
continue;
|
||||
} // already matched the first time.
|
||||
match = true;
|
||||
value = paramValue;
|
||||
}
|
||||
if (value !== "") {
|
||||
value = '=' + value;
|
||||
}
|
||||
|
||||
if (query == '') {
|
||||
query = "?" + name + value;
|
||||
} else {
|
||||
query = query + '&' + name + value;
|
||||
}
|
||||
}
|
||||
return url.substring(0, qind) + query;
|
||||
}
|
||||
function updateURL(param, force = false, cleanUrl = false) {
|
||||
|
||||
param = param.replace("?", "");
|
||||
var para = param.split('=');
|
||||
if (cleanUrl) {
|
||||
if (history.pushState) {
|
||||
var href = new URL(cleanUrl);
|
||||
if (para.length == 1) {
|
||||
href = changeParam(cleanUrl, para[0], "");
|
||||
} else {
|
||||
href = changeParam(cleanUrl, para[0], para[1]);
|
||||
}
|
||||
window.history.pushState({path: href.toString()}, '', href.toString());
|
||||
}
|
||||
} else if (!(urlParams.has(para[0]))) { // don't need to replace as it doesn't exist.
|
||||
if (history.pushState) {
|
||||
var href = window.location.href;
|
||||
href = href.replace("??", "?");
|
||||
var arr = href.split('?');
|
||||
var newurl;
|
||||
if (arr.length > 1 && arr[1] !== '') {
|
||||
newurl = href + '&' + param;
|
||||
} else {
|
||||
newurl = href + '?' + param;
|
||||
}
|
||||
|
||||
window.history.pushState({path: newurl.toString()}, '', newurl.toString());
|
||||
}
|
||||
} else if (force) {
|
||||
if (history.pushState) {
|
||||
var href = new URL(window.location.href);
|
||||
if (para.length == 1) {
|
||||
href = changeParam(window.location.href, para[0], "");
|
||||
} else {
|
||||
href = changeParam(window.location.href, para[0], para[1]);
|
||||
}
|
||||
window.history.pushState({path: href.toString()}, '', href.toString());
|
||||
}
|
||||
}
|
||||
urlParams = new URLSearchParams(window.location.search);
|
||||
}
|
||||
|
||||
if (urlParams.has("rotate")){
|
||||
document.querySelector("#rotation").value = urlParams.get("rotate") || 0;
|
||||
} else if (localStorage.getItem('rotation')){
|
||||
@ -342,18 +420,41 @@ if (localStorage.getItem('sourceType')){
|
||||
}
|
||||
|
||||
if (localStorage.getItem('iframeURL') || urlParams.has("link")){
|
||||
document.querySelector("#iframeURL").value = decodeURIComponent(urlParams.get("link") || "") || localStorage.getItem('iframeURL') || "";
|
||||
try {
|
||||
document.querySelector("#iframeURL").value = decodeURIComponent(urlParams.get("link") || "") || localStorage.getItem('iframeURL') || "";
|
||||
} catch(e){
|
||||
document.querySelector("#iframeURL").value = urlParams.get("link") || localStorage.getItem('iframeURL') || "";
|
||||
}
|
||||
}
|
||||
if (localStorage.getItem('iframeURL_twitch') || urlParams.has("twitch")){
|
||||
document.querySelector("#iframeURL_twitch").value = decodeURIComponent(urlParams.get("twitch") || "") || localStorage.getItem('iframeURL_twitch') || "";
|
||||
try {
|
||||
document.querySelector("#iframeURL_twitch").value = decodeURIComponent(urlParams.get("twitch") || "") || localStorage.getItem('iframeURL_twitch') || "";
|
||||
} catch(e){
|
||||
document.querySelector("#iframeURL_twitch").value = urlParams.get("twitch") || localStorage.getItem('iframeURL_twitch') || "";
|
||||
}
|
||||
}
|
||||
if (localStorage.getItem('iframeURL_youtube') || urlParams.has("youtube")){
|
||||
document.querySelector("#iframeURL").value = decodeURIComponent(urlParams.get("youtube") || "") || localStorage.getItem('iframeURL_youtube') || "";
|
||||
try {
|
||||
document.querySelector("#iframeURL").value = decodeURIComponent(urlParams.get("youtube") || "") || localStorage.getItem('iframeURL_youtube') || "";
|
||||
} catch(e){
|
||||
document.querySelector("#iframeURL").value = urlParams.get("youtube") || localStorage.getItem('iframeURL_youtube') || "";
|
||||
}
|
||||
}
|
||||
|
||||
var menuOffset = "70px";
|
||||
|
||||
if ( urlParams.has("hidemenu") || urlParams.has("hide") || urlParams.has("hidebar")){
|
||||
container.classList.add("hidden");
|
||||
menuOffset = "0px";
|
||||
}
|
||||
|
||||
|
||||
loadPage();
|
||||
|
||||
|
||||
|
||||
function hidebar(){
|
||||
// updateURL("hidemenu");
|
||||
container.classList.add("hidden");
|
||||
menuOffset = "0px";
|
||||
loadPage();
|
||||
@ -562,14 +663,7 @@ async function loadPage(){
|
||||
urlEdited = urlEdited.replace(/\?/g, "&");
|
||||
urlEdited = urlEdited.replace(/\&/, "?");
|
||||
|
||||
if (urlEdited !== window.location.search){
|
||||
if (!urlParams.has("link")){
|
||||
urlEdited += "&link="+ encodeURIComponent(iframeURL);
|
||||
}
|
||||
urlEdited = urlEdited.replace(/\?/g, "&");
|
||||
urlEdited = urlEdited.replace(/\&/, "?");
|
||||
window.history.pushState({path: urlEdited.toString()}, '', urlEdited.toString());
|
||||
}
|
||||
updateURL("link="+ encodeURIComponent(iframeURL), true);
|
||||
|
||||
iframe.allow = "encrypted-media;sync-xhr;usb;web-share;cross-origin-isolated;accelerometer;midi;geolocation;autoplay;camera;microphone;fullscreen;picture-in-picture;display-capture;";
|
||||
iframe.src = iframeURL;
|
||||
@ -586,6 +680,9 @@ function rotatePage(){
|
||||
var rotate = document.querySelector("#rotation").value || 0;
|
||||
var flip = document.querySelector("#transform").value;
|
||||
|
||||
updateURL("rotate="+rotate, true);
|
||||
updateURL("flip="+flip, true);
|
||||
|
||||
localStorage.setItem('iframeURL', document.getElementById('iframeURL').value);
|
||||
localStorage.setItem('rotation', document.getElementById('rotation').value);
|
||||
//localStorage.setItem('backgroundColor', document.getElementById('backgroundColor').value);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user