From 40834d04ba68531b6fd926e114219fc6bfa5be7c Mon Sep 17 00:00:00 2001 From: Joel Calado Date: Mon, 7 Dec 2020 12:51:07 +0000 Subject: [PATCH] speedtest graph color, button status, log copy graphs target value graphs max value graphs now have colors, green / yellow / red log click to copy bitrate buttons reflect incoming connection requested bitrates via background color disconnect button hidden until first connection established --- speedtest.css | 45 +++++++-- speedtest.html | 244 +++++++++++++++++++++++++++++++++++-------------- 2 files changed, 215 insertions(+), 74 deletions(-) diff --git a/speedtest.css b/speedtest.css index 8d70df1..9d09290 100644 --- a/speedtest.css +++ b/speedtest.css @@ -32,9 +32,27 @@ h1 small { padding-bottom: 5px; } +#feeds { + display: flex; +} + +#feeds span { + flex: 1; + height: 30vh; + display: flex; + flex-direction: column; +} + +#feeds h3 { + color: whitesmoke; + margin: 10px; + text-align: center; +} + iframe { - min-height: 30vh; - width: 39vw; + height: auto; + width: 100%; + flex: 1; } #controls { @@ -45,6 +63,10 @@ iframe { margin: 5px; } +#controls button.active { + background-color: green; +} + canvas { background-color: black; margin: 20px; @@ -54,7 +76,8 @@ canvas { margin-top: 20px; background: #2a2a2a; padding: 20px 0px; - border: 1px solid #383838; + border: 1px solid #383838; + cursor: pointer; } #log ul { @@ -111,9 +134,19 @@ ol { } iframe { - width: 90vw; - min-height: 0; + width: 100%; + } + + #feeds { + flex-direction: column; + } + + #feeds h3 { + display: none; } } - #statsdiv {display: none;} \ No newline at end of file + #statsdiv {display: none;} + + + \ No newline at end of file diff --git a/speedtest.html b/speedtest.html index 59854a8..0a6c5ef 100644 --- a/speedtest.html +++ b/speedtest.html @@ -27,6 +27,24 @@ })(window); var urlParams = new URLSearchParams(window.location.search); + function copyFunction(copyText) { + alert("Log copied to the clipboard."); + try { + copyText.select(); + copyText.setSelectionRange(0, 99999); + document.execCommand("copy"); + } catch (e) { + var dummy = document.createElement("input"); + document.body.appendChild(dummy); + dummy.value = copyText; + dummy.select(); + document.execCommand("copy"); + document.body.removeChild(dummy); + return false; + } + + } + function loadIframe() { // this is pretty important if you want to avoid camera permission popup problems. YOu need to load the iFRAME after you load the parent body. A quick solution is like: loadIframe();"> !!! @@ -66,7 +84,16 @@ iframe.src = srcString; iframeContainer.appendChild(iframe); - document.getElementById("container").appendChild(iframeContainer); + + var title = document.createElement("h3"); + title.innerText = "Local video feed"; + iframeContainer.appendChild(title); + + var feeds = document.createElement("div"); + feeds.id = "feeds"; + + document.getElementById("container").appendChild(feeds); + document.getElementById("feeds").appendChild(iframeContainer); var iframe = document.createElement("iframe"); var iframeContainer = document.createElement("span"); @@ -85,7 +112,12 @@ iframe.src = srcString; iframeContainer.appendChild(iframe); - document.getElementById("container").appendChild(iframeContainer); + + var title = document.createElement("h3"); + title.innerText = "Server video feed"; + iframeContainer.appendChild(title); + + document.getElementById("feeds").appendChild(iframeContainer); var button = document.createElement("br"); document.getElementById("container").appendChild(button); @@ -93,19 +125,12 @@ var buttonContainer = document.createElement("div"); buttonContainer.id = "controls"; - var button = document.createElement("button"); - button.innerHTML = "Disconnect"; - button.className = "red"; - button.onclick = function () { - iframe.contentWindow.postMessage({ close: true }, "*"); - }; - buttonContainer.appendChild(button); - var button = document.createElement("button"); button.innerHTML = "Low Bitrate"; button.className = "grey"; button.onclick = function () { iframe.contentWindow.postMessage({ bitrate: 30 }, "*"); + bitrate.target = 30; }; buttonContainer.appendChild(button); @@ -114,14 +139,25 @@ button.className = "grey"; button.onclick = function () { iframe.contentWindow.postMessage({ bitrate: 6000 }, "*"); + bitrate.target = 6000; }; buttonContainer.appendChild(button); var button = document.createElement("button"); button.innerHTML = "Default Bitrate"; - button.className = "grey"; + button.className = "grey active"; button.onclick = function () { iframe.contentWindow.postMessage({ bitrate: -1 }, "*"); + bitrate.target = 3000; + }; + buttonContainer.appendChild(button); + + var button = document.createElement("button"); + button.innerHTML = "Disconnect"; + button.className = "red"; + button.style.display = "none"; + button.onclick = function () { + iframe.contentWindow.postMessage({ close: true }, "*"); }; buttonContainer.appendChild(button); @@ -141,7 +177,34 @@ eventer(messageEvent, function (e) { if ("action" in e.data) { - logData("Action",e.data.action); + logData(e.data.action, e.data.value); + + if (e.data.action == "new-view-connection") { + buttonContainer.querySelectorAll( + "#controls button:last-child" + )[0].style.display = "inline"; + } + + if (e.data.action == "setVideoBitrate") { + buttonContainer.querySelectorAll("button").forEach((button) => { + button.classList.remove("active"); + }); + if (e.data.value == 30) { + document + .querySelectorAll("#controls button")[0] + .classList.add("active"); + } + if (e.data.value == 6000) { + document + .querySelectorAll("#controls button")[1] + .classList.add("active"); + } + if (e.data.value == -1) { + document + .querySelectorAll("#controls button")[2] + .classList.add("active"); + } + } } if ("stats" in e.data) { var out = ""; @@ -149,41 +212,37 @@ out += printValues(e.data.stats.inbound_stats[streamID]); } - - if (out.split("Bitrate_in_kbps").length > 1) { - for (var key in e.data.stats.inbound_stats[streamID]) { - if (key.startsWith("RTCMediaStreamTrack_receiver")) { var bitrate = e.data.stats.inbound_stats[streamID][key][ "Bitrate_in_kbps" ]; - plotData("bitrate-graph", bitrate, 6000); + updateData("bitrate", bitrate); var buffer = e.data.stats.inbound_stats[streamID][key][ "Buffer_Delay_in_ms" ]; - plotData("buffer-graph", buffer, 200); + updateData("buffer", buffer); var packetloss = e.data.stats.inbound_stats[streamID][key][ "packetLoss_in_percentage" - ].toFixed(2); - plotData("packetloss-graph", packetloss, 3); + ]; + if (packetloss != undefined) { + packetloss = packetloss.toFixed(2); + updateData("packetloss", packetloss); + } - var resolution = - e.data.stats.inbound_stats[streamID][key][ - "Resolution" - ] + var resolution = + e.data.stats.inbound_stats[streamID][key]["Resolution"]; - if(previousResolution != resolution) { + if (previousResolution != resolution) { previousResolution = resolution; logData("Resolution", resolution); } - } } @@ -210,10 +269,11 @@ return out; } - function logData(type, data){ + function logData(type, data) { var log = document.getElementById("log").getElementsByTagName("ul")[0]; var entry = document.createElement('li'); - entry.innerText = "[" + new Date().toLocaleTimeString() + "] " + type + " : " + data; + entry.textContent = + "[" + new Date().toLocaleTimeString() + "] " + type + " : " + data; log.prepend(entry); } @@ -252,17 +312,14 @@

Packet Loss (%)

0 - +
-
-

Log

+
+

Log

    - - +

    How to use

      @@ -277,67 +334,118 @@ CTRL + LeftClick on the new video to open stats that way)
    1. - Bitrate, Buffer delay, and packet loss are - important connection quality metrics + Bitrate, Buffer delay, and packet loss are important connection + quality metrics
    2. - Change the video bitrate by pressing the buttons below the video. - It should approach 6000-kbps if the network allows. + Change the video bitrate by pressing the buttons below the video. It + should approach 6000-kbps if the network allows.
    - \ No newline at end of file +