Back
Developing a React Video Player with Personalized Controls
The React Player plugin can help you add a video player to your website in a few minutes. Let's we'll build a customizable React video player from scratch.
Web technology has developed a lot over the years; Javascript, in particular, has played an enormous role in it. By involving React, the development and use of UI have become better and more efficient. With React, including an audio-video player on any website is easy. A simple React player plugin may assist you in performing the task in a few minutes. In this article, we'll talk about how to build a customizable React video player from scratch.
Introduction
React-Player is a React component that plays audio-visual files from various URLs, including file paths, YouTube links, Facebook links, Twitch links, SoundCloud links, Streamable links, Vimeo links, Wistia links, Mixcloud links, DailyMotion links, Kaltura links, and so on.
In this post, we'll use the React-Player component to build a video player (which you can install with the React Player npm), while focusing more on its functionalities than its appearance. To follow this tutorial, you'll need to have Node.js installed locally on your machine and have some familiarity with Material UI, Javascript, and React.
Features of React-Player
Customizable and easy-to-use
Runs on diffrent URLs, including file paths
Supports video looping and play back rates
Installing Dependencies
Running the following commands in the terminal allows us to start by setting up the project and installing the necessary dependencies:
Let's start by importing ReactPlayer
into our App.js file and updating it.
The react-player
component is now inside a Container
wrapper. Additionally, we supplied the link to the example video as the URL prop's value. Finally, we also provided the player with a set width
and height
of 100%, so it will be responsive.
Then, add the following code to your App.css file.
To enable playback within our video player React, we added the playing
and muted
props to the preceding code. In addition, we set a value of true
in place of the default value of false
for the props. As a result, the playing
footage created by the above code is shown in the picture below:
Observe that the video player is not interactive and lacks any controls. The react-player
package contains a prop called control
that, by default, has a value of false
. When the value is modified to true
, the React player controls are automatically added.
React Player Functionalities
Let's begin by creating a new folder in the src
folder named Components
. Then, create the Control.jsx and Control.css files as two new files inside the newly formed folder.
Let’s Code
First, we’ll import the required packages for our Control.jsx file:
The control.jsx file is made up of three containers:
The heading container
The middle container (Contains the Play, Rewind and Fast forward buttons)
The bottom container (Contains the Slider, volume and playback rate buttons)
The Heading Container
The Middle Container
The Bottom Container
Our control.jsx React player component will be like this:
Let's discuss the .control_Container
class-named div
element. It’s a distinct container that, if hovered above the custom video player, appears as an overlay.
The following are the styles for our Control.jsx file:
Additionally, we style some of the components by adding the Material UI's makeStyles
and withStyles
to our Control.
Adding the following code to your App.js file will import React’s Controls
component, which we also need to do:
If you followed closely, our React custom video player ought to appear like this:
Handling Play and Pause
In this section, we'll concentrate on the capabilities and logic of the custom controls for the React player, starting with playing and pausing.
Navigate to the App.js file, where we'll begin by defining a state named videoState
. An object with different properties represents this state:
We destructure the videoState
using the ES6 syntax to get its properties.
Following that, we need to create a function that toggles the play and pause capabilities. To do this, we'll spread the previous state and toggle the necessary state.
Replace the true
values for the playing
and muted
properties with the appropriate values of playing
and mute
from the destructured videoState
in the ReactPlayer
component.
The playing
prop in ReactPlayer
is used to set the value to true
or false
, playing or pausing the video.
To allow the play and pause buttons to access this feature, we pass in the function to the Control
component as a prop in the example above.
We’d also update our Control.jsx file by passing the onPlayPause
into the onClick
of our pause button.
The playing attribute value provided within the videoState
, which we passed as a prop to the Control
component, is used to render the icon using the ternary operator conditionally. For example, the play icon should appear when the video is paused, and when it is playing, the pause icon should appear.
With the addition of these functionalities, we can easily play and pause our video, like so:
Handling Rewind and Fast Forward
We want to fast-forward the video by 10 seconds and rewind it by 5 seconds, much like with other video players. The ReactPlayer
must be referenced using the useRef
hook to obtain the video's current time before implementing this feature.
We’ll begin by importing the useRef
hook and creating a reference for the React Player
.
Let's implement a rewindHandler
function that we'll call anytime the rewind button is double-tapped. This function will use two methods for the rewind and fast-forward features obtained from the videoPlayerRef
.
seekTo
: Seek the given number of seconds, or a fraction if the amount is between 0 and 1getCurrentTime()
: Returns the number of seconds that have been played
Next, we pass the functions as props to the Control
component:
Then, we receive the props and pass the two functions into their respective buttons.
We can now fast-forward and rewind our video using the code above. However, you'll also notice that the video player's slider doesn't move to the current time when we rewind or fast-forward the video. Let's fix that, since we're problem solvers, right?
Seek Functionality
The ReactPlayer
has an onProgress
prop callback for this feature, which is a Callback
that contains played and loaded progress as a fraction as well as playedSeconds
and loaded seconds.
The progressHandler
function accepts an argument called state
. This state
argument indicates an object with contained states. Every time the video player seek bar (the player's timing) updates, some sets of states are altered, and new values are returned. We keep the values of the previously modified States and our videoState
properties in this function. We want this to happen, but only when the value of the seeking property in our videoState
is negated.
Next, we pass in the progressHandler
function to the onProgess
prop in the ReactPlayer
:
Then, to update our seek slider to the appropriate time of the video, we pass the played
state that we've destructured from the videoState
to the control component as a prop.
The PrettoSlider
in our control
component then has to be updated. The maximum value for our PrettoSlider
must be 100, and the minimum value must be set to 0. The value prop is the slider's current e.target.value
, which multiplies the value of the played
props by 100.
Furthermore, we need to write functions that will enable us to use the video player slider to look for a specific moment. To do this, we'd create a seekHandler
and a seekMouseUpHandler
to help us achieve this feature.
We then pass these functions as props to the control
component. The parameter given to the function is the value we immediately receive whenever the slider moves. Then, since played
only accepts values between 0 and 1, we only updated the played
value to the value argument divided by 100 when updating the videoState
.
Additionally, we gave the mouseSeekUpHandler
function an argument called value
. Spreading the previous state and changing only the seeking
state value to false
, which allows us to update the videoState
. Then, we change the video's current time to the desired time.
To use these two functions, the PrettoSlider
has two props which we can use for this functionality: onChange
and onChangeCommitted
. According to the MUI docs, the onChange
prop is a Callback function that fires whenever the slider's value changes, while the onChangeCommitted
is a Callback function that fires when the mouse moves up.
This is what our video player should look like now:
Volume Functionality
We should have the option to mute and increase/decrease the video’s volume in our React player. The icon should then change to ‘muted’ or ‘volume-up’, depending on the volume setting in that situation.
Let’s head over to our App.js file.
There is a volume prop for this functionality in the ReactPlayer
where we pass the destructured volume
from our videoState
.
The volume slider needs to define two functions, one for the onChange
event and the other for the onChangeCommitted
event, just like the PrettoSlider
.
Now, we pass them as props to the control
component:
The volume slider is then updated by including new props, the onChange
event, the onChangeCommitted
event, and value
, and passing the onVolumeChangeHandler
, onVolumeSeekUp
, and volume
props.
Handling the Muted State
We ought to be able to choose between muted
and volume up
whenever the mute button is clicked. The symbol should switch to ‘muted’ or ‘volume-up’ depending on the volume level.
We’ll start by writing a function that handles the mute functionality in our App.js file.
In the muteHandler
, we retained everything in the videoState
and changed the muted
property to have a value opposite of the current muted
state, thereby toggling it and then passing the muted
props to the control
component.
The value of the videoState
field's muted
state determines how the two icons in the above code would render conditionally. It also passes in a function to the wrapper, which toggles the mute functionality.
This is how our video should function:
Video Time Functionality
Video players, as we all know, typically show the video's current time. To accomplish this, we use some instance methods that React Player offers:
getCurrentTime
: Returns the number of seconds that have been played.getDuration
: Returns the currently playing media’s total duration (in seconds).getSecondsLoaded
: Returns the number of seconds that have been loaded.
We still need to format the returned time according to our preferences, even though the currentTime
and duration
are rendered conditionally using ternary operators.
A function that formats the timing must be created. After accepting an argument, this function will return the time in a specific format.
To use the function in App.js, we create a new file called Format.js inside the component folder.
Following that, import the formatTime
method found in the Format.js file. Therefore, in the App.js file, we can use it. Then, two formatTime
calls are made, with the currentTime
and duration
being passed as arguments.
We then pass the formatCurrentTime
and formatDuration
as props to the control
component.
Finally, modify the default timing value to this:
Now, you can watch the length of the video as it plays and see how much time has passed. Watch the timing as the seek bar is dragged.
The Control
container div is frequently resting on the player, as you can see. Let's make it more interesting by having it resemble other video players— let’s make it visible whenever we hover on the video player.
Creating a Disappearing Seek Bar
To achieve this feature, we also need to create a reference of the div
with classname of control_Container
in the App.js file:
And pass it to the control
component:
We then pass it to the ref
property on the control_Container
div in the control
component:
Next, we head over to our App.js and declare a new variable called count
which will be equal to 0:
We include an if
statement inside the progressHandler
function to determine whether the count
exceeds 3, at which point we use the controlRef
and set the visibility to hidden
. By doing so, the control
component div is hidden.
We must create another function to make the control div visible whenever the player is hovered over.
Our player now looks like this:
Buffering Functionality in our React Player
When we watch videos online, they frequently stall, primarily because of poor network connections. Let's add a similar feature to our video player.
The ReactPlayer provides two props that accept a callback for this feature: onBuffer
and onBufferEnd
.
The last step alerts users when a video freezes. The buffer state must be true
to render a load effectively.
Observe the Loading
text when the video freezes.
Conclusion
This post taught us how to construct and modify a video player using the react-player
package and Material UI
to style and import the required icons. Of course, you can always improve the build by including a few special features to make the player entirely custom.
Here is the URL to the GitHub repository.