NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name i-Achelois.videoPlayer
// @namespace https://zaw.li
// @version 0.1
// @description Adds a variable speed slider into the (i-)NTULearn recorded lectures
// @author Lit3Nitride
// @homepage https://github.com/Lit3Nitride/i-Achelois
// @license GPL-3.0+; http://www.gnu.org/licenses/gpl-3.0.txt
// @match https://*.ntu.edu.sg/aculearn*
// @grant none
// ==/UserScript==
(function() {
'use strict';
// Set up the variables.
//
// btn
// is one of the radio buttons that we'll
// keep and use to actually change the speed
//
// slider
// is the volume slider we'll insert
//
// sliderNum
// is the text box that displays the current speed
//
// sliderText
// is the rounded speed multiplied by 100
// so that we can display 2 decimal places
var btn, slider, sliderNum, sliderText
// This is the function that keeps checking
// for the video player to be loaded before
// starting the script proper
(function load() {
btn = document.getElementById("mep_0_rate_25")
if (btn === null)
setTimeout(load, 100)
else
init()
})()
// Setup of the rest of the script once the video player is loaded
function init() {
// Remove the annoying thumbnail nonsense
document.getElementById("div_index").parentNode.removeChild(document.getElementById("div_index"))
// The container of all the speed selectors
var rateSelect = document.getElementsByClassName("mejs-rate-selector")[0]
// Resize the container since we now need only to fit the slider
rateSelect.style["height"] = "25px"
rateSelect.style["width"] = "150px"
rateSelect.style["margin-bottom"] = "-5px"
// Make the first radio button invisible (without removing it)
rateSelect.children[0].rows[0].style["display"] = "none"
// Add in the slider and the current speed text box
rateSelect.children[0].rows[1].innerHTML = '\
<td>\
<input type="range" min="52.5" max="200" value="100" id="btnSlider" step="any" style="width:80%;">\
</td>\
<td style="color: white">\
<span id="sliderNum">1.00</span>×\
</td>'
// Assign the newly created elements into our pre-defined variables
slider = document.getElementById("btnSlider")
sliderNum = document.getElementById("sliderNum")
// Remove the rest of the speed buttons
for (var i=rateSelect.children[0].rows.length-1; i>1; i--)
rateSelect.children[0].rows[i].remove()
// Assign the trigger that handles speed change to changes of the slider
rateSelect.children[0].rows[1].children[0].children[0].onmousedown = function() {trigger(true)}
rateSelect.children[0].rows[1].children[0].children[0].onmouseup = trigger
rateSelect.children[0].rows[1].children[0].children[0].onchange = trigger
// Make the rate button a "reset" button (like how clicking on
// the volume button mutes the video
document.getElementsByClassName("mejs-rate-button")[0].children[0].onclick = function(){
slider.value = 100
doTrigger()
}
}
// Precheck to see if the speed should be continually updated
function trigger(triggerStart) {
// Check if the mouse button is being held down
// If so, keep updating the speed
window.isTriggered = typeof triggerStart == "undefined" ? false:triggerStart
setTimeout(doTrigger, 20)
}
// The actual changing of speed
function doTrigger() {
// We interpolate the slider so that
//
// 1. Have the values that correspond to the original speed buttons
// f(2) -> 8.00
// f(1) -> 1.00
// f(?) -> 0.25
//
// 2. Have |f'(1)| < f'(2) and f'(1) < f'( ? ) because when we are closer
// to speed 1.00, we want to fine-tune it more, but when we are further
// from 1.00, we just want the video to be really fast or really slow
// so we want the slider to change more further from there
//
// A polynomial curve of order 3 centered about x=1 fits this description,
// then we solve for the parameters
btn.value = 7*(slider.value/100 - 1)**3+1
// Multiply the value by 100 and round it, which corresponds to 2 decimal places
sliderText = Math.round(btn.value*100)
// Print it out with the decimal point
sliderNum.textContent = (sliderText < 100 ? 0:sliderText.toString().substr(0,1)) + "." + sliderText.toString().substr(sliderText >= 100)
// Basically we've changed the value of the lone radio survivor into
// the speed we want and click it
btn.click()
// Keep repeating if the mouse is still triggered
if (window.isTriggered)
setTimeout(doTrigger, 20)
}
})();