DEV Community

Cover image for Create a custom video player in React πŸ“½οΈ
Avneesh Agarwal
Avneesh Agarwal

Posted on β€’ Edited on

22 5

Create a custom video player in React πŸ“½οΈ

Wassup guys, in this tutorial we are going to see how to build a custom video player in React. Let's jump straight into it!

jump right in

Setup

Create a new react app



npx create-react-app custom-video-player


Enter fullscreen mode Exit fullscreen mode

Cleanup

  • Delete everything in the app div in App.js.


import "./App.css";

function App() {
  return <div className="app"></div>;
}

export default App;


Enter fullscreen mode Exit fullscreen mode
  • Delete everything in App.css

  • in index.css add-



* {
  margin: 0;
}


Enter fullscreen mode Exit fullscreen mode

Create the UI for our Video player

Adding the Video

Inside the app div add a video tag with the src of your video, I am also going to add a className for styling-



 <video
    className="video"
    src="https://res.cloudinary.com/dssvrf9oz/video/upload/v1635662987/pexels-pavel-danilyuk-5359634_1_gmixla.mp4"
 ></video>


Enter fullscreen mode Exit fullscreen mode

Adding the controls of the videos

Below the video component, I will add this div which has some Svgs as icons. You can use direct Svgs like me or use an icon library for the icons :).



  <div className="controlsContainer">
        <div className="controls">
          <img className="controlsIcon" alt="" src="/backward-5.svg" />
          <img className="controlsIcon--small" alt="" src="/play.svg" />
          <img className="controlsIcon" alt="" src="/forward-5.svg" />
        </div>
  </div>


Enter fullscreen mode Exit fullscreen mode

Adding the progress bar for time

We are also going to create a progress bar that shows the current time and total time of the video.



 <div className="timecontrols">
        <p className="controlsTime">1:02</p>
        <div className="time_progressbarContainer">
          <div style={{ width: "40%" }} className="time_progressBar"></div>
        </div>
        <p className="controlsTime">2:05</p>
   </div>


Enter fullscreen mode Exit fullscreen mode

Forgive me for not having very good naming conventions in classes. I have forgotten how to name my classes because of Tailwind :P

Styling the UI

The video player looks very ugly right now, so let's style it. In App.css I am going to add some stylings-



/* Main Container */

.app {
  display: flex;
  flex-direction: column;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

/* Video */

.video {
  width: 100vw;
  height: 100vh;
}

/* Controls */

.controlsContainer {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100vw;
  background-color: transparent;
  margin-top: -50vw;
  padding: 0 40px;
  z-index: 20;
}

.controls {
  display: flex;
  align-items: center;
  justify-content: space-evenly;
  padding-top: 18rem;
  margin: auto;
}

.controlsIcon {
  width: 40px;
  height: 40px;
  cursor: pointer;
  margin-left: 10rem;
  margin-right: 10rem;
}

.controlsIcon--small {
  width: 32px;
  height: 32px;
  cursor: pointer;
  margin-left: 10rem;
  margin-right: 10rem;
}

/* The time controls section */

.timecontrols {
  display: flex;
  align-items: center;
  justify-content: space-evenly;
  position: absolute;
  bottom: 4rem;
  margin-left: 10vw;
}

.time_progressbarContainer {
  background-color: gray;
  border-radius: 15px;
  width: 75vw;
  height: 5px;
  z-index: 30;
  position: relative;
  margin: 0 20px;
}

.time_progressBar {
  border-radius: 15px;
  background-color: indigo;
  height: 100%;
}

.controlsTime {
  color: white;
}


Enter fullscreen mode Exit fullscreen mode

Now our video player would look like this-

image.png

Adding the logic to the player

To work on the functionalities we first need to attach a ref to the video with the useRef hook. So follow the steps given below:

  • Create a ref like this-


const videoRef = useRef(null);


Enter fullscreen mode Exit fullscreen mode
  • Import the useRef hook from react


import { useRef } from "react";


Enter fullscreen mode Exit fullscreen mode
  • Attach it to the video


 <video
    ref={videoRef}
    className="video"
    src="https://res.cloudinary.com/dssvrf9oz/video/upload/v1635662987/pexels-pavel-danilyuk-5359634_1_gmixla.mp4"
 ></video>


Enter fullscreen mode Exit fullscreen mode

Play and Pause functionality

For play and pause create a simple function, which takes an argument of control and based on the control it will play or pause the video-



 const videoHandler = (control) => {
    if (control === "play") {
      videoRef.current.play();
    } else if (control === "pause") {
      videoRef.current.pause();
    }
  };


Enter fullscreen mode Exit fullscreen mode

Now in the play.svg image, we will add an onClick function to start the video.



  <img
     onClick={() => videoHandler("play")}
     className="controlsIcon--small"
     alt=""
     src="/play.svg"
     />


Enter fullscreen mode Exit fullscreen mode

If you click on the icon the video will play!

Changing the icon based on the playing/paused state
To achieve this I am going to use the useState hook. Create a playing state like this-



const [playing, setPlaying] = useState(false);


Enter fullscreen mode Exit fullscreen mode

In the const video handler function, we need to change the value onClick of them like this-



const videoHandler = (control) => {
    if (control === "play") {
      videoRef.current.play();
      setPlaying(true);
    } else if (control === "pause") {
      videoRef.current.pause();
      setPlaying(false);
    }
  };


Enter fullscreen mode Exit fullscreen mode

Changing the icon
Where we have the play icon, now we will render it based on a condition with the help of a ternary operator -



  {playing ? (
            <img
              onClick={() => videoHandler("pause")}
              className="controlsIcon--small"
              alt=""
              src="/pause.svg"
            />
          ) : (
            <img
              onClick={() => videoHandler("play")}
              className="controlsIcon--small"
              alt=""
              src="/play.svg"
            />
          )}


Enter fullscreen mode Exit fullscreen mode

Now, we can play and pause the video πŸ₯³

Forwarding and reverting the video

I am going to create very simple functions for this-



 const fastForward = () => {
    videoRef.current.currentTime += 5;
  };

  const revert = () => {
    videoRef.current.currentTime -= 5;
  };


Enter fullscreen mode Exit fullscreen mode

Now we will add these functions as onClick of the respective buttons.

Forward



<img
  onClick={fastForward}
  className="controlsIcon"
  alt=""
  src="/forward-5.svg"
     />


Enter fullscreen mode Exit fullscreen mode

Revert



<img
  onClick={revert}
  className="controlsIcon"
  alt=""
  src="/backward-5.svg"
     />


Enter fullscreen mode Exit fullscreen mode

Time progress bar

Get the length of the video

To get the length of the video, follow the following steps

  • Give an id to the video component


 <video
    id="video1"
    ref={videoRef}
    className="video"
    src="https://res.cloudinary.com/dssvrf9oz/video/upload/v1635662987/pexels-pavel-danilyuk-5359634_1_gmixla.mp4"
 ></video>


Enter fullscreen mode Exit fullscreen mode
  • Create a state to store the video length


const [videoTime, setVideoTime] = useState(0);


Enter fullscreen mode Exit fullscreen mode
  • Set the video time like this on the play of the video


if (control === "play") {
      videoRef.current.play();
      setPlaying(true);
      var vid = document.getElementById("video1");
      setVideoTime(vid.duration);
    }


Enter fullscreen mode Exit fullscreen mode

Now we can use the videoTime variable instead of hardcoded time. This string manipulation will make the time in a format like- 1:05



  <p className="controlsTime">
    {Math.floor(videoTime / 60) + ":" + ("0" + Math.floor(videoTime % 60)).slice(-2)}
 </p>


Enter fullscreen mode Exit fullscreen mode

Getting the current time of the video

To get the current time of video we will need to use a function that runs every second, so I am going to use window.setInterval for the same.



window.setInterval(function () {
    setCurrentTime(videoRef.current?.currentTime);
  }, 1000);


Enter fullscreen mode Exit fullscreen mode

Now as always, we need to create a state to store the value-



const [currentTime, setCurrentTime] = useState(0);


Enter fullscreen mode Exit fullscreen mode

Instead of the hard code value, we will use the variable



<p className="controlsTime">
    {Math.floor(currentTime / 60) + ":" + ("0" + Math.floor(currentTime % 60)).slice(-2)}
</p>


Enter fullscreen mode Exit fullscreen mode

Getting the progress and setting it to the progress bar

Create another state for progress-



const [progress, setProgress] = useState(0);


Enter fullscreen mode Exit fullscreen mode

Now inside the window.setInterval function that we created, add another line-



setProgress((videoRef.current?.currentTime / videoTime) * 100);


Enter fullscreen mode Exit fullscreen mode

The function would look like this now-



window.setInterval(function () {
    setCurrentTime(videoRef.current?.currentTime);
    setProgress((videoRef.current?.currentTime / videoTime) * 100);
  }, 1000);


Enter fullscreen mode Exit fullscreen mode

Our custom video player is now ready πŸŽ‰πŸŽŠ

Useful links-

GitHub repository

ReactJS docs

All socials

SurveyJS custom survey software

JavaScript Form Builder UI Component

Generate dynamic JSON-driven forms directly in your JavaScript app (Angular, React, Vue.js, jQuery) with a fully customizable drag-and-drop form builder. Easily integrate with any backend system and retain full ownership over your data, with no user or form submission limits.

Learn more

Top comments (3)

Collapse
 
baileys profile image
Arthur Li β€’

Try a onTimeUpdate event. I think it's better than creating Intervals update

Collapse
 
avneesh0612 profile image
Avneesh Agarwal β€’

Oh cool. I will try it

Collapse
 
consultantvengage profile image
Rahul Pandey β€’

Does not work. Do you have a demo version running somewhere

πŸ‘‹ Kindness is contagious

Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.

A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!

On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.

Okay