Skip to content

Instantly share code, notes, and snippets.

@simonhaenisch
Last active June 22, 2023 01:30
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save simonhaenisch/116010ed657f6b257246464e33719613 to your computer and use it in GitHub Desktop.
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.
<!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>
@rubyFeedback
Copy link

Could you comment / explain how to set this file up?

@gogodee
Copy link

gogodee commented Mar 24, 2020

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.

@ordinat05
Copy link

sorry, why didn't it work? didn't work but didn't write? "Not allowed to load local resource:" Please turn back

@ordinat05
Copy link

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