From b617f98aec51502d0eeba73a0306b847249f147f Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Tue, 7 Apr 2026 11:16:36 +0200 Subject: [PATCH] webrtc test --- server/endpoints.js | 8 ++++ server/web.js | 2 +- views/audioonly.ejs | 2 +- web/js/3las/3las.js | 38 +++++-------------- web/js/3las/fallback/3las.fallback.js | 25 ++++-------- .../formats/3las.formatreader.mpeg.js | 25 ++++-------- web/js/audio.js | 38 +++++++++---------- 7 files changed, 53 insertions(+), 85 deletions(-) diff --git a/server/endpoints.js b/server/endpoints.js index d7cff81..d2c5927 100644 --- a/server/endpoints.js +++ b/server/endpoints.js @@ -339,6 +339,14 @@ router.get('/server_time', (req, res) => { router.get('/ping', (req, res) => res.send('pong')); +// techkrzysiek's WebRTC plugin integration from the Miedzyzdroje server. +router.get('/webrtc-audio-flags.json', (req, res) => res.json({disable3las: false})); +// /webrtc-audio.conf should serve a list of supported WebRTC endpoints; like this "56000:https://webrtc.fmdx.pro/miedzyzdroje_56k/whep"; each entry is seperated by a semicolon +// We should be able to use mediamtx for SDP/WHEP and the WebRTC itself. + +// Testing only! TODO: Add this to config +router.get('/webrtc-audio.conf', (req, res) => res.send("192000;https://batorego.flerken.pl.eu.org/webrtc/whep192/whep")); + const logHistory = {}; // Function to check if the ID has been logged within the last 60 minutes diff --git a/server/web.js b/server/web.js index 439f371..1a0d673 100644 --- a/server/web.js +++ b/server/web.js @@ -114,7 +114,7 @@ wss.on('connection', (ws, request) => { const command = helpers.antispamProtection(message, clientIp, ws, userCommands, lastWarn, userCommandHistory, '18', 'text', 16 * 1024); if (!clientIp.includes("127.0.0.1")) { - if (!request.session.isAdminAuthenticated && (command.startsWith('X') || command.startsWith('Y') || command.startsWith("D") || command.startsWith("")) || + if (((command.startsWith('X') || command.startsWith('Y')) && !request.session.isAdminAuthenticated) || ((command.startsWith('F') || command.startsWith('W')) && serverConfig.bwSwitch === false)) { logWarn(`User \x1b[90m${clientIp}\x1b[0m attempted to send a potentially dangerous command: ${command.slice(0, 64)}.`); return; diff --git a/views/audioonly.ejs b/views/audioonly.ejs index 5778253..3295d5c 100644 --- a/views/audioonly.ejs +++ b/views/audioonly.ejs @@ -66,6 +66,6 @@ - + \ No newline at end of file diff --git a/web/js/3las/3las.js b/web/js/3las/3las.js index b9a347f..a63793c 100644 --- a/web/js/3las/3las.js +++ b/web/js/3las/3las.js @@ -1,27 +1,16 @@ var audioStreamRestartInterval; var elapsedTimeConnectionWatchdog; -var _3LAS_Settings = /** @class */ (function () { - function _3LAS_Settings() { - this.SocketHost = location.hostname ? location.hostname : "127.0.0.1"; - this.SocketPort = location.port; - this.SocketPath = "/"; - this.Fallback = new Fallback_Settings(); - } - return _3LAS_Settings; -}()); var _3LAS = /** @class */ (function () { - function _3LAS(logger, settings) { + function _3LAS(url, logger) { + this.wsurl = url; this.Logger = logger; - if (!this.Logger) { - this.Logger = new Logging(null, null); - } - this.Settings = settings; + if (!this.Logger) this.Logger = new Logging(null, null); try { - this.Fallback = new Fallback(this.Logger, this.Settings.Fallback); + this.Fallback_Settings = new Fallback_Settings(); + this.Fallback = new Fallback(this.Logger, this.Fallback_Settings); this.Fallback.ActivityCallback = this.OnActivity.bind(this); - } - catch (_b) { + } catch (_b) { this.Fallback = null; } @@ -29,9 +18,7 @@ var _3LAS = /** @class */ (function () { this.Logger.Log('3LAS: Browser does not support either media handling methods.'); throw new Error(); } - if (isAndroid) { - this.WakeLock = new WakeLock(this.Logger); - } + if (isAndroid) this.WakeLock = new WakeLock(this.Logger); } Object.defineProperty(_3LAS.prototype, "Volume", { get: function () { @@ -52,9 +39,7 @@ var _3LAS = /** @class */ (function () { // Restart audio stream if radio data connection was reestablished // to prevent stuttering audio in some cases - if (audioStreamRestartInterval) { - clearInterval(audioStreamRestartInterval); - } + if (audioStreamRestartInterval) clearInterval(audioStreamRestartInterval); audioStreamRestartInterval = setInterval(() => { if (requiresAudioStreamRestart) { requiresAudioStreamRestart = false; @@ -90,12 +75,9 @@ var _3LAS = /** @class */ (function () { }, 3000); // This is stupid, but required for Android.... thanks Google :( - if (this.WakeLock) - this.WakeLock.Begin(); + if (this.WakeLock) this.WakeLock.Begin(); try { - const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:'; - const url = `${wsProtocol}//${location.hostname}/audio`; - this.WebSocket = new WebSocketClient(this.Logger, url , this.OnSocketError.bind(this), this.OnSocketConnect.bind(this), this.OnSocketDataReady.bind(this), this.OnSocketDisconnect.bind(this)); + this.WebSocket = new WebSocketClient(this.Logger, this.wsurl , this.OnSocketError.bind(this), this.OnSocketConnect.bind(this), this.OnSocketDataReady.bind(this), this.OnSocketDisconnect.bind(this)); this.Logger.Log("Init of WebSocketClient succeeded"); this.Logger.Log("Trying to connect to server."); } diff --git a/web/js/3las/fallback/3las.fallback.js b/web/js/3las/fallback/3las.fallback.js index 81d123d..c6c422b 100644 --- a/web/js/3las/fallback/3las.fallback.js +++ b/web/js/3las/fallback/3las.fallback.js @@ -17,16 +17,11 @@ var Fallback_Settings = /** @class */ (function () { var Fallback = /** @class */ (function () { function Fallback(logger, settings) { this.Logger = logger; - if (!this.Logger) { - this.Logger = new Logging(null, null); - } + if (!this.Logger) this.Logger = new Logging(null, null); // Create audio context - if (typeof AudioContext !== "undefined") - this.Audio = new AudioContext(); - else if (typeof webkitAudioContext !== "undefined") - this.Audio = new webkitAudioContext(); - else if (typeof mozAudioContext !== "undefined") - this.Audio = new mozAudioContext(); + if (typeof AudioContext !== "undefined") this.Audio = new AudioContext(); + else if (typeof webkitAudioContext !== "undefined") this.Audio = new webkitAudioContext(); + else if (typeof mozAudioContext !== "undefined") this.Audio = new mozAudioContext(); else { this.Logger.Log('3LAS: Browser does not support "AudioContext".'); throw new Error(); @@ -120,17 +115,13 @@ var Fallback = /** @class */ (function () { } }; // Callback function from socket connection - Fallback.prototype.OnSocketError = function (message) { - }; - Fallback.prototype.OnSocketConnect = function () { - }; - Fallback.prototype.OnSocketDisconnect = function () { - }; + Fallback.prototype.OnSocketError = function (message) {}; + Fallback.prototype.OnSocketConnect = function () {}; + Fallback.prototype.OnSocketDisconnect = function () {}; Fallback.prototype.OnSocketDataReady = function (data) { this.PacketModCounter++; if (this.PacketModCounter > 100) { - if (this.ActivityCallback) - this.ActivityCallback(); + if (this.ActivityCallback) this.ActivityCallback(); this.PacketModCounter = 0; } this.FormatReader.PushData(new Uint8Array(data)); diff --git a/web/js/3las/fallback/formats/3las.formatreader.mpeg.js b/web/js/3las/fallback/formats/3las.formatreader.mpeg.js index a8b0c79..e6ad365 100644 --- a/web/js/3las/fallback/formats/3las.formatreader.mpeg.js +++ b/web/js/3las/fallback/formats/3las.formatreader.mpeg.js @@ -88,9 +88,7 @@ var AudioFormatReader_MPEG = /** @class */ (function (_super) { expectedTotalPlayTime_1 += lastGranulePlayTime_1; bufferLength += this.Frames[this.Frames.length - 1].Data.length; // If needed, add some space for the ID3v2 tag - if (this.AddId3Tag) { - bufferLength += AudioFormatReader_MPEG.Id3v2Tag.length; - } + if (this.AddId3Tag) bufferLength += AudioFormatReader_MPEG.Id3v2Tag.length; // Create a buffer long enough to hold everything var decodeBuffer = new Uint8Array(bufferLength); var offset = 0; @@ -109,8 +107,7 @@ var AudioFormatReader_MPEG = /** @class */ (function (_super) { // Increment Id var id_1 = this.Id++; // Check if decoded frames might be too far back in the past - if (!this.OnBeforeDecode(id_1, expectedTotalPlayTime_1)) - return; + if (!this.OnBeforeDecode(id_1, expectedTotalPlayTime_1)) return; // Push window to the decoder this.Audio.decodeAudioData(decodeBuffer.buffer, (function (decodedData) { var _id = id_1; @@ -133,8 +130,7 @@ var AudioFormatReader_MPEG = /** @class */ (function (_super) { // Sync found, set frame start this.FrameStartIdx = i; break; - } - i++; + } i++; } } // Find frame end @@ -172,22 +168,17 @@ var AudioFormatReader_MPEG = /** @class */ (function (_super) { }; // Checks if there is a frame ready to be extracted AudioFormatReader_MPEG.prototype.CanExtractFrame = function () { - if (this.FrameStartIdx < 0 || this.FrameEndIdx < 0) - return false; - else if (this.FrameEndIdx <= this.DataBuffer.length) - return true; - else - return false; + if (this.FrameStartIdx < 0 || this.FrameEndIdx < 0) return false; + else if (this.FrameEndIdx <= this.DataBuffer.length) return true; + else return false; }; // Extract a single frame from the buffer AudioFormatReader_MPEG.prototype.ExtractFrame = function () { // Extract frame data from buffer var frameArray = this.DataBuffer.buffer.slice(this.FrameStartIdx, this.FrameEndIdx); // Remove frame from buffer - if ((this.FrameEndIdx + 1) < this.DataBuffer.length) - this.DataBuffer = new Uint8Array(this.DataBuffer.buffer.slice(this.FrameEndIdx)); - else - this.DataBuffer = new Uint8Array(0); + if ((this.FrameEndIdx + 1) < this.DataBuffer.length) this.DataBuffer = new Uint8Array(this.DataBuffer.buffer.slice(this.FrameEndIdx)); + else this.DataBuffer = new Uint8Array(0); // Reset Start/End indices this.FrameStartIdx = 0; this.FrameEndIdx = -1; diff --git a/web/js/audio.js b/web/js/audio.js index 267aa35..8bf3908 100644 --- a/web/js/audio.js +++ b/web/js/audio.js @@ -7,6 +7,7 @@ class WebSocketAudioPlayer { this.sourceBuffer = null; this.queue = []; this.started = false; + this._volume = 1; } supported() { @@ -21,7 +22,7 @@ class WebSocketAudioPlayer { const liveEdge = buffered.end(buffered.length - 1); const lag = liveEdge - this.audio.currentTime; - if (lag > .9) this.audio.currentTime = liveEdge - 0.2; // snap to near live edge + if (lag > .85) this.audio.currentTime = liveEdge - 0.2; // snap to near live edge } Start() { @@ -59,8 +60,13 @@ class WebSocketAudioPlayer { this.started = false; } - setVolume(v) { - if (this.audio) this.audio.volume = Math.max(0, Math.min(1, v)); + get Volume() { + return this._volume; + } + set Volume(v) { + const actual = Math.max(0, Math.min(1, v)) + if (this.audio) this.audio.volume = actual; + this._volume = actual; } _appendNext() { @@ -87,16 +93,12 @@ function createStream() { if (MediaSource.isTypeSupported("audio/mpeg")) { firefox = false; Stream = new WebSocketAudioPlayer(url); - Stream.setVolume($('#volumeSlider').val()); } else { firefox = true; alert("Your browser does not support MP3 over MSE, meaning we have to use 3LAS which is terrible and gives terrible audio quality. If you want better sound, switch to anything chromium based") - const settings = new _3LAS_Settings(); - Stream = new _3LAS(null, settings); - Stream.Volume = $('#volumeSlider').val(); - Stream.ConnectivityCallback = OnConnectivityCallback; + Stream = new _3LAS(url, null); } - + Stream.Volume = $('#volumeSlider').val(); } catch (error) { console.error("Initialization Error: ", error); } @@ -130,22 +132,16 @@ function OnPlayButtonClick(_ev) { $playbutton.addClass('bg-gray').prop('disabled', true); setTimeout(() => $playbutton.removeClass('bg-gray').prop('disabled', false), 2000); - if (Stream && firefox) Stream.setVolume($("#volumeSlider").val()); } function updateVolume() { - if(!firefox) { - const newVolume = $(this).val(); - if (Stream) Stream.setVolume(newVolume); - else console.warn("Stream is not initialized."); - } else { - if(Stream) { - const newVolume = $(this).val(); - newVolumeGlobal = newVolume; - console.log("Volume updated to:", newVolume); - Stream.Volume = newVolume; - } else console.warn("Stream is not initialized."); + const newVolume = $(this).val(); + if(!Stream) { + console.warn("Stream is not initialized."); + return; } + + Stream.Volume = newVolume; } $(document).ready(Init);