diff --git a/web/static/js/main.js b/web/static/js/main.js index 1356b41..e20bc3d 100644 --- a/web/static/js/main.js +++ b/web/static/js/main.js @@ -1,18 +1,65 @@ import { GSWebSocket } from "./modules/websocket.js"; import { ViewerCounter } from "./modules/viewerCounter.js"; +// Some variables that need to be fixed by web page +const ViewersCounterRefreshPeriod = 1000; +const stream = "demo"; +let quality = "source"; + // Create WebSocket const s = new GSWebSocket(); -s.open(() => { - // FIXME open callback -}, () => { - // FIXME close callback +s.open(); + +// Register keyboard events +const viewer = document.getElementById("viewer"); +window.addEventListener("keydown", (event) => { + switch (event.key) { + case "f": + // F key put player in fullscreen + if (document.fullscreenElement !== null) { + document.exitFullscreen(); + } else { + viewer.requestFullscreen(); + } + break; + case "m": + case " ": + // M and space key mute player + viewer.muted = !viewer.muted; + event.preventDefault(); + viewer.play(); + break; + } }); // Create viewer counter -const streamName = "demo"; // FIXME const viewerCounter = new ViewerCounter( document.getElementById("connected-people"), - streamName, + stream, ); -viewerCounter.regularUpdate(1000); // FIXME +viewerCounter.regularUpdate(ViewersCounterRefreshPeriod); + +// Side widget toggler +const sideWidgetToggle = document.getElementById("sideWidgetToggle"); +const sideWidget = document.getElementById("sideWidget"); +if (sideWidgetToggle !== null && sideWidget !== null) { + // On click, toggle side widget visibility + sideWidgetToggle.addEventListener("click", function () { + if (sideWidget.style.display === "none") { + sideWidget.style.display = "block"; + sideWidgetToggle.textContent = "»"; + } else { + sideWidget.style.display = "none"; + sideWidgetToggle.textContent = "«"; + } + }); +} + +// Video quality toggler +document.getElementById("quality").addEventListener("change", (event) => { + quality = event.target.value; + console.log(`Stream quality changed to ${quality}`); + + // Restart the connection with a new quality + // FIXME +}); diff --git a/web/static/js/modules/websocket.js b/web/static/js/modules/websocket.js index f6a31c7..792d9f9 100644 --- a/web/static/js/modules/websocket.js +++ b/web/static/js/modules/websocket.js @@ -17,21 +17,18 @@ export class GsWebSocket { * @param {Function} openCallback Function called when connection is established. * @param {Function} closeCallback Function called when connection is lost. */ - open(openCallback, closeCallback) { + open() { this._open(); - this.socket.addEventListener("open", (event) => { + this.socket.addEventListener("open", () => { console.log("WebSocket opened"); - openCallback(event); }); - this.socket.addEventListener("close", (event) => { + this.socket.addEventListener("close", () => { console.log("WebSocket closed, retrying connection in 1s..."); setTimeout(this._open, 1000); - closeCallback(event); }); - this.socket.addEventListener("error", (event) => { + this.socket.addEventListener("error", () => { console.log("WebSocket errored, retrying connection in 1s..."); setTimeout(this._open, 1000); - closeCallback(event); }); } diff --git a/web/static/js/sideWidget.js b/web/static/js/sideWidget.js deleted file mode 100644 index efc0d9e..0000000 --- a/web/static/js/sideWidget.js +++ /dev/null @@ -1,12 +0,0 @@ -// Side widget toggler -const sideWidgetToggle = document.getElementById("sideWidgetToggle") -sideWidgetToggle.addEventListener("click", function () { - const sideWidget = document.getElementById("sideWidget") - if (sideWidget.style.display === "none") { - sideWidget.style.display = "block" - sideWidgetToggle.textContent = "»" - } else { - sideWidget.style.display = "none" - sideWidgetToggle.textContent = "«" - } -}) \ No newline at end of file diff --git a/web/static/js/videoQuality.js b/web/static/js/videoQuality.js deleted file mode 100644 index ba6e15e..0000000 --- a/web/static/js/videoQuality.js +++ /dev/null @@ -1,9 +0,0 @@ -document.getElementById("quality").addEventListener("change", (event) => { - console.log(`Stream quality changed to ${event.target.value}`) - - // Restart the connection with a new quality - peerConnection.close() - peerConnection = null - streamPath = window.location.href + event.target.value - startPeerConnection() -}) diff --git a/web/static/js/viewer.js b/web/static/js/viewer.js index 9b8f3ea..4891dd8 100644 --- a/web/static/js/viewer.js +++ b/web/static/js/viewer.js @@ -1,97 +1,81 @@ -let peerConnection -let streamPath = window.location.href +let peerConnection; +let streamPath = window.location.href; +let stream = streamPath; +let quality = "source"; -startPeerConnection = () => { + +const startPeerConnection = () => { // Init peer connection peerConnection = new RTCPeerConnection({ iceServers: [{ urls: stunServers }] - }) + }); // On connection change, change indicator color // if connection failed, restart peer connection peerConnection.oniceconnectionstatechange = e => { - console.log("ICE connection state changed, " + peerConnection.iceConnectionState) + console.log("ICE connection state changed, " + peerConnection.iceConnectionState); switch (peerConnection.iceConnectionState) { - case "disconnected": - document.getElementById("connectionIndicator").style.fill = "#dc3545" - break - case "checking": - document.getElementById("connectionIndicator").style.fill = "#ffc107" - break - case "connected": - document.getElementById("connectionIndicator").style.fill = "#28a745" - break - case "closed": - case "failed": - console.log("Connection failed, restarting...") - peerConnection.close() - peerConnection = null - setTimeout(startPeerConnection, 1000) - break + case "disconnected": + document.getElementById("connectionIndicator").style.fill = "#dc3545"; + break; + case "checking": + document.getElementById("connectionIndicator").style.fill = "#ffc107"; + break; + case "connected": + document.getElementById("connectionIndicator").style.fill = "#28a745"; + break; + case "closed": + case "failed": + console.log("Connection failed, restarting..."); + peerConnection.close(); + peerConnection = null; + setTimeout(startPeerConnection, 1000); + break; } - } + }; // We want to receive audio and video - peerConnection.addTransceiver('video', { 'direction': 'sendrecv' }) - peerConnection.addTransceiver('audio', { 'direction': 'sendrecv' }) + peerConnection.addTransceiver("video", { "direction": "sendrecv" }); + peerConnection.addTransceiver("audio", { "direction": "sendrecv" }); // Create offer and set local description peerConnection.createOffer().then(offer => { // After setLocalDescription, the browser will fire onicecandidate events - peerConnection.setLocalDescription(offer) - }).catch(console.log) + peerConnection.setLocalDescription(offer); + }).catch(console.log); // When candidate is null, ICE layer has run out of potential configurations to suggest // so let's send the offer to the server peerConnection.onicecandidate = event => { if (event.candidate === null) { // Send offer to server - // The server know the stream name from the url // The server replies with its description // After setRemoteDescription, the browser will fire ontrack events - console.log("Sending session description to server") + console.log("Sending session description to server"); fetch(streamPath, { - method: 'POST', + method: "POST", headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json' + "Accept": "application/json", + "Content-Type": "application/json" }, - body: JSON.stringify(peerConnection.localDescription) + body: JSON.stringify({ + "webRtcSdp": peerConnection.localDescription, + "stream": stream, + "quality": quality + }) }) .then(response => response.json()) .then((data) => peerConnection.setRemoteDescription(new RTCSessionDescription(data))) - .catch(console.log) + .catch(console.log); } - } + }; // When video track is received, configure player peerConnection.ontrack = function (event) { - console.log(`New ${event.track.kind} track`) + console.log(`New ${event.track.kind} track`); if (event.track.kind === "video") { - const viewer = document.getElementById('viewer') - viewer.srcObject = event.streams[0] + const viewer = document.getElementById("viewer"); + viewer.srcObject = event.streams[0]; } - } -} - -// Register keyboard events -let viewer = document.getElementById("viewer") -window.addEventListener("keydown", (event) => { - switch (event.key) { - case 'f': - // F key put player in fullscreen - if (document.fullscreenElement !== null) { - document.exitFullscreen() - } else { - viewer.requestFullscreen() - } - break - case 'm': - case ' ': - // M and space key mute player - viewer.muted = !viewer.muted - event.preventDefault() - viewer.play() - break - } -}) + }; +}; diff --git a/web/static/js/viewersCounter.js b/web/static/js/viewersCounter.js deleted file mode 100644 index 7298f6e..0000000 --- a/web/static/js/viewersCounter.js +++ /dev/null @@ -1,12 +0,0 @@ -// Refresh viewer count by pulling metric from server -function refreshViewersCounter(streamID, period) { - // Distinguish oneDomainPerStream mode - fetch("/_stats/" + streamID) - .then(response => response.json()) - .then((data) => document.getElementById("connected-people").innerText = data.ConnectedViewers) - .catch(console.log) - - setTimeout(() => { - refreshViewersCounter(streamID, period) - }, period) -} diff --git a/web/template/player.html b/web/template/player.html index 3e340a4..20d6125 100644 --- a/web/template/player.html +++ b/web/template/player.html @@ -34,14 +34,11 @@ {{end}} -{{if .WidgetURL}}{{end}} - - - + -{{end}} \ No newline at end of file +{{end}}