// @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3-or-Later function setup_playback(description) { document.getElementById("no-script").classList.remove("noscript"); document.getElementById("controls").classList.add("javascript"); video_manifest = description; console.log(description); player = document.getElementById("player"); player.addEventListener("pause", (event) => playStateChanged(false)); player.addEventListener("playing", (event) => playStateChanged(true)); filteredOptions = filterOptions(description.entries); if(filteredOptions.length == 0){ player.src = "invalid://invalid"; document.getElementById("unplayable-modal").showModal(); return; } player.src = filteredOptions[0].path; qualitySelector = document.getElementById("quality-selector"); filteredOptions.forEach(option => { opt = document.createElement("option") opt.value = option.path; opt.innerHTML = option.label; qualitySelector.appendChild(opt); }); startRes = findOptimalOptionForScreen(filteredOptions); qualitySelector.value = startRes.path qualitySelected(); doSpeedTest(startRes, filteredOptions); } function qualitySelected() { qualitySelector = document.getElementById("quality-selector"); player = document.getElementById("player"); paused = player.paused; time = player.currentTime; player.src = qualitySelector.value; player.load(); player.currentTime = time; if(!paused) { player.play(); } } function filterOptions(options) { player = document.getElementById("player"); return options.filter(o => o.type === "video" && canPlayStream(o) && (o.metadata.alternative_to == undefined || !canPlayStream(options.find(s => s.label == o.metadata.alternative_to)))); } function canPlayStream(stream) { player = document.getElementById("player"); return player.canPlayType(`${stream.mimetype}; codecs="${stream.metadata.codecs}"`); } function findOptimalOptionForScreen(options) { screenSize = Math.max(window.screen.width, window.screen.height); screenSize = screenSize * window.devicePixelRatio filtered = options.filter(o => o.type === "video" && Math.max(o.metadata.size.split("x")[0], o.metadata.size.split("x")[1]) <= screenSize); console.log(filtered); if(filtered.length == 0){ return options[options.length - 1]; } return filtered[0]; } function downloadVideo() { document.getElementById("download-modal").showModal(); } function showInfo() { document.getElementById("info-modal").showModal(); } function shareVideo() { document.getElementById("share-modal").showModal(); } function playStateChanged(playing) { controls = document.getElementById("controls") if(playing) { controls.classList.remove("paused") } else { controls.classList.add("paused") } } function doSpeedTest(currentOption, options) { startTime = window.performance.now(); request = new XMLHttpRequest(); request.onreadystatechange = function() { if(request.readyState === 2) { // Reset start time, headers received. startTime = window.performance.now(); } if(request.readyState === 4 && (request.status === 200 || request.status === 206)) { endTime = window.performance.now(); size = request.response.size; rate = size / ((endTime - startTime) / 1000) console.log(`Detected connection rate: ${rate} bytes/sec`); filtered = options.filter(o => o.type === "video" && o.byterate < rate); if(filtered.length == 0) { filtered = [options[options.length - 1]]; } optimal = findOptimalOptionForScreen(filtered); if(optimal !== currentOption) { qualitySelector.value = optimal.path console.log("Switched res"); qualitySelected(); } else { console.log("Got it right first try B)"); } } } requestSize = Math.min(options[0].filesize, Math.round(options[0].byterate)); request.open("GET", options[0].path); request.responseType = "blob"; request.setRequestHeader("Range", `bytes=0-${requestSize}`); request.send(); } // @license-end