Custom HTML video player
Tags: html, css, javascript
Published: 2023-05-14 05:12:16

Hello developers! In this tutorial I will teach you all how you can create your custom HTML video player using css and JavaScript.

First Let's create the basic html structure:

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Custom Video Player - HTML, CSS and JavaScript</title>
    <link href="./style.css" rel="stylesheet">
</head>
<body>
    <div class="container">
        <div class="video-container">
            <video src="./video.mp4" width="100%" height="auto" id="video"></video><br>
        </div>
        <div class="progress-container">
            <span id="currentTime"></span>&nbsp;<input type="range" name="seekbar" id="seekbar" min="0" max="100" style="width: 100%;">&nbsp;<span id="videoDuration"></span>
        </div>
        <br>
        <div style="margin: auto; display: block;">
            <div class="controllers">
                <div class="play-controllers">
                    <button class="btn" id="rewindBtn"><span class="material-icons">fast_rewind</span></button>
                    <button class="btn" id="playBtn"><span class="material-icons">play_circle</span></button>
                    <button class="btn" id="forwardBtn"><span class="material-icons">fast_forward</span></button>
                </div>
                <div class="volume-controllers">
                    <button class="btn" id="muteBtn"><span class="material-icons">volume_off</span></button>
                    <span class="material-icons" id="volume_icon">volume_up</span>
                    <input type="range" name="volume" id="volume" min="0" max="100" style="width: 100%;">
                    <span id="volumePercent"></span>
                </div>
            </div>
        </div>
    </div>

    <script src="./script.js"></script>
</body>
</html>
```

Next we will write the css for designing our pages
```css
@import url('https://fonts.googleapis.com/icon?family=Material+Icons');
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap');

* {
  margin: 0;
  padding: 0;
  font-family: 'Inter', sans-serif;
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  background: skyblue;
}

.container {
  width: 50%;
  background: white;
  padding: 8px;
  border-radius: 4px;
}

.video-container {
  padding: 6px;
  background: #000;
  border-radius: 4px;
}

.progress-container {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.volume-controllers {
  display: flex;
  align-items: center;
}

.btn {
  width: fit-content;
  height: fit-content;
  padding: 2px;
  cursor: pointer;
  background: #d3d3d3;
  border: none;
  border-radius: 4px;
}

.material-icons {
  display: inline-block;
  font-size: 24px;
  line-height: 1;
  vertical-align: middle;
  padding-bottom: 0;
}

.controllers {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
```

At last let us wrap up by completing the javascript logic
```javascript
// Initialize the global variables
let video = document.getElementById("video"); 
let playBtn = document.getElementById("playBtn");
let videoDuration = document.getElementById("videoDuration");
let currentTime = document.getElementById("currentTime");
let volume = document.getElementById("volume");
let volume_icon = document.getElementById("volume_icon");
let volumePercent = document.getElementById("volumePercent");
let muteBtn = document.getElementById("muteBtn");
let seekbar = document.getElementById("seekbar");
let rewindBtn = document.getElementById("rewindBtn");
let forwardBtn = document.getElementById("forwardBtn");

// Set the seekbar value to current time of the video
seekbar.value = video.currentTime;
currentTime.innerHTML = '0:0:0' // Set the initial value of current time to 0:0:0

video.addEventListener("loadedmetadata", () => {
    const duration = Math.floor(video.duration); // Get the video duration
    // Get hours, minutes and seconds from the duration
    const hours = Math.floor(duration / 3600);
    const minutes = Math.floor((duration - (hours * 3600)) / 60);
    const seconds = duration - (hours * 3600) - (minutes * 60);
    videoDuration.innerHTML = `${hours}:${minutes}:${seconds}`;

    // Set the initial video volume to 0.5 (50%)
    video.volume = 0.5;
    volume.value = video.volume * 100;
    volumePercent.innerHTML = `${volume.value}%`
})

// Play the video
playBtn.addEventListener("click", () => {
    if (video.paused) {
        video.play();
        // Update the current timestamp of the video
        video.addEventListener("timeupdate", () => {
            const duration = Math.floor(video.currentTime);
            const hours = Math.floor(duration / 3600);
            const minutes = Math.floor((duration - (hours * 3600)) / 60);
            const seconds = duration - (hours * 3600) - (minutes * 60);
            currentTime.innerHTML = `${hours}:${minutes}:${seconds}`;
            // Update the seekbar value
            seekbar.value = (video.currentTime / video.duration) * 100;
        })
        playBtn.innerHTML = `<span class="material-icons">pause_circle</span>`;
    } else {
        video.pause();
        playBtn.innerHTML = `<span class="material-icons">play_circle</span>`;
    }
})

// Reset all the values when video has ended
video.addEventListener("ended", () => {
    seekbar.value = 0;
    video.currentTime = 0;
    playBtn.innerHTML = `<span class="material-icons">play_circle</span>`;
})

let interval;
// Rewind the video for 10 seconds
rewindBtn.addEventListener("mousedown", () => {
    interval = setInterval(() => {
        video.currentTime -= 10;
    }, 100)
})
rewindBtn.addEventListener("mouseup", () => {
   clearInterval(interval)
})

// Forward the video for 10 seconds
forwardBtn.addEventListener("mousedown", () => {
    interval = setInterval(() => {
        video.currentTime += 10;
    }, 100)
})
forwardBtn.addEventListener("mouseup", () => {
   clearInterval(interval)
})

// Switch to the particular timestamp of the video on seekbar changes
seekbar.addEventListener("input", () => {
    let duration = video.duration;
    let progress = seekbar.value;
    let currentTime = (progress / 100) * duration;
    video.currentTime = currentTime;
    const totalSeconds = Math.floor(video.currentTime);
    const hours = Math.floor(totalSeconds / 3600);
    const minutes = Math.floor((totalSeconds - (hours * 3600)) / 60);
    const seconds = totalSeconds - (hours * 3600) - (minutes * 60);
    currentTime.innerHTML = `${hours}:${minutes}:${seconds}`;
})

// Volume change functionality
volume.addEventListener("input", (e) => {
    video.volume = e.target.value / 100;
    volumePercent.innerHTML = `${e.target.value}%`
    if (e.target.value == 0) {
        volume_icon.innerHTML = 'volume_off'
    } else {
        volume_icon.innerHTML = 'volume_up'
    }
})

// Mute or Unmute the video
muteBtn.addEventListener("click", () => {
    if (video.muted) {
        volume.value = video.volume * 100;
        video.muted = false; // Unmute the video
        volume_icon.innerHTML = 'volume_up'
        muteBtn.innerHTML = `<span class="material-icons">volume_off</span>`;
    } else {
        volume.value = 0;
        video.muted = true; // Mute the video
        volume_icon.innerHTML = 'volume_off'
        muteBtn.innerHTML = `<span class="material-icons">volume_up</span>`;
    }
    volumePercent.innerHTML = `${volume.value}%`
})
```
Test the above code and like this post if you like my project.