My project is about user chooses a directory and then the program takes all the videos inside the directory and via help of a video player then shows the content of the video. This photo might explain the project layout: (Right side is where you choose the video and left side is where the video plays)
I have used vanilla javascript so far. here is the code:
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Video Player</title>
</head>
<body>
<div class="select-folder-div">
<input type="file" name="file" id="file-selector" class="file-selector"
webkitdirectory multiple>
</div>
<div class="main-div">
<div class="video-player-div" id="video-player-div">
</div>
<div class="video-chooser-div" id="video-chooser-div">
</div>
</div>
<script src="index.js"></script>
</body>
</html>
CSS:
body {
background: rgb(34, 32, 32);
color: rgb(204, 87, 204);
font-size: 1.5em;
font-family:'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans
Unicode', Geneva, Verdana, sans-serif;
}
.main-div {
display: flex;
flex-direction: row;
}
.video-player-div{
display: flex;
align-items: center;
align-self: flex-start;
border: 5px solid rgb(204, 87, 204);
width: 70%;
margin-top: 5%;
margin-bottom: 10%;
margin-left: 3%;
margin-right: 3%;
padding: 3%;
}
.video-chooser-div {
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-items: flex-start;
gap: 20px;
border: 5px solid rgb(204, 87, 204);
width: 21%;
margin-top: 5%;
margin-bottom: 10%;
margin-right: 3%;
padding: 3%;
overflow: auto;
}
.file-selector {
margin-left: 45%;
margin-top: 3%;
}
.video-name:hover {
cursor: pointer;
color: blueviolet;
}
.video-name:active {
color: rgb(99, 14, 178);
}
Javascript:
const directoryInput = document.getElementById("file-selector");
const videoChooser = document.getElementById("video-chooser-div");
const videoPlayer = document.getElementById("video-player-div");
directoryInput.addEventListener("change", (event) => {
videoChooser.innerHTML = "";
for (const file of event.target.files) {
if (file.name.endsWith(".mp4")) {
let videoContentDiv = document.createElement("div");
videoContentDiv.className = "video-content";
let videoName = file.name;
let videoNameTag = document.createElement("p");
videoNameTag.className = "video-name";
videoNameTag.textContent = videoName;
videoContentDiv.appendChild(videoNameTag);
videoChooser.appendChild(videoContentDiv);
videoContentDiv.addEventListener("click", () => {
videoPlayer.innerHTML = "";
const video = document.createElement("video");
const reader = new FileReader();
reader.onload = (event) => {
video.src = event.target.result;
console.log(video.src)
};
reader.readAsDataURL(file);
video.width = "100%";
video.controls = true;
videoPlayer.appendChild(video);
});
}
}
}, false);
The Problem is I am able to select a directory and show all the mp4 contents inside it however when I click on the text the video tag doesn't show up. When I check what is inside the div there is indeed a video tag with a base64 code as source, but there is nothing on the screen not even an empty video place. I tried to check the base64, and I think I realized there are empty parts inside the base64 as I scrolled down, and I am not sure if it is normal. Even it is I don't know how to solve it.
You can simplify your code.
Add a static <video>
element to your HTML and hide it via css if src is empty
video[src=""] {
opacity: 0
}
On upload you create an object URL URL.createObjectURL(file);
and save it to the new playlist item.
Then you're adding a click event swapping the current video src attribute with the playlist item's object URL (e.g saved in a data attribute).
const directoryInput = document.getElementById("file-selector");
const videoChooser = document.getElementById("video-chooser-div");
const videoPlayer = document.getElementById("video-player-div");
directoryInput.addEventListener("change", (event) => {
videoChooser.innerHTML = "";
for (const file of event.target.files) {
if (file.name.endsWith(".mp4")) {
let videoContentDiv = document.createElement("div");
videoContentDiv.className = "video-content";
// add playlist items
let videoName = file.name;
let videoNameTag = document.createElement("p");
videoNameTag.className = "video-name";
videoNameTag.textContent = videoName;
// create object url and save it in data attribute
videoNameTag.dataset.src = URL.createObjectURL(file);
// play playlist item on click
videoNameTag.addEventListener('click', e => {
video.src = e.currentTarget.dataset.src;
video.play()
})
videoContentDiv.appendChild(videoNameTag);
videoChooser.appendChild(videoContentDiv);
}
}
}, false);
body {
background: rgb(34, 32, 32);
color: rgb(204, 87, 204);
font-size: 1.5em;
font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans
Unicode', Geneva, Verdana, sans-serif;
}
.main-div {
display: flex;
flex-direction: row;
}
.video-player-div {
display: flex;
align-items: center;
align-self: flex-start;
border: 5px solid rgb(204, 87, 204);
width: 70%;
margin-top: 5%;
margin-bottom: 10%;
margin-left: 3%;
margin-right: 3%;
padding: 3%;
}
.video-chooser-div {
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-items: flex-start;
gap: 20px;
border: 5px solid rgb(204, 87, 204);
width: 21%;
margin-top: 5%;
margin-bottom: 10%;
margin-right: 3%;
padding: 3%;
overflow: auto;
}
.file-selector {
margin-left: 45%;
margin-top: 3%;
}
.video-name:hover {
cursor: pointer;
color: blueviolet;
}
.video-name:active {
color: rgb(99, 14, 178);
}
/* hide empty video elements */
video[src=""] {
opacity: 0
}
<div class="select-folder-div">
<input type="file" name="file" id="file-selector" class="file-selector" multiple>
</div>
<div class="main-div">
<div class="video-player-div" id="video-player-div">
<video id="video" style="width:100%; height:100%" src="" controls>
</video>
</div>
<div class="video-chooser-div" id="video-chooser-div">
</div>
</div>
This approach should be more efficient than creating a base64 data URL. Also, you might encounter problems due to URL length limitations when using base64.