mirror of
https://github.com/eliasstepanik/vdo.ninja.git
synced 2026-01-11 13:48:38 +00:00
bug fixes and added more audio codecs
This commit is contained in:
parent
13d5e80d7c
commit
ea52a3d164
@ -510,7 +510,7 @@
|
||||
user-select: none;
|
||||
}
|
||||
.pressed>.group{
|
||||
border: solid 2px black;
|
||||
box-shadow: inset 2px 2px 10px #0007, inset -2px -2px 10px #0007;
|
||||
background-color: #276022aa;
|
||||
}
|
||||
button.pressed {
|
||||
|
||||
@ -19,7 +19,6 @@ h1 {
|
||||
font-size: 1rem;
|
||||
padding: 10px;
|
||||
position: relative;
|
||||
user-select: none;
|
||||
background: #d0d0d0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
51
index.html
51
index.html
@ -57,7 +57,7 @@
|
||||
<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=229" />
|
||||
<link rel="stylesheet" href="./main.css?ver=235" />
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/adapter.js"></script>
|
||||
<style id="lightbox-animations" type="text/css"></style>
|
||||
<!-- <link rel="manifest" href="manifest.json" /> -->
|
||||
@ -73,7 +73,7 @@
|
||||
<meta name="apple-mobile-web-app-status-bar" content="#db4938" />
|
||||
-->
|
||||
</head>
|
||||
<body id="main" class="hidden">
|
||||
<body id="main" class="hidden" onload="main()">
|
||||
<span itemprop="image" itemscope itemtype="image/png">
|
||||
<link itemprop="url" href="./media/vdoNinja_logo_full.png" />
|
||||
</span>
|
||||
@ -81,9 +81,9 @@
|
||||
<span itemprop="thumbnail" itemscope itemtype="http://schema.org/ImageObject">
|
||||
<link itemprop="url" href="./media/vdoNinja_logo_full.png" />
|
||||
</span>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/CodecsHandler.js?ver=43"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/CodecsHandler.js?ver=45"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./thirdparty/aes.js"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./webrtc.js?ver=544"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" src="./webrtc.js?ver=549"></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">
|
||||
@ -109,6 +109,7 @@
|
||||
data-drag="1"
|
||||
onclick="copyFunction(this, event)"
|
||||
class="task grabLinks"
|
||||
data-menu="context-menu"
|
||||
style="font-weight: bold; color: #afa !important; cursor: grab; background-color: #0000; font-size: 115%; min-width: 335px; max-width: 800px;"
|
||||
></a>
|
||||
<i class="las la-paperclip" style="color: #DDD;" onclick="copyFunction(document.getElementById('reshare'), event);" onmouseover="this.style.cursor='pointer'"></i>
|
||||
@ -179,7 +180,9 @@
|
||||
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;">
|
||||
<i id="fullscreenPageToggle" onmousedown="event.preventDefault(); event.stopPropagation();" class="toggleSize las la-expand-arrows-alt my-float"></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">
|
||||
<i id="settingstoggle" class="toggleSize las la-sync-alt my-float"></i>
|
||||
</div>
|
||||
@ -882,7 +885,7 @@
|
||||
<font style="color:#daad09;">Welcome to VDO Ninja! We've rebranded! Nothing else is changing and we're staying 100% free.</font>
|
||||
</h4>
|
||||
<br />
|
||||
🚀🚀 Site updated November 18th, 2022 to v22. If having new sudden issues, please try clearing your browser's cache, including refreshing the cache within any OBS browser source. You can also still access the previous version, which <a href="https://vdo.ninja/v21/">is hosted here</a>. Development <a target="_blank" href='https://updates.vdo.ninja/'>updates are here.</a>
|
||||
🚀🚀 Site last updated on Nov.18th (<a target='_blank' href='https://docs.vdo.ninja/releases/v22'>v22 release notes</a>). You can also still access the previous version, which <a href="https://vdo.ninja/v21/">is hosted here</a>. Development <a target="_blank" href='https://updates.vdo.ninja/'>updates are here.</a>
|
||||
<br />
|
||||
<br />
|
||||
<h3>
|
||||
@ -943,7 +946,7 @@
|
||||
<div class='directorBlock'>
|
||||
<h2 title="Invite a guest or camera source to publish into the group room" style="margin-top: 5px;"><i class="las la-video director-link-icons" ></i><span data-translate="invite-a-guest">INVITE A GUEST</span></h2>
|
||||
<span style="margin:5px; line-height: 1.6;" data-translate='invite-users-to-join'>Guests can use the link to join the group room</span>
|
||||
<a onclick='copyFunction(this,event)' id="director_block_1" class='task grabLinks' style='cursor:copy;background-color: #0003;'></a>
|
||||
<a onclick='copyFunction(this,event)' id="director_block_1" class='task grabLinks' data-menu="context-menu" style='cursor:copy;background-color: #0003;'></a>
|
||||
<span style="display:block;">
|
||||
<span style="bottom: 0; margin: 0 0 0 10px; top: 22px; position: relative; display:inline-block; max-width: 45%;">
|
||||
<label class="switch" title="If disabled, the invited guest will not be able to see or hear anyone in the room.">
|
||||
@ -962,7 +965,7 @@
|
||||
<div class='directorBlock' style="background-color: var(--green-accent);" >
|
||||
<h2 title="Use this link in the OBS Browser Source to capture the video or audio" style="margin-left: 1px;margin-top: 5px;"><i class="las la-th-large director-link-icons" style="margin-right: 6px;" ></i> <span data-translate="capture-a-group-scene">CAPTURE A GROUP SCENE</span></h2>
|
||||
<span style="margin:5px; line-height: 1.6;" data-translate='this-is-obs-browser-source-link'>Use in OBS or other studio software to capture the group video mix</span>
|
||||
<a onclick='copyFunction(this,event)' data-drag="1" draggable="true" id="director_block_3" class='task grabLinks' style='cursor:grab;background-color: #0003;'></a>
|
||||
<a onclick='copyFunction(this,event)' data-drag="1" draggable="true" id="director_block_3" data-menu="context-menu" class='task grabLinks' style='cursor:grab;background-color: #0003;'></a>
|
||||
<span style="display:block;">
|
||||
<span style="bottom: 0; margin: 0 0 0 10px; top: 22px; position: relative; display:inline-block; max-width: 45%;">
|
||||
<label class="switch" title="If disabled, you must manually add a video to a scene for it to appear.">
|
||||
@ -1318,8 +1321,8 @@
|
||||
</div>
|
||||
|
||||
<div id="hiddenElements"></div>
|
||||
<div id="overlayClockContainer" data-initial="600" class="hidden"><span id="overlayClock"></span></div>
|
||||
<div id="overlayClockContainer2" data-initial="600" class="hidden"><span id="overlayClock2"></span></div>
|
||||
<div id="overlayClockContainer" data-menu='context-menu-clock' data-initial="600" class="hidden"><span id="overlayClock"></span></div>
|
||||
<div id="overlayClockContainer2" data-menu='context-menu-clock' data-initial="600" class="hidden"><span id="overlayClock2"></span></div>
|
||||
<div id="overlayMsgs" onclick="this.innerHTML = '';" style="display:none"></div>
|
||||
<div id="bigPlayButton" onclick="this.innerHTML = '';" style="display:none"></div>
|
||||
<div id="controls_blank" style="display: none;">
|
||||
@ -1502,7 +1505,7 @@
|
||||
</button>
|
||||
|
||||
|
||||
<span class="hidden advanced" data-cluster="2">
|
||||
<span class="hidden advanced audiocluster1" data-cluster="2">
|
||||
|
||||
<button style="width:35.2px;" data-action-type="add-channel" title="Set to Audio Channel 1" onclick="changeChannelOffset(this.dataset.UUID, 0);">
|
||||
<span >C1</span>
|
||||
@ -1515,7 +1518,7 @@
|
||||
</button>
|
||||
</span>
|
||||
|
||||
<span class="hidden advanced" data-cluster="2">
|
||||
<span class="hidden advanced audiocluster2" data-cluster="2">
|
||||
|
||||
<button style="width:35.2px;" data-action-type="add-channel" title="Set to Audio Channel 4" onclick="changeChannelOffset(this.dataset.UUID,3);">
|
||||
<span >C4</span>
|
||||
@ -1528,7 +1531,7 @@
|
||||
</button>
|
||||
</span>
|
||||
|
||||
<span class="hidden advanced" data-cluster="2">
|
||||
<span class="hidden advanced groupcluster1" data-cluster="2">
|
||||
<button style="width:35.2px;" data-action-type="toggle-group" data-group="1" title="Add/remove from group 1" onclick="changeGroup(this);">
|
||||
<span >G1</span>
|
||||
</button>
|
||||
@ -1540,7 +1543,7 @@
|
||||
</button>
|
||||
</span>
|
||||
|
||||
<span class="hidden advanced" data-cluster="2">
|
||||
<span class="hidden advanced groupcluster2" data-cluster="2">
|
||||
|
||||
<button style="width:35.2px;" data-action-type="toggle-group" data-group="4" title="Add/remove from group 4" onclick="changeGroup(this);">
|
||||
<span >G4</span>
|
||||
@ -1765,7 +1768,7 @@
|
||||
<button id="pIpStartButton" style="width: 135px; background-color:#EFEFEF;padding:20px;text-align:center;display:none;"><b>Preview PiP VIdeo</b><br /><i style="padding:5px; font-size:300%;color:black;" class="las la-compress-arrows-alt"></i></button>
|
||||
|
||||
|
||||
<div class="hidden" id="grabDirectorSoloLinkParent" title="The solo view link of the Director's video."><i class="las la-user"></i> Director's solo link:<a onclick="copyFunction(this,event)" data-drag="1" draggable="true" id="grabDirectorSoloLink" class="task" ></a></div>
|
||||
<div class="hidden" id="grabDirectorSoloLinkParent" title="The solo view link of the Director's video."><i class="las la-user"></i> Director's solo link:<a onclick="copyFunction(this,event)" data-drag="1" draggable="true" id="grabDirectorSoloLink" data-menu="context-menu" class="task" ></a></div>
|
||||
<br />
|
||||
<button onclick="toggleSettings()" class="toggleSettings"><i class="chevron right" style="font-size:150%;top:3px;position:relative;"></i> <b><span data-translate="close-settings">Close Settings</span></b></button>
|
||||
|
||||
@ -1865,6 +1868,16 @@
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<nav id="context-menu-clock" class="context-menu">
|
||||
<ul class="context-menu__items">
|
||||
<li class="context-menu__item">
|
||||
<a href="#" class="context-menu__link" data-action="pip-clock">
|
||||
<i class="las la-external-link"></i>
|
||||
<span data-translate="detach-clock2-pip">Pop-out clock toggle</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<nav id="context-menu-video" class="context-menu">
|
||||
<ul class="context-menu__items">
|
||||
<li class="context-menu__item">
|
||||
@ -2206,7 +2219,7 @@
|
||||
</u>
|
||||
</div>
|
||||
<div id="meshcastMenu" class="hidden">
|
||||
Publishing Region: <select name="edgelist" id="edgelist" onchange="selectMeshcast(this);" title="Select a location that is closest to both you and your audience."></select>
|
||||
Meshcast publishing region: <select name="edgelist" id="edgelist" onchange="selectMeshcast(this);" title="Select a location that is closest to both you and your audience."></select>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
@ -2220,7 +2233,7 @@
|
||||
|
||||
|
||||
var session = WebRTC.Media; // session is a required global variable if configuring manually. Run before loading main.js but after webrtc.js.
|
||||
session.version = "22.7"; // nov 18th
|
||||
session.version = "22.9"; // nov 18th
|
||||
session.streamID = session.generateStreamID(); // randomly generates a streamID for this session. You can set your own programmatically if needed
|
||||
|
||||
session.defaultPassword = "someEncryptionKey123"; // Change this password if self-deploying for added security/privacy
|
||||
@ -2292,11 +2305,11 @@
|
||||
// session.defaultBackgroundImages = ["./media/bg_sample1.webp", "./media/bg_sample2.webp"]; // for &effects=5 (virtual backgrounds)
|
||||
// session.hidehome = true; // If used, 'hide home' will make the landing page inaccessible, along with hiding a few go-home elements.
|
||||
</script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="lib-js" src="./lib.js?ver=554"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="lib-js" src="./lib.js?ver=572"></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=485"></script>
|
||||
<script type="text/javascript" crossorigin="anonymous" id="main-js" src="./main.js?ver=497"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
33
main.css
33
main.css
@ -119,7 +119,10 @@ tr {
|
||||
th {
|
||||
padding:4px;
|
||||
}
|
||||
|
||||
.preSelectButton {
|
||||
margin: 4px 0 4px 8px;
|
||||
padding: 1px 4px;
|
||||
}
|
||||
.meter {
|
||||
display: inline-block;
|
||||
width: 0px;
|
||||
@ -356,12 +359,21 @@ button.white:active {
|
||||
text-align: center;
|
||||
position: fixed;
|
||||
overflow-wrap: anywhere;
|
||||
pointer-events: none;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
#overlayClock{
|
||||
padding:2px 20px;
|
||||
background-color: #0009;
|
||||
}
|
||||
#overlayClock video {
|
||||
width: calc(22vh + 22vw / 2);
|
||||
max-width: 100%;
|
||||
max-height:25%;
|
||||
}
|
||||
#overlayClock:empty{
|
||||
display:none;
|
||||
}
|
||||
#overlayClockContainer2{
|
||||
margin: 0 auto;
|
||||
background-color: #0000;
|
||||
@ -377,12 +389,16 @@ button.white:active {
|
||||
right:0;
|
||||
bottom:0;
|
||||
overflow-wrap: anywhere;
|
||||
pointer-events: none;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
#overlayClock2{
|
||||
padding:0 5px;
|
||||
background-color: #0009;
|
||||
}
|
||||
#overlayClock2:empty{
|
||||
display:none;
|
||||
}
|
||||
#overlayMsgs{
|
||||
margin:0 auto;
|
||||
background-color: #0000;
|
||||
@ -486,7 +502,7 @@ body.darktheme .credits>a:visited {
|
||||
}
|
||||
|
||||
.advDirectGuestSettings {
|
||||
padding: 10px;
|
||||
padding: 10px 5px;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
@ -1262,6 +1278,11 @@ input[type='radio'] { cursor:pointer; }
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
#recordLocalbutton.la-spinner {
|
||||
animation: spin-animation 3s infinite;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.retry-spinner {
|
||||
border: 1vh solid #7f838666;
|
||||
border-top: 1vh solid #f0f0f066;
|
||||
@ -3330,7 +3351,7 @@ a#reshare {
|
||||
margin: 0px var(--regular-margin);
|
||||
}
|
||||
|
||||
span#guestTips {
|
||||
#guestTips {
|
||||
margin: 0 auto 15px auto;
|
||||
width: 450px;
|
||||
display: flex;
|
||||
@ -4202,6 +4223,8 @@ input:checked + .slider:before {
|
||||
content: "\f1e6"; }
|
||||
.la-reply:before {
|
||||
content: "\f3e5"; }
|
||||
.la-expand-arrows-alt:before {
|
||||
content: "\f31e"; }
|
||||
.la-headset:before {
|
||||
content: "\f590"; }
|
||||
.la-check:before {
|
||||
|
||||
129
main.js
129
main.js
@ -535,15 +535,35 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
|
||||
document.addEventListener('fullscreenchange', event => {
|
||||
log("full screen change event");
|
||||
log(event);
|
||||
if (session.orientation && session.mobile){
|
||||
if (document.fullscreenElement) {
|
||||
document.exitFullscreen();
|
||||
getById("fullscreenPageToggle").classList.add("la-expand-arrows-alt");
|
||||
getById("fullscreenPageToggle").classList.remove("la-compress-arrows-alt");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (document.fullscreenElement) {
|
||||
getById("fullscreenPageToggle").classList.remove("la-expand-arrows-alt");
|
||||
getById("fullscreenPageToggle").classList.add("la-compress-arrows-alt");
|
||||
} else {
|
||||
updateMixer();
|
||||
getById("fullscreenPageToggle").classList.add("la-expand-arrows-alt");
|
||||
getById("fullscreenPageToggle").classList.remove("la-compress-arrows-alt");
|
||||
|
||||
}
|
||||
updateMixer();
|
||||
});
|
||||
|
||||
if (urlParams.has('fullscreenbutton') || urlParams.has('fsb')){ // just an alternative; might be compoundable
|
||||
if (!(iOS || iPad)){
|
||||
session.fullscreenButton = true;
|
||||
getById("fullscreenPage").classList.remove("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
// fullScreenPage
|
||||
|
||||
if (urlParams.has('midi') || urlParams.has('hotkeys')) {
|
||||
session.midiHotkeys = urlParams.get('midi') || urlParams.get ('hotkeys') || 1;
|
||||
session.midiHotkeys = parseInt(session.midiHotkeys);
|
||||
@ -712,6 +732,7 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.layout = {};
|
||||
}
|
||||
}
|
||||
console.warn("Warning: If using &layout with &broadcast, only the director's video will appear in the custom layout, which is likely not intended.");
|
||||
}
|
||||
|
||||
if (urlParams.has('layouts')) { // an ordered array of layouts, which can be used to switch between using the API layouts action.
|
||||
@ -2420,6 +2441,9 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
} else if (session.h264profile=="false"){
|
||||
session.h264profile = false;
|
||||
}
|
||||
} else if ((session.codec==="hardware") && Android){ // same as &h264profile, but easier for me to remember. I'll try to automate this in the future.
|
||||
session.codec = "h264";
|
||||
session.h264profile = "42e01f";
|
||||
}
|
||||
|
||||
if (urlParams.has('nofec')){ // disables error control / throttling -- currently on audio
|
||||
@ -3109,6 +3133,8 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
session.showall = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (urlParams.has('samplerate') || urlParams.has('sr')) {
|
||||
session.sampleRate = parseInt(urlParams.get('samplerate')) || parseInt(urlParams.get('samplerate')) || 48000;
|
||||
if (session.audioCtx) {
|
||||
@ -3119,8 +3145,39 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
});
|
||||
session.audioEffects = true;
|
||||
}
|
||||
|
||||
// if (session.audioCodec === "lyra"){ // WIP. does not work
|
||||
// try {
|
||||
// var { default: Module } = await import('./thirdparty/lyra/webassembly_codec_wrapper.js');
|
||||
// await Module().then((module) => {
|
||||
// console.log("Initialized codec's wasmModule.");
|
||||
// session.lyraCodecModule = module;
|
||||
// }).catch(e => {
|
||||
// console.log(`Module() error: ${e.name} message: ${e.message}`);
|
||||
// });
|
||||
// } catch(e){
|
||||
// errorlog(e);
|
||||
// }
|
||||
// if (session.lyraCodecModule){
|
||||
// console.log("Lyra module loaded");
|
||||
// session.micSampleRate = 16000;
|
||||
// session.encodedInsertableStreams = true;
|
||||
// } else {
|
||||
// console.log("Lyra module failed to load");
|
||||
// }
|
||||
// }
|
||||
|
||||
if (urlParams.has("insertablestreams")){
|
||||
session.encodedInsertableStreams = true;
|
||||
}
|
||||
|
||||
if (urlParams.has('micsamplerate') || urlParams.has('msr')) {
|
||||
session.micSampleRate = parseInt(urlParams.get('micsamplerate')) || parseInt(urlParams.get('msr')) || 48000;
|
||||
}
|
||||
|
||||
if (urlParams.has('noaudioprocessing') || urlParams.has('noap')) {
|
||||
session.disableWebAudio = true; // default true; might be useful to disable on slow or old computers?
|
||||
session.disableViewerWebAudioPipeline = true; // this has the potential to break things.
|
||||
session.audioEffects = false; // disable audio inbound effects also.
|
||||
session.audioMeterGuest = false;
|
||||
if (session.noisegate===null){
|
||||
@ -3414,8 +3471,8 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
}
|
||||
}
|
||||
if (session.roomid || urlParams.has('roomid') || urlParams.has('r') || urlParams.has('room') || filename || (session.permaid !== false)) {
|
||||
|
||||
if (session.roomid || urlParams.has('roomid') || urlParams.has('r') || urlParams.has('room') || filename || (session.permaid !== false)) {
|
||||
var roomid = "";
|
||||
if (urlParams.has('room')) { // needs to be first; takes priority
|
||||
roomid = urlParams.get('room');
|
||||
@ -3438,13 +3495,13 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
if (urlParams.has('effects') || urlParams.has('effect')) {
|
||||
session.effect = urlParams.get('effects') || urlParams.get('effect') || null;
|
||||
}
|
||||
|
||||
if (window.FaceDetector !== undefined){
|
||||
document.querySelectorAll(".facetracker").forEach(ele=>{
|
||||
ele.disabled = null;
|
||||
ele.removeAttribute("disabled");
|
||||
ele.title = "Will slowly pan, tilt, and zoom in on the first face detected";
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -5172,27 +5229,6 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
});
|
||||
}
|
||||
|
||||
window.onload = function winonLoad() { // This just keeps people from killing the live stream accidentally. Also give me a headsup that the stream is ending
|
||||
window.addEventListener("beforeunload", confirmUnload);
|
||||
window.addEventListener("unload", function(e) {
|
||||
try {
|
||||
session.ws.close();
|
||||
if (session.videoElement.recording) {
|
||||
session.videoElement.recorder.writer.close();
|
||||
session.videoElement.recording = false;
|
||||
}
|
||||
for (var i in session.rpcs) {
|
||||
if (session.rpcs[i].videoElement) {
|
||||
if (session.rpcs[i].videoElement.recording) {
|
||||
session.rpcs[i].videoElement.recorder.writer.close();
|
||||
session.rpcs[i].videoElement.recording = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
session.hangup();
|
||||
} catch (e) {}
|
||||
});
|
||||
};
|
||||
|
||||
var lastTouchEnd = 0;
|
||||
document.addEventListener('touchend', function(event) {
|
||||
@ -5229,6 +5265,14 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
AltPressed = false;
|
||||
}
|
||||
|
||||
if (event.key === "Escape") {
|
||||
if (document.fullscreenElement) {
|
||||
document.exitFullscreen();
|
||||
//updateMixer();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (session.disableHotKeys){return;}
|
||||
|
||||
if (PPTHotkey){
|
||||
@ -5366,12 +5410,31 @@ async function main(){ // main asyncronous thread; mostly initializes the user s
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setTimeout(function(){ // lets lazy load the following..
|
||||
window.addEventListener("beforeunload", confirmUnload); // This just keeps people from killing the live stream accidentally. Also give me a headsup that the stream is ending
|
||||
window.addEventListener("unload", function(e) {
|
||||
try {
|
||||
session.ws.close();
|
||||
if (session.videoElement.recording) {
|
||||
session.videoElement.recorder.writer.close();
|
||||
session.videoElement.recording = false;
|
||||
}
|
||||
for (var i in session.rpcs) {
|
||||
if (session.rpcs[i].videoElement) {
|
||||
if (session.rpcs[i].videoElement.recording) {
|
||||
session.rpcs[i].videoElement.recorder.writer.close();
|
||||
session.rpcs[i].videoElement.recording = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
session.hangup();
|
||||
} catch (e) {
|
||||
errorlog(e);
|
||||
}
|
||||
});
|
||||
|
||||
main(); // asyncronous load
|
||||
|
||||
try {
|
||||
try {
|
||||
navigator.serviceWorker.getRegistrations().then(registrations => { // getting rid of old service workers.
|
||||
try {
|
||||
log(registrations);
|
||||
@ -5382,9 +5445,8 @@ try {
|
||||
}
|
||||
} catch(e){}
|
||||
}).catch(errorlog);
|
||||
} catch(e){}
|
||||
} catch(e){}
|
||||
|
||||
setTimeout(function(){ // lazy load
|
||||
var script = document.createElement('script');
|
||||
document.head.appendChild(script);
|
||||
script.onload = function() {
|
||||
@ -5393,4 +5455,9 @@ setTimeout(function(){ // lazy load
|
||||
script.src = "./thirdparty/StreamSaver.js?v=13"; // dynamically load this only if its needed. Keeps loading time down.
|
||||
};
|
||||
script.src = "./thirdparty/polyfill.min.js"; // dynamically load this only if its needed. Keeps loading time down.
|
||||
},0);
|
||||
},100);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// main(); //calling this now from body tag.
|
||||
|
||||
@ -2,13 +2,6 @@ body{
|
||||
zoom: 75%;
|
||||
background-color: #1F1E1F;
|
||||
}
|
||||
.hidden{
|
||||
display:unset!important;
|
||||
visibility: visible;
|
||||
width:unset;
|
||||
height:unset;
|
||||
opacity: 1;
|
||||
}
|
||||
button[data-action-type='solo-chat'] {
|
||||
display:none! important;
|
||||
}
|
||||
@ -54,7 +47,66 @@ span[data-action-type='sceneCluster2']{
|
||||
span[data-action-type='sceneCluster1']{
|
||||
display:none! important;
|
||||
}
|
||||
|
||||
button[data-action-type='recorder-remote']{
|
||||
display:none! important;
|
||||
}
|
||||
button[data-action-type='advanced-camera-settings']{
|
||||
display:inline-block! important;
|
||||
}
|
||||
button[data-action-type='force-keyframe']{
|
||||
display:none! important;
|
||||
}
|
||||
body {
|
||||
font-size: 0.9em! important;
|
||||
}
|
||||
button[data-action-type='mute-scene']{
|
||||
display:inline-block! important;
|
||||
visibility: visible;
|
||||
width: unset;
|
||||
height: unset;
|
||||
opacity: 1;
|
||||
}
|
||||
button[data-action-type='stats-remote']{
|
||||
display:inline-block! important;
|
||||
visibility: visible;
|
||||
width: unset;
|
||||
height: unset;
|
||||
opacity: 1;
|
||||
}
|
||||
button[data-action-type='advanced-audio-settings']{
|
||||
display:inline-block! important;
|
||||
visibility: visible;
|
||||
width: unset;
|
||||
height: unset;
|
||||
opacity: 1;
|
||||
}
|
||||
button[data-action-type='advanced-camera-settings']{
|
||||
display:inline-block! important;
|
||||
visibility: visible;
|
||||
width: unset;
|
||||
height: unset;
|
||||
opacity: 1;
|
||||
}
|
||||
button[data-action-type='advanced-camera-settings']{
|
||||
display:inline-block! important;
|
||||
visibility: visible;
|
||||
width: unset;
|
||||
height: unset;
|
||||
opacity: 1;
|
||||
}
|
||||
.groupcluster1 {
|
||||
display:inline-block! important;
|
||||
visibility: visible;
|
||||
width: unset;
|
||||
height: unset;
|
||||
opacity: 1;
|
||||
}
|
||||
.hideDropMenu:empty{
|
||||
display:none;
|
||||
}
|
||||
.hideDropMenu {
|
||||
display:none;
|
||||
}
|
||||
.orderspan{
|
||||
display:none! important;
|
||||
}
|
||||
@ -64,9 +116,8 @@ span[data-action-type='sceneCluster1']{
|
||||
.directorContainer {
|
||||
display:none!important;
|
||||
}
|
||||
|
||||
.hideDropMenu{
|
||||
display:none!important;
|
||||
:root {
|
||||
--advanced-mode: inline;
|
||||
}
|
||||
|
||||
#header{
|
||||
|
||||
@ -507,9 +507,13 @@
|
||||
user-select: none;
|
||||
}
|
||||
.pressed>canvas{
|
||||
border: solid 2px black;
|
||||
box-shadow: inset 2px 2px 10px #0007, inset -2px -2px 10px #0007;
|
||||
background-color: #FFFA;
|
||||
}
|
||||
.pressed>.group{
|
||||
box-shadow: inset 2px 2px 10px #0007, inset -2px -2px 10px #0007;
|
||||
background-color: #276022aa;
|
||||
}
|
||||
button.pressed {
|
||||
background-color: #CEF;
|
||||
}
|
||||
@ -2450,7 +2454,7 @@
|
||||
additional += "&broadcast";
|
||||
toggleBroadcast = true;
|
||||
} else {
|
||||
additional += "&layout";
|
||||
additional += "&layout"; // do not use &broadcast with &layout, else you will get broken results.
|
||||
toggleBroadcast = false;
|
||||
}
|
||||
|
||||
|
||||
277
thirdparty/CodecsHandler.js
vendored
277
thirdparty/CodecsHandler.js
vendored
@ -28,6 +28,10 @@ Copyright (c) 2012-2020 [Muaz Khan](https://github.com/muaz-khan)
|
||||
var CodecsHandler = (function() {
|
||||
function preferCodec(sdp, codecName) {
|
||||
|
||||
if (codecName){
|
||||
codecName = codecName.toLowerCase();
|
||||
}
|
||||
|
||||
var info = splitLines(sdp);
|
||||
if (!info.videoCodecNumbers) {
|
||||
return sdp;
|
||||
@ -41,18 +45,45 @@ var CodecsHandler = (function() {
|
||||
return sdp;
|
||||
} else if (codecName === 'av1' && info.av1LineNumber === info.videoCodecNumbers[0]) {
|
||||
return sdp;
|
||||
} else if (codecName === 'red' && info.redLineNumber === info.videoCodecNumbers[0]) {
|
||||
return sdp;
|
||||
} else if (codecName === 'fec' && info.fecLineNumber === info.videoCodecNumbers[0]) {
|
||||
return sdp;
|
||||
}
|
||||
//} else if (codecName === 'red' && info.redLineNumber === info.videoCodecNumbers[0]) {
|
||||
// return sdp;
|
||||
//} else if (codecName === 'fec' && info.fecLineNumber === info.videoCodecNumbers[0]) {
|
||||
// return sdp;
|
||||
//}
|
||||
|
||||
sdp = preferCodecHelper(sdp, codecName, info);
|
||||
|
||||
return sdp;
|
||||
}
|
||||
|
||||
function preferCodecHelper(sdp, codec, info, ignore) {
|
||||
|
||||
function preferAudioCodec(sdp, codecName) {
|
||||
if (codecName){
|
||||
codecName = codecName.toLowerCase();
|
||||
}
|
||||
var info = splitAudioLines(sdp);
|
||||
if (!info.audioCodecNumbers) {
|
||||
return sdp;
|
||||
} else if (codecName === 'opus' && info.opusLineNumber === info.audioCodecNumbers[0]) {
|
||||
return sdp;
|
||||
} else if (codecName === 'isac' && info.isacLineNumber === info.audioCodecNumbers[0]) {
|
||||
return sdp;
|
||||
} else if (codecName === 'g722' && info.g722LineNumber === info.audioCodecNumbers[0]) {
|
||||
return sdp;
|
||||
} else if (codecName === 'pcmu' && info.pcmuLineNumber === info.audioCodecNumbers[0]) {
|
||||
return sdp;
|
||||
} else if (codecName === 'pcma' && info.pcmaLineNumber === info.audioCodecNumbers[0]) {
|
||||
return sdp;
|
||||
} else if (codecName === 'red' && info.redLineNumber === info.audioCodecNumbers[0]) {
|
||||
return sdp;
|
||||
}
|
||||
|
||||
sdp = preferAudioCodecHelper(sdp, codecName, info);
|
||||
return sdp;
|
||||
}
|
||||
|
||||
function preferCodecHelper(sdp, codec, info) {
|
||||
var preferCodecNumber = '';
|
||||
|
||||
if (codec === 'vp8') {
|
||||
@ -82,28 +113,26 @@ var CodecsHandler = (function() {
|
||||
return sdp;
|
||||
}
|
||||
preferCodecNumber = info.av1LineNumber;
|
||||
|
||||
} else if (codec === 'red') {
|
||||
if (!info.redLineNumber) {
|
||||
} else {
|
||||
return sdp;
|
||||
}
|
||||
preferCodecNumber = info.redLineNumber;
|
||||
//} else if (codec === 'red') {
|
||||
// if (!info.redLineNumber) {
|
||||
// return sdp;
|
||||
// }
|
||||
// preferCodecNumber = info.redLineNumber;
|
||||
|
||||
} else if (codec === 'fec') {
|
||||
if (!info.fecLineNumber) {
|
||||
return sdp;
|
||||
}
|
||||
preferCodecNumber = info.fecLineNumber;
|
||||
}
|
||||
//} else if (codec === 'fec') {
|
||||
// if (!info.fecLineNumber) {
|
||||
// return sdp;
|
||||
// }
|
||||
// preferCodecNumber = info.fecLineNumber;
|
||||
// }
|
||||
|
||||
var newLine = info.videoCodecNumbersOriginal.split('SAVPF')[0] + 'SAVPF ';
|
||||
|
||||
var newOrder = [preferCodecNumber];
|
||||
|
||||
if (ignore) {
|
||||
newOrder = [];
|
||||
}
|
||||
|
||||
info.videoCodecNumbers.forEach(function(codecNumber) {
|
||||
if (codecNumber === preferCodecNumber) return;
|
||||
newOrder.push(codecNumber);
|
||||
@ -115,6 +144,55 @@ var CodecsHandler = (function() {
|
||||
return sdp;
|
||||
}
|
||||
|
||||
function preferAudioCodecHelper(sdp, codec, info) {
|
||||
var preferCodecNumber = '';
|
||||
|
||||
if (codec === 'opus') {
|
||||
if (!info.opusLineNumber) {
|
||||
return sdp;
|
||||
}
|
||||
preferCodecNumber = info.opusLineNumber;
|
||||
} else if (codec === 'isac') {
|
||||
if (!info.isacLineNumber) {
|
||||
return sdp;
|
||||
}
|
||||
preferCodecNumber = info.isacLineNumber;
|
||||
} else if (codec === 'g722') {
|
||||
if (!info.g722LineNumber) {
|
||||
return sdp;
|
||||
}
|
||||
preferCodecNumber = info.g722LineNumber;
|
||||
} else if (codec === 'pcmu') {
|
||||
if (!info.pcmuLineNumber) {
|
||||
return sdp;
|
||||
}
|
||||
preferCodecNumber = info.pcmuLineNumber;
|
||||
} else if (codec === 'pcma') {
|
||||
if (!info.pcmaLineNumber) {
|
||||
return sdp;
|
||||
}
|
||||
preferCodecNumber = info.pcmaLineNumber;
|
||||
} else if (codec === 'red') {
|
||||
if (!info.redLineNumber) {
|
||||
return sdp;
|
||||
}
|
||||
preferCodecNumber = info.redLineNumber;
|
||||
}
|
||||
var newLine = info.audioCodecNumbersOriginal.split('SAVPF')[0] + 'SAVPF ';
|
||||
|
||||
var newOrder = [preferCodecNumber];
|
||||
|
||||
info.audioCodecNumbers.forEach(function(codecNumber) {
|
||||
if (codecNumber === preferCodecNumber) return;
|
||||
newOrder.push(codecNumber);
|
||||
});
|
||||
|
||||
newLine += newOrder.join(' ');
|
||||
|
||||
sdp = sdp.replace(info.audioCodecNumbersOriginal, newLine);
|
||||
return sdp;
|
||||
}
|
||||
|
||||
function splitLines(sdp) {
|
||||
var info = {};
|
||||
sdp.split('\n').forEach(function(line) {
|
||||
@ -128,35 +206,81 @@ var CodecsHandler = (function() {
|
||||
});
|
||||
}
|
||||
|
||||
if (line.indexOf('VP8/90000') !== -1 && !info.vp8LineNumber) {
|
||||
var LINE = line.toUpperCase();
|
||||
|
||||
if (LINE.indexOf('VP8/90000') !== -1 && !info.vp8LineNumber) {
|
||||
info.vp8LineNumber = line.replace('a=rtpmap:', '').split(' ')[0];
|
||||
}
|
||||
|
||||
if (line.indexOf('VP9/90000') !== -1 && !info.vp9LineNumber) {
|
||||
if (LINE.indexOf('VP9/90000') !== -1 && !info.vp9LineNumber) {
|
||||
info.vp9LineNumber = line.replace('a=rtpmap:', '').split(' ')[0];
|
||||
}
|
||||
|
||||
if (line.indexOf('H264/90000') !== -1 && !info.h264LineNumber) {
|
||||
if (LINE.indexOf('H264/90000') !== -1 && !info.h264LineNumber) {
|
||||
info.h264LineNumber = line.replace('a=rtpmap:', '').split(' ')[0];
|
||||
}
|
||||
|
||||
if (line.indexOf('H265/90000') !== -1 && !info.h265LineNumber) {
|
||||
if (LINE.indexOf('H265/90000') !== -1 && !info.h265LineNumber) {
|
||||
info.h265LineNumber = line.replace('a=rtpmap:', '').split(' ')[0];
|
||||
}
|
||||
|
||||
if (line.indexOf('AV1X/90000') !== -1 && !info.av1LineNumber) {
|
||||
if (LINE.indexOf('AV1X/90000') !== -1 && !info.av1LineNumber) {
|
||||
info.av1LineNumber = line.replace('a=rtpmap:', '').split(' ')[0];
|
||||
} else if (line.indexOf('AV1/90000') !== -1 && !info.av1LineNumber) {
|
||||
} else if (LINE.indexOf('AV1/90000') !== -1 && !info.av1LineNumber) {
|
||||
info.av1LineNumber = line.replace('a=rtpmap:', '').split(' ')[0];
|
||||
}
|
||||
|
||||
if (line.indexOf('red/90000') !== -1 && !info.redLineNumber) {
|
||||
//if (LINE.indexOf('RED/90000') !== -1 && !info.redLineNumber) {
|
||||
// info.redLineNumber = line.replace('a=rtpmap:', '').split(' ')[0];
|
||||
// }
|
||||
|
||||
// if (LINE.indexOf('FEC/90000') !== -1 && !info.fecLineNumber) {
|
||||
// info.fecLineNumber = line.replace('a=rtpmap:', '').split(' ')[0];
|
||||
// }
|
||||
});
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
function splitAudioLines(sdp) {
|
||||
var info = {};
|
||||
sdp.split('\n').forEach(function(line) {
|
||||
if (line.indexOf('m=audio') === 0) {
|
||||
info.audioCodecNumbers = [];
|
||||
line.split('SAVPF')[1].split(' ').forEach(function(codecNumber) {
|
||||
codecNumber = codecNumber.trim();
|
||||
if (!codecNumber || !codecNumber.length) return;
|
||||
info.audioCodecNumbers.push(codecNumber);
|
||||
info.audioCodecNumbersOriginal = line;
|
||||
});
|
||||
}
|
||||
|
||||
var LINE = line.toLowerCase();
|
||||
|
||||
if (LINE.indexOf('opus/48000') !== -1 && !info.opusLineNumber) {
|
||||
info.opusLineNumber = line.replace('a=rtpmap:', '').split(' ')[0];
|
||||
}
|
||||
|
||||
if (LINE.indexOf('isac/32000') !== -1 && !info.isacLineNumber) {
|
||||
info.isacLineNumber = line.replace('a=rtpmap:', '').split(' ')[0];
|
||||
}
|
||||
|
||||
if (LINE.indexOf('g722/8000') !== -1 && !info.g722LineNumber) {
|
||||
info.g722LineNumber = line.replace('a=rtpmap:', '').split(' ')[0];
|
||||
}
|
||||
|
||||
if (LINE.indexOf('pcmu/8000') !== -1 && !info.pcmuLineNumber) {
|
||||
info.pcmuLineNumber = line.replace('a=rtpmap:', '').split(' ')[0];
|
||||
}
|
||||
|
||||
if (LINE.indexOf('pcma/8000') !== -1 && !info.pcmaLineNumber) {
|
||||
info.pcmaLineNumber = line.replace('a=rtpmap:', '').split(' ')[0];
|
||||
}
|
||||
|
||||
if (LINE.indexOf('red/48000') !== -1 && !info.redLineNumber) {
|
||||
info.redLineNumber = line.replace('a=rtpmap:', '').split(' ')[0];
|
||||
}
|
||||
|
||||
if (line.indexOf('ulpfec/90000') !== -1 && !info.fecLineNumber) {
|
||||
info.fecLineNumber = line.replace('a=rtpmap:', '').split(' ')[0];
|
||||
}
|
||||
});
|
||||
|
||||
return info;
|
||||
@ -495,24 +619,24 @@ var CodecsHandler = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof params.dtx != 'undefined') {
|
||||
if (params.dtx){
|
||||
if (sdpLines[opusFmtpLineIndex].split("usedtx=").length==1){
|
||||
appendOpusNext += ';usedtx=1';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof params.useinbandfec != 'undefined') { // useful for handling packet loss
|
||||
if (sdpLines[opusFmtpLineIndex].split("useinbandfec=").length==1){
|
||||
appendOpusNext += ';useinbandfec=' + params.useinbandfec; // Defaults to 0
|
||||
} else {
|
||||
sdpLines[opusFmtpLineIndex] = sdpLines[opusFmtpLineIndex].replace("useinbandfec="+(params.useinbandfec ? 0 : 1), "useinbandfec="+params.useinbandfec);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof params.usedtx != 'undefined') { // Default is 0
|
||||
if (sdpLines[opusFmtpLineIndex].split("usedtx=").length==1){
|
||||
appendOpusNext += ';usedtx=' + params.usedtx; // if decoder prefers the use of DTX.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
sdpLines[opusFmtpLineIndex] = sdpLines[opusFmtpLineIndex].concat(appendOpusNext);
|
||||
|
||||
sdp = sdpLines.join('\r\n');
|
||||
|
||||
return sdp;
|
||||
}
|
||||
|
||||
@ -549,6 +673,73 @@ var CodecsHandler = (function() {
|
||||
return 32768;
|
||||
}
|
||||
|
||||
function modifyDescLyra(modifiedSDP) { // WIP
|
||||
if (!modifiedSDP.includes("m=audio")){ // don't bother modifying if no audio line found
|
||||
return modifiedSDP;
|
||||
}
|
||||
///// Snippet based on Apache 2.0 licenced code. Source: https://github.com/Flash-Meeting/lyra-webrtc //////////
|
||||
modifiedSDP = modifiedSDP.replace("SAVPF 111", "SAVPF 109 111").replace("a=rtpmap:111", "a=rtpmap:109 L16/16000/1\r\na=fmtp:109 ptime=20\r\na=rtpmap:111");
|
||||
modifiedSDP = modifiedSDP.replace("a=rtpmap:106 CN/32000\r\n", "").replace("a=rtpmap:105 CN/16000\r\n", "").replace("a=rtpmap:13 CN/8000\r\n", "").replace(" 106 105 13", "");
|
||||
///////////////////////////////
|
||||
return modifiedSDP;
|
||||
}
|
||||
|
||||
function modifyDescPCM(modifiedSDP, rate=32000, stereo=false, ptimeOverride=false) {
|
||||
if (!modifiedSDP.includes("m=audio")){ // don't bother modifying if no audio line found
|
||||
return modifiedSDP;
|
||||
}
|
||||
var ptime = 10;
|
||||
if (ptimeOverride){
|
||||
ptime = parseInt(ptimeOverride); // 10 seems to work with 48000, so might as well make it default
|
||||
}
|
||||
ptime = parseInt(ptime/10)*10;
|
||||
if (ptime<10){
|
||||
ptime = 10;
|
||||
}
|
||||
rate = parseInt(rate) || 32000;
|
||||
|
||||
|
||||
if (!stereo && (rate>=48000)){
|
||||
rate = 48000; // 44100 doesn't want to work for me, so we'll skip it.
|
||||
ptime = 10; // 48000 only works with ptime=10
|
||||
} else if (!stereo && rate>=44100){
|
||||
rate = 44100; // 44100 doesn't want to work for me, so we'll skip it.
|
||||
ptime = 10;
|
||||
} else if (rate>=32000){
|
||||
rate = 32000;
|
||||
if (stereo){
|
||||
ptime=10; // can be ptime = 20 if not stereo
|
||||
} else if (ptime>20){
|
||||
ptime=20;
|
||||
}
|
||||
} else if (rate>=16000){
|
||||
rate = 16000;
|
||||
if (stereo){
|
||||
if (ptime>20){
|
||||
ptime=20; // can be ptime = 20 if not stereo
|
||||
}
|
||||
} else if (ptime>40){
|
||||
ptime=40;
|
||||
}
|
||||
} else {
|
||||
rate = 8000;
|
||||
if (stereo){
|
||||
if (ptime>40){
|
||||
ptime=40; // can be ptime = 20 if not stereo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stereo){
|
||||
modifiedSDP = modifiedSDP.replace("SAVPF 111", "SAVPF 109 111").replace("a=rtpmap:111", "a=rtpmap:109 L16/"+rate+"/2\r\na=fmtp:109 ptime="+ptime+"\r\na=rtpmap:111");
|
||||
} else {
|
||||
modifiedSDP = modifiedSDP.replace("SAVPF 111", "SAVPF 109 111").replace("a=rtpmap:111", "a=rtpmap:109 L16/"+rate+"/1\r\na=fmtp:109 ptime="+ptime+"\r\na=rtpmap:111");
|
||||
}
|
||||
|
||||
modifiedSDP = modifiedSDP.replace("a=rtpmap:106 CN/32000\r\n", "").replace("a=rtpmap:105 CN/16000\r\n", "").replace("a=rtpmap:13 CN/8000\r\n", "").replace(" 106 105 13", "");
|
||||
return modifiedSDP;
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
disableNACK: disableNACK,
|
||||
@ -557,6 +748,10 @@ var CodecsHandler = (function() {
|
||||
|
||||
disableREMB: disableREMB,
|
||||
|
||||
modifyDescPCM: modifyDescPCM,
|
||||
|
||||
modifyDescLyra: modifyDescLyra,
|
||||
|
||||
getVideoBitrates: function(sdp) {
|
||||
return getVideoBitrates(sdp);
|
||||
},
|
||||
@ -572,7 +767,9 @@ var CodecsHandler = (function() {
|
||||
return getOpusBitrate(sdp);
|
||||
},
|
||||
|
||||
preferCodec: preferCodec
|
||||
preferCodec: preferCodec,
|
||||
|
||||
preferAudioCodec: preferAudioCodec
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
25
thirdparty/lyra/README.md
vendored
Normal file
25
thirdparty/lyra/README.md
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
## WebRTC snippets for Lyra sourced from meeting.dev
|
||||
|
||||
Apache 2.0 Licenced
|
||||
|
||||
Sourced from: https://meeting.dev/lab/lyra-webrtc/loopback.html
|
||||
|
||||
|
||||
## NOTE FROM STEVE
|
||||
At the moment Lyra isn't actually being used, but I'm trying to get it working with VDO.Ninja. It may be removed at some future point - steve
|
||||
|
||||
## TFLITE MODELS SOURCED FROM GOOGLE ON GITHUB
|
||||
|
||||
google/lyra is licensed under the
|
||||
Apache License 2.0
|
||||
https://github.com/google/lyra
|
||||
https://github.com/google/lyra/tree/f079e8c4dd1c61c87de1852178976ee3bdf15561/model_coeffs
|
||||
|
||||
|
||||
## Further Acknowledgments
|
||||
|
||||
Thanks to [the team that developed Lyra](https://ai.googleblog.com/2021/02/lyra-new-very-low-bitrate-codec-for.html) and to [mayitayew for making it work with WASM](https://github.com/mayitayew/soundstream-wasm).
|
||||
|
||||
We are using a modified Lyra WASM. It is available [here](https://github.com/Flash-Meeting/lyra-wasm)
|
||||
|
||||
|
||||
6
thirdparty/lyra/model_coeffs/README.md
vendored
Normal file
6
thirdparty/lyra/model_coeffs/README.md
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
TFLITE MODELS SOURCED FROM GOOGLE ON GITHUB
|
||||
|
||||
google/lyra is licensed under the
|
||||
Apache License 2.0
|
||||
https://github.com/google/lyra
|
||||
https://github.com/google/lyra/tree/f079e8c4dd1c61c87de1852178976ee3bdf15561/model_coeffs
|
||||
BIN
thirdparty/lyra/model_coeffs/lyragan.tflite
vendored
Normal file
BIN
thirdparty/lyra/model_coeffs/lyragan.tflite
vendored
Normal file
Binary file not shown.
BIN
thirdparty/lyra/model_coeffs/quantizer.tflite
vendored
Normal file
BIN
thirdparty/lyra/model_coeffs/quantizer.tflite
vendored
Normal file
Binary file not shown.
BIN
thirdparty/lyra/model_coeffs/soundstream_encoder.tflite
vendored
Normal file
BIN
thirdparty/lyra/model_coeffs/soundstream_encoder.tflite
vendored
Normal file
Binary file not shown.
6508
thirdparty/lyra/webassembly_codec_wrapper.js
vendored
Normal file
6508
thirdparty/lyra/webassembly_codec_wrapper.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
thirdparty/lyra/webassembly_codec_wrapper.wasm
vendored
Normal file
BIN
thirdparty/lyra/webassembly_codec_wrapper.wasm
vendored
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user