Last active
March 25, 2025 10:37
-
-
Save simonhaenisch/116010ed657f6b257246464e33719613 to your computer and use it in GitHub Desktop.
Play local video files in the browser (HTML5 video player) with playlist, speed control and keyboard shortcuts for pause (spacebar) and 5 second jump (left/right arrow). Created to watch Wes Bos tutorials offline. Playback speed defaults to 2x.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Local HTML5 Video Player</title> | |
</head> | |
<body> | |
<style> | |
* { box-sizing: border-box; } | |
body { margin: 0; font-family: sans-serif; } | |
video { | |
z-index: 1; | |
display: block; | |
margin: 0 auto; | |
background-color: #ccc; | |
/* maximize video player size within viewport while maintaining 16:9 format */ | |
width: 100vw; | |
height: 56.25vw; | |
max-width: 177.78vh; | |
max-height: 100vh; | |
} | |
@keyframes fadeOut { | |
0% { opacity: 1; } | |
95% { opacity: 1; } | |
100% { opacity: 0; } | |
} | |
.fadeout { animation: fadeOut 1s linear; } | |
input, ul, a { | |
position: absolute; | |
z-index: 2; | |
opacity: 0; | |
transition: opacity 0.15s ease-out; | |
} | |
input:hover, ul:hover, a:hover { opacity: 1; } | |
input[type=file] { display: none; } | |
a { | |
display: block; | |
width: 100%; | |
background-color: rgba(0, 0, 0, 0.7); | |
text-align: center; | |
text-decoration: none; | |
text-transform: uppercase; | |
color: white; | |
left: 0; | |
top: 0; | |
padding: 2em; | |
font-size: 1.5em; | |
} | |
input[type=text] { | |
bottom: 1.5em; | |
left: 1em; | |
font-size: 1.5em; | |
width: 4em; | |
text-align: center; | |
border: 1em solid rgba(0, 0, 0, 0.7); | |
} | |
ul { | |
margin: 0; | |
padding: 0 0 0 1em; | |
top: 0; | |
right: 0; | |
color: white; | |
background-color: rgba(0, 0, 0, 0.7); | |
list-style: none; | |
} | |
li { | |
margin: 0.5em; | |
cursor: pointer; | |
} | |
li.played { | |
text-decoration: line-through; | |
list-style: square; | |
} | |
</style> | |
<video controls autoplay></video> | |
<input type="file" multiple> | |
<a class='fadeout' href="#">Open Files</a> | |
<input class='fadeout' type="text" placeholder="playback speed" value="2"> | |
<ul></ul> | |
<script> | |
// get DOM elements | |
const video = document.querySelector('video'); | |
const filesInput = document.querySelector('input[type=file]'); | |
const speedInput = document.querySelector('input[type=text]'); | |
const filesButton = document.querySelector('a'); | |
const playlist = document.querySelector('ul'); | |
// redirect filesButton click to hidden filesInput | |
filesButton.addEventListener('click', e => { | |
filesInput.click(); | |
e.preventDefault(); | |
return false; | |
}); | |
filesInput.addEventListener('change', function (e) { | |
// delete all current list items in playlist | |
playlist.innerHTML = ''; | |
// go through all selected files | |
for (const file of Array.from(this.files)) { | |
// create list item and object url for the video file | |
const listItem = document.createElement('li'); | |
listItem.objUrl = URL.createObjectURL(file); | |
listItem.textContent = file.name; | |
// give list item a click event listener for the corresponding video | |
listItem.addEventListener('click', function (e) { | |
this.classList.add('played'); | |
video.src = this.objUrl; | |
video.playbackRate = Number(speedInput.value); | |
}); | |
// append li to the list | |
playlist.appendChild(listItem); | |
}; | |
// show the playlist for a moment | |
playlist.classList.add('fadeout'); | |
}, false /* don't capture */); | |
// remove playlist fadeout after the animation ends, so it can be retriggered | |
playlist.addEventListener('animationend', e => { | |
playlist.classList.remove('fadeout'); | |
}); | |
// handle changes to speed input | |
speedInput.addEventListener('change', e => { | |
video.playbackRate = Number(speedInput.value); | |
// write actual playback rate value back to input | |
speedInput.value = Number(video.playbackRate); | |
}); | |
// add keyboard shortcuts for pause (space) and 5 sec jump (left/right arrow) | |
document.addEventListener('keydown', e => { | |
// console.log(e.keyCode); | |
switch (e.keyCode) { | |
case 32: // space | |
video.paused ? video.play() : video.pause(); | |
break; | |
case 37: // left arrow | |
video.currentTime += -5; | |
break; | |
case 39: // right arrow | |
video.currentTime += 5; | |
break; | |
} | |
}); | |
</script> | |
</body> | |
</html> |
Could you comment / explain how to set this file up?
You just save the HTML file and open it on a browser.
Then, if you hover your mouse on top, you'll see an Open File button. Select all the video files and click open.
Now, you can control the playback speed in the bottom left corner, when you hover your mouse over it.
In the top right corner, there's a playlist and on top, there's open file button.
sorry, why didn't it work? didn't work but didn't write? "Not allowed to load local resource:" Please turn back
how to make disable "Not allowed to load local resource:" browser settings ?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Could you comment / explain how to set this file up?