Greasy Fork is available in English.
Replaces any default HTML5 player with custom controls
// ==UserScript== // @name Simple HTML5 video player // @description Replaces any default HTML5 player with custom controls // @grant GM_addStyle // @include * // @run-at document-load // @version 8 // @namespace https://greasyfork.org/users/3167 // @license MIT // ==/UserScript== var videowrapper_init = false; function HHMMSS(num) { num = num || 0; var sec_num = Math.floor(num); var hours = Math.floor(sec_num / 3600); var minutes = Math.floor((sec_num - (hours * 3600)) / 60); var seconds = sec_num - (hours * 3600) - (minutes * 60); if (hours < 10) {hours = "0"+hours;} if (minutes < 10) {minutes = "0"+minutes;} if (seconds < 10) {seconds = "0"+seconds;} if (hours<1) { return minutes+':'+seconds; } return hours+':'+minutes+':'+seconds; } function fs_status() { if (document.fullscreenElement) { return 1; } else if (document.webkitFullscreenElement) { return 1; } else if (document.mozFullScreenElement) { return 1; } else return -1; } function init_videowrapper() { var videos = document.getElementsByTagName('video'); for (var i=0; i<videos.length; i++) { (function(video) { if (video.controls==true && !video.iswrapped) { var spacing = 4; var computedStyle = window.getComputedStyle(video); video.controls_timeout=false; video.controls=false; video.iswrapped=true; var videowrapper = document.createElement('videowrapper'); videowrapper.className=video.className; var showui = function() { videowrapper.classList.add("showui"); } var hideui = function() { videowrapper.classList.remove("showui"); } var peekui = function(duration) { duration = duration || 1000; showui(); if (video.controls_timeout) { clearTimeout(video.controls_timeout); } video.controls_timeout = setTimeout(hideui, duration); } var showosd = function() { videowrapper.classList.add("showosd"); } var hideosd = function() { videowrapper.classList.remove("showosd"); } var peekosd = function(duration) { duration = duration || 1000; showosd(); if (video.osd_timeout) { clearTimeout(video.osd_timeout); } video.osd_timeout = setTimeout(hideosd, duration); } var setosd = function(content) { videowrapper.setAttribute("data-osd", content) } setosd('Loading'); if (computedStyle.position == "absolute") { videowrapper.className="absolute"; } else { videowrapper.className="relative"; } if (video.height>0) { videowrapper.style.height=video.height; } if (video.width>0) { videowrapper.style.width=video.width; } video.classList.add("iswrapped"); if (video.parentNode==document.body && document.body.childNodes.length==1) { //document.body.style.display="flex"; //document.body.style.alignItems="center"; //document.body.style.justifyContent="center"; //document.body.style.margin="auto"; //document.body.style.height="100vh"; document.body.className="videobody"; } if (video.parentNode!=videowrapper) { video.parentNode.insertBefore(videowrapper, video); videowrapper.appendChild(video); } var controls = document.createElement('controls'); video.parentNode.insertBefore(controls, video.nextSibling); var playbutton = document.createElement('button'); controls.appendChild(playbutton); playbutton.innerHTML="▶"; playbutton.style.left = spacing + "px"; var timestamp = document.createElement('span'); controls.appendChild(timestamp); timestamp.innerHTML="0:00/0:00"; timestamp.style.left = (spacing + playbutton.clientWidth + spacing) + "px"; var fsbutton = document.createElement('button'); controls.appendChild(fsbutton); fsbutton.innerHTML="□"; fsbutton.style.right = spacing + "px"; var volumebar = document.createElement('input'); controls.appendChild(volumebar); volumebar.type="range"; volumebar.min=0; volumebar.max=1; volumebar.step=0.01; volumebar.value=0.5; volumebar.innerHTML=""; volumebar.style.width="50px"; volumebar.style.right= (spacing + fsbutton.clientWidth + spacing) + "px"; var mutebutton = document.createElement('button'); controls.appendChild(mutebutton); mutebutton.innerHTML="🔊"; mutebutton.style.right=(spacing + volumebar.clientWidth + spacing + fsbutton.clientWidth + spacing) + "px"; var seekbar = document.createElement('input'); controls.appendChild(seekbar); seekbar.type="range"; seekbar.value=0; seekbar.step=0.01; seekbar.innerHTML=""; seekbar.hidden = true; var header = document.createElement('header'); video.parentNode.insertBefore(header, video.nextSibling); var label = document.createElement('label'); header.appendChild(label); label.innerHTML="Loading..."; /* var savebutton = document.createElement('a'); controls.appendChild(savebutton); savebutton.innerHTML="🡇"; savebutton.style.lineHeight="32px"; savebutton.style.position="absolute"; savebutton.style.right="8px"; savebutton.style.bottom="0"; savebutton.style.border="none"; savebutton.style.paddingTop="0"; savebutton.style.paddingBottom="0"; savebutton.style.paddingLeft="4px"; savebutton.style.paddingRight="4px"; savebutton.style.background="none"; savebutton.style.fontFamily="Segoe UI Symbol"; savebutton.style.fontSize="18px"; savebutton.style.margin="0"; savebutton.style.height="32px"; savebutton.href=video.currentSrc; savebutton.download=""; */ var playvideo = function() { video.play(); if (video.livemode) { video.currentTime = video.duration - 3; } } playbutton.addEventListener("click", function() { if (video.paused == true) { playvideo(); } else { video.pause(); } }); video.addEventListener("click", function() { if (video.paused == true) { playvideo(); } else { if (!video.livemode) { video.pause(); } } }); video.addEventListener("play", function() { setosd(playbutton.innerHTML); peekosd(1000); playbutton.innerHTML = "❚❚"; //controls.className="playing"; videowrapper.classList.remove("paused"); videowrapper.classList.add("playing"); }); video.addEventListener("pause", function() { setosd(playbutton.innerHTML); peekosd(3000); playbutton.innerHTML = "▶"; //controls.className="paused"; videowrapper.classList.remove("playing"); videowrapper.classList.add("paused"); }); var updatetimestamp = function() { if (video.livemode) { var buffer = Math.round(video.duration - video.currentTime); timestamp.innerHTML = "Buffer: " + buffer + "s"; } else { timestamp.innerHTML = HHMMSS(video.currentTime) + "/" + HHMMSS(video.duration); } } video.addEventListener("timeupdate", function() { updatetimestamp(); }); video.addEventListener("durationchange", function() { updatetimestamp(); }); mutebutton.addEventListener("click", function() { if (video.muted == false) { video.muted = true; } else { video.muted = false; } }); var togglefs = function() { if (fs_status()>0) { if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); } else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); } else if (document.msExitFullscreen) { document.msExitFullscreen(); } } else { if (videowrapper.requestFullscreen) { videowrapper.requestFullscreen(); } else if (videowrapper.mozRequestFullScreen) { videowrapper.mozRequestFullScreen(); // Firefox } else if (videowrapper.webkitRequestFullscreen) { videowrapper.webkitRequestFullscreen(); // Chrome and Safari } } }; fsbutton.addEventListener("click", togglefs); videowrapper.addEventListener("dblclick", togglefs); seekbar.addEventListener("input", function() { var time = video.duration * (seekbar.value / 100); video.currentTime = time; }); video.addEventListener("timeupdate", function() { var value = (100 / video.duration) * video.currentTime; var progress = (video.currentTime / video.duration); seekbar.value = value; //seekbar.style.background = '-webkit-gradient( linear, left top, right top, color-stop(' + progress + ', var(--range-progress-color)), color-stop(' + progress + ', var(--range-background-color)))'; }); var updatebuffer = function() { if (video.duration == Infinity || video.hls || video.livemode) { video.livemode = true; } if (video.livemode) { seekbar.hidden = true; label.innerHTML = "Live"; } else { var start = video.buffered.length>0 ? ( video.buffered.start(0) / video.duration) : 0; var end = video.buffered.length>0 ? (video.buffered.end(0) / video.duration) : 0; seekbar.hidden = false; seekbar.style.left = (spacing + playbutton.clientWidth + spacing + timestamp.clientWidth + spacing) + "px"; seekbar.style.right= (spacing + mutebutton.clientWidth + spacing + volumebar.clientWidth + spacing + fsbutton.clientWidth + spacing) + "px"; seekbar.style.width='calc(100% - ' + seekbar.style.left + ' - ' + seekbar.style.right + ')'; seekbar.style.background = '-webkit-gradient( linear, left top, right top, color-stop(' + start + ', var(--range-background-color)), color-stop(' + start + ', var(--range-progress-color)), color-stop(' + end + ', var(--range-progress-color)), color-stop(' + end + ', var(--range-background-color)))'; if (video.currentSrc && video.currentSrc.length>0) { label.innerHTML = decodeURIComponent(video.currentSrc.split("/").pop()); } } if (video.videoHeight>0) { videowrapper.classList.remove("audiomode"); videowrapper.classList.add("videomode"); } else { videowrapper.classList.remove("videomode"); videowrapper.classList.add("audiomode"); } }; video.addEventListener("timeupdate", updatebuffer); video.addEventListener("canplay", updatebuffer); video.addEventListener("progress", updatebuffer); video.addEventListener("canplaythrough", updatebuffer); seekbar.addEventListener("mousedown", function() { seekbar.paused = video.paused; video.pause(); }); // Play the video when the slider handle is dropped seekbar.addEventListener("mouseup", function() { if (!seekbar.paused) { video.play(); } }); volumebar.addEventListener("input", function() { video.volume = volumebar.value; }); video.addEventListener('wheel', function(e) { e.preventDefault(); var volumedelta = 0.10; if (e.deltaY < 0) { video.volume = Math.min(video.volume+volumedelta, 1); } if (e.deltaY > 0) { video.volume = Math.max(video.volume-volumedelta, 0); } volumebar.value = video.volume; var volumedata = Math.round(video.volume*100) + "%"; setosd(volumedata); peekosd(1000); }); var updatevolume = function() { if (video.muted || video.volume==0) { mutebutton.innerHTML = "🔇"; } else { mutebutton.innerHTML = "🔊"; } volumebar.style.background = '-webkit-gradient( linear, left top, right top, color-stop(' + video.volume + ', var(--range-progress-color)), color-stop(' + video.volume + ', var(--range-background-color)))'; localStorage.setItem("videovolume", video.volume); } video.addEventListener("volumechange", updatevolume); volumebar.value = localStorage.getItem("videovolume", video.volume); video.volume = volumebar.value; videowrapper.addEventListener("mousemove", function() { peekui(1000); //seekbar.style.background = '-webkit-gradient( linear, left top, right top, color-stop(' + progress + ', var(--range-progress-color)), color-stop(' + progress + ', var(--range-background-color)))'; }); updatebuffer(); updatevolume(); //seekbar.style.background = '-webkit-gradient( linear, left top, right top, color-stop(' + seekbar.value / 100 + ', var(--range-progress-color)), color-stop(' + seekbar.value / 100 + ', var(--range-background-color)))'; //volumebar.style.background = '-webkit-gradient( linear, left top, right top, color-stop(' + video.volume + ', var(--range-progress-color)), color-stop(' + video.volume + ', var(--range-background-color)))'; } })(videos[i]) } } var stylesheet = ` body.videobody { height: 100vh; margin: 0; padding: 0; display: flex; } videowrapper button { font-family: "Segoe UI Symbol", system-ui, sans-serif !important; } videowrapper label, videowrapper:before { font-family: system-ui, sans-serif !important; } videowrapper { --background-color: rgba(0, 0, 0, 0.5); --controls-color: #dcdcdc; --range-progress-color: #8c8c8c; --range-background-color: #3c3c3c; display: block; font-size: 0px; position: relative; width: auto; height: auto; background: inherit; } videowrapper.absolute { display: flex; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; } .videobody videowrapper.absolute { position: relative; } videowrapper video.iswrapped { position: relative; max-height: 100vh; } videowrapper:-webkit-full-page-media { width: auto; height: auto; } videowrapper:-webkit-full-screen { width: 100%; height: 100%; } videowrapper video::-webkit-media-controls-enclosure { display:none !important; } videowrapper:-webkit-full-screen controls, videowrapper:-webkit-full-screen header { z-index: 2147483647; } videowrapper controls > *, videowrapper header > * { color: var(--controls-color); /* mix-blend-mode: difference; */ background: none; outline: none; line-height: 32px; position: absolute; font-family: monospace; } videowrapper controls, videowrapper header { overflow: hidden; white-space: nowrap; transition: all 0.5s ease !important; background: var(--background-color) !important; height: 32px !important; width: 100% !important; display: block !important; position: absolute !important; cursor: default !important; font-size: 18px !important; user-select: none; } videowrapper controls { bottom: 0px !important; } videowrapper header { top: 0px !important; } videowrapper controls, videowrapper header { opacity: 1; } videowrapper.playing controls, videowrapper.playing header { opacity: 0; } videowrapper controls:hover, videowrapper.showui controls, videowrapper.paused controls, videowrapper.audiomode controls, videowrapper header:hover, videowrapper.showui header, videowrapper.paused header, videowrapper.audiomode header { opacity: 1; } videowrapper button, videowrapper label { line-height: 32px !important; position: absolute !important; bottom: 0px !important; background-color: none !important; font-size: 18px !important; height: 32px !important; border: none !important; margin: 0 !important; } videowrapper button { width: 32px !important; padding: 0 !important; } videowrapper input[type=range] { line-height: 32px !important; position: absolute !important; background-color: var(--range-background-color) !important; bottom: 10px !important; height: 10px !important; border: none !important; margin: 0px !important; border-radius: 6px !important; -webkit-appearance: none !important; } videowrapper input[type='range']::-webkit-slider-thumb { -webkit-appearance: none !important; background-color: var(--controls-color); border: none; height: 16px; width: 16px; border-radius: 50%; } videowrapper.audiomode video:-webkit-full-page-media { width: 600px; } videowrapper:before { content: attr(data-osd); position: absolute; left: 50%; top: calc(50%); color: white; -webkit-text-stroke: 3px #333333; font-size: 64px; font-weight: bold; font-style: normal; z-index: 1; transform: translate(-50%, -50%); pointer-events: none; opacity: 0; } videowrapper.audiomode:before, videowrapper.showosd:before, videowrapper.paused:before { opacity: 1; } videowrapper label { right: 0; min-width: 100%; text-align: left; box-sizing: border-box; width: 100% !important; padding: 0px 8px !important; } `; function init() { if (videowrapper_init) { console.log("Cannot init_videowrapper twice!"); return; } videowrapper_init = true; if (typeof GM_addStyle != "undefined") { GM_addStyle (stylesheet); } else { var css = document.createElement("style"); css.type = "text/css"; css.innerHTML = stylesheet; document.head.appendChild(css); } init_videowrapper(); if (typeof unsafeWindow != "undefined") { unsafeWindow.init_videowrapper = init_videowrapper; } } init();