Advertisement
Guest User

Untitled

a guest
Jan 28th, 2020
409
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 5 25.31 KB | None | 0 0
  1. <!DOCTYPE html>
  2. <!--
  3.    @license Apache-2.0
  4.    Copyright 2018 Novage LLC.
  5.  
  6.    Licensed under the Apache License, Version 2.0 (the "License");
  7.    you may not use this file except in compliance with the License.
  8.    You may obtain a copy of the License at
  9.  
  10.        http://www.apache.org/licenses/LICENSE-2.0
  11.  
  12.    Unless required by applicable law or agreed to in writing, software
  13.    distributed under the License is distributed on an "AS IS" BASIS,
  14.    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15.    See the License for the specific language governing permissions and
  16.    limitations under the License.
  17. -->
  18. <html lang="en">
  19. <head>
  20.     <meta charset="UTF-8">
  21.  
  22.     <script async src="https://www.googletagmanager.com/gtag/js?id=UA-106860120-1"></script>
  23.     <script>window.dataLayer = window.dataLayer||[];function gtag(){dataLayer.push(arguments)};gtag('js',new Date());gtag('config','UA-106860120-1');</script>
  24.  
  25.     <title>P2P Media Loader</title>
  26.     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  27.  
  28.     <script async src="https://cdn.jsdelivr.net/npm/p2p-media-loader-core@latest/build/p2p-media-loader-core.min.js"></script>
  29.     <script async src="http://novage.com.ua/assets/p2p-graph.js"></script>
  30.  
  31.     <script>
  32.         const URL_P2P_MEDIA_LOADER_HLSJS = "https://cdn.jsdelivr.net/npm/p2p-media-loader-hlsjs@latest/build/p2p-media-loader-hlsjs.min.js";
  33.     </script>
  34.  
  35.     <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
  36.     <script async src="https://cdnjs.cloudflare.com/ajax/libs/rickshaw/1.6.3/rickshaw.min.js"></script>
  37.  
  38.     <link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/rickshaw/1.6.3/rickshaw.min.css">
  39.  
  40.     <style>
  41.         body {
  42.             font: normal 400 16px 'Roboto', sans-serif;
  43.             color: #333333;
  44.             margin-top: 1em;
  45.             margin-bottom: 3em;
  46.         }
  47.  
  48.         .main-header .title {
  49.             text-align: center;
  50.         }
  51.  
  52.         .container {
  53.             padding: 0 15px;
  54.             margin: 0 auto;
  55.         }
  56.  
  57.         @media (min-width: 576px) {
  58.             .container {
  59.                 max-width: 540px;
  60.             }
  61.         }
  62.  
  63.         @media (min-width: 768px) {
  64.             .container {
  65.                 max-width: 720px;
  66.             }
  67.         }
  68.  
  69.         @media (min-width: 992px) {
  70.             .container {
  71.                 max-width: 960px;
  72.             }
  73.         }
  74.  
  75.         @media (min-width: 1200px) {
  76.             .container {
  77.                 max-width: 1140px;
  78.             }
  79.         }
  80.  
  81.         #main-view *, ::after, ::before {
  82.             box-sizing: border-box;
  83.         }
  84.  
  85.         #main-view .wrapper {
  86.             display: flex;
  87.             flex-wrap: wrap;
  88.         }
  89.  
  90.         #main-view .wrapper .column-1,
  91.         #main-view .wrapper .column-2 {
  92.             width: 100%;
  93.         }
  94.  
  95.         @media (min-width: 768px) {
  96.             #main-view .wrapper .column-1 {
  97.                 flex: 0 0 66.666667%;
  98.                 max-width: 66.666667%;
  99.                 padding-right: 30px;
  100.             }
  101.  
  102.             #main-view .wrapper .column-2 {
  103.                 flex: 0 0 33.333333%;
  104.                 max-width: 33.333333%;
  105.             }
  106.         }
  107.  
  108.         #video {
  109.             width: 100%;
  110.         }
  111.  
  112.         .embed-responsive {
  113.             position: relative;
  114.             display: block;
  115.             width: 100%;
  116.             padding: 0;
  117.             overflow: hidden;
  118.         }
  119.  
  120.         #main-view .form-group {
  121.             display: flex;
  122.             flex-direction: column;
  123.             margin-bottom: 1em;
  124.         }
  125.  
  126.         #main-view .form-group label {
  127.             margin-bottom: 0.5em;
  128.         }
  129.  
  130.         #main-view .form-control {
  131.             display: block;
  132.             width: 100%;
  133.             height: calc(2.25em + 2px);
  134.             padding: .375em .75em;
  135.             font-size: 1em;
  136.             line-height: 1.5em;
  137.             color: #495057;
  138.             background-color: #fff;
  139.             background-clip: padding-box;
  140.             border: 1px solid #ced4da;
  141.             border-radius: .25em;
  142.         }
  143.  
  144.         #main-view .form-button {
  145.             text-align: center;
  146.             white-space: nowrap;
  147.             border: 1px solid transparent;
  148.             padding: .375em .75em;
  149.             font-size: 1em;
  150.             line-height: 1.5em;
  151.             border-radius: .25em;
  152.             color: #fff;
  153.             background-color: #972e2d;
  154.             border-color: #972e2d;
  155.             margin-bottom: 5px;
  156.         }
  157.  
  158.         #main-view .form-button:hover {
  159.             background-color: #c60000;
  160.             border-color: #c60000;
  161.         }
  162.  
  163.         #main-view .form-button:focus {
  164.             outline: none;
  165.         }
  166.  
  167.         #main-view .embed-responsive::before {
  168.             display: block;
  169.             content: "";
  170.         }
  171.  
  172.         #main-view .embed-responsive .embed-responsive-item {
  173.             position: absolute;
  174.             top: 0;
  175.             bottom: 0;
  176.             left: 0;
  177.             width: 100%;
  178.             height: 100%;
  179.             border: 0;
  180.         }
  181.  
  182.         #main-view .embed-responsive-16by9::before {
  183.             padding-top: 56.25%;
  184.         }
  185.  
  186.         #main-view #level {
  187.             margin-top: 2px;
  188.             width: auto;
  189.             float: right;
  190.         }
  191.  
  192.         #graph {
  193.             max-width: 100%;
  194.             overflow: hidden;
  195.             margin: 3em auto;
  196.             border: 1px solid #eee;
  197.         }
  198.         #chart_container {
  199.             position: relative;
  200.             margin: 3em auto;
  201.             padding-left: 20px;
  202.             max-width: 100%;
  203.         }
  204.  
  205.         #y_axis {
  206.             position: absolute;
  207.             top: 0;
  208.             width: 40px;
  209.             left: -20px;
  210.         }
  211.  
  212.         #y_axis > svg {
  213.             overflow: visible;
  214.         }
  215.  
  216.         #legend {
  217.             position: absolute;
  218.             top: 20px;
  219.             left: 40px;
  220.             z-index: 1;
  221.         }
  222.  
  223.         #legend-totals {
  224.             position: absolute;
  225.             bottom: 20px;
  226.             left: 40px;
  227.             z-index: 1;
  228.         }
  229.  
  230.         #main-view .hide {
  231.             display: none;
  232.         }
  233.  
  234.     </style>
  235.  
  236. </head>
  237. <body>
  238. <div class="container">
  239. <div id="main-view">
  240.     <div id="error-webrtc-data-channels" class="hide">
  241.         WebRTC Data Channels API is not supported by your browser. P2P disabled.<br>
  242.         Read more at <a href="http://iswebrtcreadyyet.com/legacy.html" target="_blank">Is WebRTC ready yet?</a>.
  243.         <hr>
  244.     </div>
  245.     <div id="error-hls-js" class="hide">
  246.         Your browser doesn't support hls.js engine. P2P disabled.<br>
  247.         Read more at <a href="https://en.wikipedia.org/wiki/Media_Source_Extensions" target="_blank">Media Source Extensions</a>.
  248.         <hr>
  249.     </div>
  250.     <div class="wrapper">
  251.         <div class="column-1">
  252.             <div id="video_container"></div>
  253.             <div id="chart_container">
  254.                 <div id="legend"></div>
  255.                 <div id="legend-totals"></div>
  256.                 <div id="y_axis"></div>
  257.                 <div id="chart"></div>
  258.             </div>
  259.         </div>
  260.         <div class="column-2">
  261.             <div id="graph"></div>
  262.            
  263.             <div id="announce"></div>
  264.         </div>
  265.     </div>
  266. </div>
  267.  
  268. <script>
  269.  
  270.     function waitForGlobalObject(objectName, objectNextName) {
  271.         return new Promise((resolve) => {
  272.             function check() {
  273.                 if ((window[objectName] !== undefined)
  274.                         && ((objectNextName === undefined) || window[objectName][objectNextName] !== undefined)) {
  275.                    resolve();
  276.                 } else {
  277.                     setTimeout(check, 200);
  278.                 }
  279.             }
  280.  
  281.             check();
  282.         });
  283.     }
  284.  
  285.     function waitForModule(moduleName) {
  286.         return new Promise((resolve) => {
  287.             function check() {
  288.                 try {
  289.                     resolve(require(moduleName));
  290.                 } catch (e) {
  291.                     setTimeout(check, 200);
  292.                 }
  293.             }
  294.  
  295.             check();
  296.         });
  297.     }
  298.  
  299.     function loadScript(src) {
  300.         return new Promise((resolve, reject) => {
  301.             const script= document.createElement('script');
  302.             script.type= 'text/javascript';
  303.             script.onload = () => {
  304.                 resolve();
  305.             };
  306.             script.onerror = () => {
  307.                 console.log("Failed to load script", src);
  308.                 reject();
  309.             };
  310.             script.src = src;
  311.             document.head.appendChild(script);
  312.         });
  313.     }
  314.  
  315.     function loadStyle(src) {
  316.         return new Promise((resolve, reject) => {
  317.             const link= document.createElement('link');
  318.             link.rel = 'stylesheet';
  319.             link.type= 'text/css';
  320.             link.onload = () => {
  321.                 resolve();
  322.             };
  323.             link.onerror = () => {
  324.                 console.log("Failed to load CSS", src);
  325.                 reject();
  326.             };
  327.             link.href = src;
  328.             document.head.appendChild(link);
  329.         });
  330.     }
  331.  
  332.     class DemoApp {
  333.         async init() {
  334.             await waitForGlobalObject("p2pml", "core");
  335.  
  336.             this.isP2PSupported = p2pml.core.HybridLoader.isSupported();
  337.             if (!this.isP2PSupported) {
  338.                 document.querySelector("#error-webrtc-data-channels").classList.remove("hide");
  339.             }
  340.  
  341.             if (location.protocol == "https:") {
  342.                 document.querySelector("#https-only").classList.remove("hide");
  343.             }
  344.  
  345.             this.liveSyncDurationCount = 7;
  346.  
  347.             this.initForm();
  348.  
  349.             var videoUrlForm = document.getElementById("videoUrlForm");
  350.             this.videoUrl = "http://psrv02.hosting365.hu/media/output.m3u8";
  351.             this.playerType = "jwplayer";
  352.             this.videoContainer = document.getElementById("video_container");
  353.  
  354.             this.loadSpeedTimespan = 10; // seconds
  355.  
  356.             const P2PGraphClass = await waitForModule("p2p-graph");
  357.             this.graph = new P2PGraphClass("#graph");
  358.             this.graph.add({ id: "me", name: "You", me: true });
  359.  
  360.             await waitForGlobalObject("Rickshaw");
  361.             this.initChart();
  362.  
  363.             this.restartDemo();
  364.         }
  365.  
  366.         initForm() {
  367.             var form = document.getElementById("videoUrlForm");
  368.             var params = new URLSearchParams(document.location.search);
  369.  
  370.             var value = params.get("url");
  371.             if (value) {
  372.                 form.url.value = value;
  373.             }
  374.  
  375.             value = params.get("type");
  376.             if (value) {
  377.                 form.type.value = value;
  378.             }
  379.  
  380.             value = params.get("swarm");
  381.             if (value) {
  382.                 this.swarmId = value;
  383.             }
  384.  
  385.             value = params.get("trackers");
  386.             if (value) {
  387.                 this.trackers = value.split(",");
  388.             }
  389.         }
  390.  
  391.         async restartDemo() {
  392.             this.downloadStats = [];
  393.             this.downloadTotals = { http: 0, p2p: 0 };
  394.             this.uploadStats = [];
  395.             this.uploadTotal = 0;
  396.  
  397.             while (this.videoContainer.hasChildNodes()) {
  398.                 this.videoContainer.removeChild(this.videoContainer.lastChild);
  399.             }
  400.  
  401.             const config = {
  402.                 segments: {
  403.                     swarmId: this.swarmId
  404.                 },
  405.                 loader: {
  406.                 cachedSegmentExpiration: 10800000,
  407.                 cachedSegmentsCount: 1000
  408.                 }
  409.             };
  410.  
  411.             if (this.trackers) {
  412.                 config.loader.trackerAnnounce = this.trackers;
  413.             }
  414.  
  415.             switch (this.playerType) {              
  416.                 case "jwplayer":
  417.                     await loadScript("https://cdn.jsdelivr.net/npm/hls.js@latest");
  418.  
  419.                     if (!Hls.isSupported()) {
  420.                         document.querySelector("#error-hls-js").classList.remove("hide");
  421.                     }
  422.  
  423.                     await loadScript(URL_P2P_MEDIA_LOADER_HLSJS);
  424.                     this.engine = this.isP2PSupported ? new p2pml.hlsjs.Engine(config) : undefined;
  425.                     break;
  426.                    
  427.                 default:
  428.                     console.error('Unexpected player type: ', this.playerType);
  429.                     return;
  430.             }
  431.  
  432.             switch (this.playerType) {          
  433.                 case "jwplayer":
  434.                     this.initJwPlayer();
  435.                     break;      
  436.             }
  437.  
  438.             if (this.isP2PSupported) {
  439.                 this.engine.on(p2pml.core.Events.PieceBytesDownloaded, this.onBytesDownloaded.bind(this));
  440.                 this.engine.on(p2pml.core.Events.PieceBytesUploaded, this.onBytesUploaded.bind(this));
  441.  
  442.                 var trackerAnnounce = this.engine.getSettings().loader.trackerAnnounce;
  443.                 if (Array.isArray(trackerAnnounce)) {
  444.                     document.getElementById("announce").innerHTML = trackerAnnounce.join("<br />");
  445.                 }
  446.             }
  447.  
  448.             this.refreshChart();
  449.             this.refreshGraph();
  450.         }
  451.  
  452.         async initJwPlayer() {
  453.             const scriptPromise = await Promise.all([
  454.                 loadScript("https://content.jwplatform.com/libraries/aG3IMhIy.js"),
  455.                 loadScript("https://cdn.jsdelivr.net/npm/@hola.org/jwplayer-hlsjs@latest/dist/jwplayer.hlsjs.min.js")
  456.             ]);
  457.  
  458.             var video = document.createElement("div");
  459.             video.id = "video";
  460.             video.volume = 0;
  461.             video.setAttribute("playsinline", "");
  462.             video.setAttribute("muted", "");
  463.             video.setAttribute("autoplay", "");
  464.             this.videoContainer.appendChild(video);
  465.  
  466.             await scriptPromise;
  467.  
  468.             var player = jwplayer("video");
  469.             player.setup({ file: this.videoUrl, mute: true });
  470.  
  471.             jwplayer_hls_provider.attach();
  472.  
  473.             if (this.isP2PSupported) {
  474.                 p2pml.hlsjs.initJwPlayer(player, {
  475.                     liveSyncDurationCount: this.liveSyncDurationCount,
  476.                     loader: this.engine.createLoaderClass()
  477.                 });
  478.             }
  479.         }
  480.  
  481.         initChart() {
  482.             var chartConf = {
  483.                 element: document.querySelector("#chart"),
  484.                 renderer: 'multi',
  485.                 interpolation: "basis",
  486.                 stack: false,
  487.                 min: 'auto',
  488.                 strokeWidth: 1,
  489.                 series: [
  490.                     {name: "Upload P2P", color: "#88eab9", data: [], renderer: 'area'},
  491.                     {name: " - P2P", color: "#88b9ea", data: [], renderer: 'area'},
  492.                     {name: " - HTTP", color: "#eae288", data: [], renderer: 'area'},
  493.                     {name: "Download", color: "#f64", data: [], renderer: 'line'}
  494.                 ]
  495.             };
  496.  
  497.             this.chart = new Rickshaw.Graph(chartConf);
  498.  
  499.             new Rickshaw.Graph.Axis.X({
  500.                 graph: this.chart,
  501.                 tickFormat: () => ''
  502.             });
  503.  
  504.             new Rickshaw.Graph.Axis.Y({
  505.                 graph: this.chart,
  506.                 orientation: 'left',
  507.                 element: document.getElementById('y_axis')
  508.             });
  509.  
  510.             this.legend = new Rickshaw.Graph.Legend({
  511.                 graph: this.chart,
  512.                 element: document.getElementById('legend')
  513.             });
  514.  
  515.             this.legendTotals = new Rickshaw.Graph.Legend({
  516.                 graph: this.chart,
  517.                 element: document.getElementById("legend-totals")
  518.             });
  519.  
  520.             this.chart.render();
  521.             setInterval(this.updateChartData.bind(this), 500);
  522.  
  523.             var chartResize = () => {
  524.                 chartConf.width = this.chart.element.clientWidth;
  525.                 this.chart.configure(chartConf);
  526.                 this.chart.render();
  527.             };
  528.  
  529.             chartResize();
  530.             window.addEventListener("resize", chartResize);
  531.         }
  532.  
  533.         refreshChart() {
  534.             if (!this.chart) {
  535.                 return;
  536.             }
  537.  
  538.             var data0 = this.chart.series[0].data;
  539.             var data1 = this.chart.series[1].data;
  540.             var data2 = this.chart.series[2].data;
  541.             var data3 = this.chart.series[3].data;
  542.             var lastX = data0.length > 0 ? data0[data0.length - 1].x : -1;
  543.  
  544.             var seriesDataMapper = (currentValue, index) => ({x: index + lastX + 1, y: 0});
  545.  
  546.             data0.length = 0;
  547.             data1.length = 0;
  548.             data2.length = 0;
  549.             data3.length = 0;
  550.  
  551.             var stubData = Array.apply(null, Array(200)).map(seriesDataMapper);
  552.             data0.push.apply(data0, stubData.slice(0));
  553.             data1.push.apply(data1, stubData.slice(0));
  554.             data2.push.apply(data2, stubData.slice(0));
  555.             data3.push.apply(data3, stubData.slice(0));
  556.  
  557.             this.chart.update();
  558.         }
  559.  
  560.         updateChartData() {
  561.             var downloadSpeed = this.getDownloadSpeed();
  562.             var http = Number((downloadSpeed.http * 8 / 1000000).toFixed(2));
  563.             var p2p = Number((downloadSpeed.p2p * 8 / 1000000).toFixed(2));
  564.             var total = Number((http + p2p).toFixed(2));
  565.             var upload = Number(this.getUploadSpeed() * 8 / 1000000).toFixed(2);
  566.  
  567.             var data0 = this.chart.series[0].data;
  568.             var data1 = this.chart.series[1].data;
  569.             var data2 = this.chart.series[2].data;
  570.             var data3 = this.chart.series[3].data;
  571.             var x = data0.length > 0 ? data0[data0.length - 1].x + 1 : 0;
  572.  
  573.             data0.shift();
  574.             data1.shift();
  575.             data2.shift();
  576.             data3.shift();
  577.             data0.push({x: x, y: -upload});
  578.             data1.push({x: x, y: total});
  579.             data2.push({x: x, y: http});
  580.             data3.push({x: x, y: total});
  581.             this.chart.update();
  582.  
  583.             this.formatChartLegendLine(0, total);
  584.             this.formatChartLegendLine(1, http);
  585.             this.formatChartLegendLine(2, p2p);
  586.             this.formatChartLegendLine(3, upload);
  587.  
  588.             this.updateLegendTotals();
  589.         }
  590.  
  591.         formatChartLegendLine(index, speed) {
  592.             if (this.legend) {
  593.                 var line = this.legend.lines[index];
  594.                 line.element.childNodes[1].textContent = line.series.name + ' - ' + speed + ' Mbit/s';
  595.             }
  596.         }
  597.  
  598.         updateLegendTotals() {
  599.             if (!this.legendTotals) {
  600.                 return;
  601.             }
  602.  
  603.             var httpMb = this.downloadTotals.http / 1048576;
  604.             var p2pMb = this.downloadTotals.p2p / 1048576;
  605.             var totalMb = httpMb + p2pMb;
  606.             var uploadMb = this.uploadTotal / 1048576;
  607.  
  608.             if (totalMb != 0) {
  609.                 this.legendTotals.lines[0].element.childNodes[1].textContent
  610.                     = "Download - "
  611.                     + Number(totalMb).toFixed(1) + " MiB";
  612.  
  613.                 this.legendTotals.lines[1].element.childNodes[1].textContent
  614.                     = " - HTTP - "
  615.                     + Number(httpMb).toFixed(1) + " MiB - "
  616.                     + Number((httpMb * 100) / totalMb).toFixed(0) + "%";
  617.  
  618.                 this.legendTotals.lines[2].element.childNodes[1].textContent
  619.                     = " - P2P - "
  620.                     + Number(p2pMb).toFixed(1) + " MiB - "
  621.                     + Number((p2pMb * 100) / totalMb).toFixed(0) + "%";
  622.  
  623.                 this.legendTotals.lines[3].element.childNodes[1].textContent
  624.                     = "Upload P2P - "
  625.                     + Number(uploadMb).toFixed(1) + " MiB";
  626.             }
  627.         }
  628.  
  629.         getDownloadSpeed() {
  630.             var startingPoint = performance.now() - (this.loadSpeedTimespan * 1000);
  631.             var httpSize = 0;
  632.             var p2pSize = 0;
  633.  
  634.             var i = this.downloadStats.length;
  635.             while (i--) {
  636.                 var stat = this.downloadStats[i];
  637.                 if (stat.timestamp < startingPoint) {
  638.                    break;
  639.                }
  640.  
  641.                if (stat.method === "p2p") {
  642.                    p2pSize += stat.size;
  643.                } else if (stat.method === "http") {
  644.                    httpSize += stat.size;
  645.                }
  646.            }
  647.  
  648.            this.downloadStats.splice(0, i + 1);
  649.  
  650.            return {p2p: p2pSize / this.loadSpeedTimespan, http: httpSize / this.loadSpeedTimespan};
  651.        }
  652.  
  653.        getUploadSpeed() {
  654.            var startingPoint = performance.now() - (this.loadSpeedTimespan * 1000);
  655.            var size = 0;
  656.  
  657.            var i = this.uploadStats.length;
  658.            while (i--) {
  659.                var stat = this.uploadStats[i];
  660.                if (stat.timestamp < startingPoint) {
  661.                    break;
  662.                }
  663.  
  664.                size += stat.size;
  665.            }
  666.  
  667.            this.uploadStats.splice(0, i + 1);
  668.  
  669.            return size / this.loadSpeedTimespan;
  670.        }
  671.  
  672.        onBytesDownloaded(method, size) {
  673.            this.downloadStats.push({method: method, size: size, timestamp: performance.now()});
  674.            this.downloadTotals[method] += size;
  675.        }
  676.  
  677.        onBytesUploaded(method, size) {
  678.            this.uploadStats.push({size: size, timestamp: performance.now()});
  679.            this.uploadTotal += size;
  680.        }
  681.  
  682.        refreshGraph(p2pLoader) {
  683.            if (!this.graph) {
  684.                return;
  685.            }
  686.  
  687.            var nodes = this.graph.list();
  688.            for (var i = 0; i < nodes.length; i++) {
  689.                if (nodes[i].id !== "me") {
  690.                    this.graph.disconnect("me", nodes[i].id);
  691.                    this.graph.remove(nodes[i].id);
  692.                }
  693.            }
  694.  
  695.            if (this.isP2PSupported) {
  696.                this.engine.on(p2pml.core.Events.PeerConnect, this.onPeerConnect.bind(this));
  697.                this.engine.on(p2pml.core.Events.PeerClose, this.onPeerClose.bind(this));
  698.            }
  699.        }
  700.  
  701.        onPeerConnect(peer) {
  702.            if (!this.graph.hasPeer(peer.id)) {
  703.                this.graph.add({id: peer.id, name: peer.remoteAddress || 'Unknown'});
  704.                this.graph.connect("me", peer.id);
  705.            }
  706.        }
  707.  
  708.        onPeerClose(id) {
  709.            if (this.graph.hasPeer(id)) {
  710.                this.graph.disconnect("me", id);
  711.                this.graph.remove(id);
  712.            }
  713.        }
  714.  
  715.        constructor() {
  716.            this.hlsLevelSwitcher = {
  717.                auto: "Auto",
  718.                hls: undefined,
  719.                select: undefined,
  720.  
  721.                init: function (hls, select) {
  722.                    if (hls.levelController.levels.length < 2) {
  723.                        select.style.display = "none";
  724.                        return;
  725.                    } else {
  726.                        select.style.display = "block";
  727.                    }
  728.  
  729.                    this.hls = hls;
  730.                    this.select = select;
  731.  
  732.                    this._clearOptions();
  733.                    this._addOption(this.auto);
  734.                    hls.levelController.levels.forEach((e, i) => {
  735.                         var name = [];
  736.                         if (e.height) {
  737.                             name.push(e.height + "p");
  738.                         }
  739.                         if (e.bitrate) {
  740.                             name.push(Math.round(e.bitrate / 1000) + "k");
  741.                         }
  742.                         if (name.length === 0) {
  743.                             name.push("Quality #" + i);
  744.                         }
  745.                         this._addOption(name.join(" / "), i);
  746.                     });
  747.  
  748.                     hls.on(Hls.Events.LEVEL_SWITCHED, this._hlsLevelSwitch.bind(this));
  749.  
  750.                     this.select.addEventListener("change", (event) => {
  751.                         hls.nextLevel = event.target.selectedIndex - 1;
  752.                         this._hlsLevelSwitch();
  753.                     });
  754.                 },
  755.  
  756.                 _hlsLevelSwitch: function () {
  757.                     var auto = this.select.querySelector("option:not([data-index])");
  758.                     var curr = this.select.querySelector("option[data-index='" + this.hls.currentLevel + "']");
  759.                     if (this.hls.autoLevelEnabled || this.hls.currentLevel === -1) {
  760.                         auto.selected = true;
  761.                         auto.text = curr ? curr.text + " (" + this.auto + ")" : this.auto;
  762.                     } else {
  763.                         curr.selected = true;
  764.                         auto.text = this.auto;
  765.                     }
  766.                 },
  767.  
  768.                 _clearOptions: function () {
  769.                     while (this.select.options.length) {
  770.                         this.select.remove(0);
  771.                     }
  772.                 },
  773.  
  774.                 _addOption: function (text, index) {
  775.                     var option = document.createElement("option");
  776.                     option.text = text;
  777.                     if (index !== undefined) {
  778.                         option.dataset.index = index;
  779.                     }
  780.                     this.select.add(option);
  781.                 }
  782.             };
  783.  
  784.            
  785.         }
  786.     }
  787.  
  788.     window.demo = new DemoApp();
  789.     window.demo.init();
  790.  
  791. </script>
  792. </div>
  793. </body>
  794. </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement