Editor’s note: This article was last updated by Fimber Elemuwa on 18 May 2023 to compare React video playback using ReactPlayer and Video-React, and to include information about playing videos in React using the HTML tag.
As developers, it is crucial to stay up to date with the latest tools and technologies that enable seamless video playback within web applications. React, the popular JavaScript library, provides an efficient and flexible platform for building user interfaces, making it an ideal choice for incorporating video playback functionality into web projects.
In this article, we will be looking at the basics of video playback and highlighting some of the most popular JavaScript video player frameworks, their features, and how to implement them in React. Whether you’re building a video streaming platform, an e-learning application, or simply adding videos to enhance your website, this guide will equip you with the necessary tools to bring your vision to life.
Jump ahead:
To understand video playback, it is important to first understand the process involved between the user clicking on the play button and the first frame of the video being played. There are a fair number of steps that can go wrong between these two points, which ultimately can affect your video performance or, at worse case, mean your video does not play at all.
Unless your video file is very small, it’s unlikely that your video player will download the whole file in one go before playback. This would ultimately result in the consumer waiting a considerable amount of time before they see any content, which would likely make them impatient and move away from the video.
The process of downloading the entire video in one go is often referred to as single source playback and is not recommended for most use cases. Instead, video content is usually split up into pieces known as “chunks,” which the video player downloads in a series to ensure that the device is only ever downloading small pieces of data at any given time.
On top of the data being split into small chunks, there are usually multiple levels of video quality available to the player, so the client is able to choose which bitrate is better suited for their network conditions. If you have ever seen the dreaded buffering symbol, it is because the video player has failed to step down to a smaller bitrate in time, and the player is trying to download each chunk.
The process where the client is switching between different quality levels of video and trying to download chunks is called Adaptive Bitrate Streaming (ABS). MSS (Microsoft Smooth Streaming), HLS (HTTP Live Streaming), and DASH (Dynamic Adaptive Streaming over HTTP) are three different technologies created to achieve effective ABS.
SSTP was standardized by Microsoft and first appeared with the introduction of the Silverlight player. SSTP downloads a video in a series of small chunks, which are cached on the edge of the network, meaning that the transaction of clients requesting and receiving these chunks can happen much quicker.
To begin playback, the video player requests a manifest file from the server, which lays out the details about the requested video, such as the duration of the video, the location of each chunk, and the bitrates available to the player.
Below is a sample SSTP manifest with some of the key information labeled:
<SmoothStreamingMedia MajorVersion="2" MinorVersion="1" Duration="1209510000"> // Total video duration <!-- Encryption --> <Protection> <ProtectionHeader SystemID="{9A04F079-9840-4286-AB92E65BE0885F95}"> <!-- Base 64-Encoded data omitted for clarity --> </ProtectionHeader> </Protection> <!-- Video information --> <StreamIndex Type="video" Name="video" Chunks="4" // Number of chunks QualityLevels="4" // Number of bitrates available MaxWidth="1280" MaxHeight="720" DisplayWidth="1280" DisplayHeight="720" Name = "video" Url="QualityLevels({bitrate})/Fragments(video={start time})"> // URL template to request chunks <!-- Quality levels --> <QualityLevel Index="0" Bitrate="1536000" FourCC="WVC1" MaxWidth="720" MaxHeight="480" CodecPrivateData = "270000010FCBEE1670EF8A16783BF180C9089CC4AFA11C0000010E1207F840" > <CustomAttributes> <Attribute Name = "Compatibility" Value = "Desktop" /> </CustomAttributes> </QualityLevel> <QualityLevel Index="5" Bitrate="307200" FourCC="WVC1" MaxWidth="720" MaxHeight="480" CodecPrivateData = "270000010FCBEE1670EF8A16783BF180C9089CC4AFA11C0000010E1207F840"> <CustomAttributes> <Attribute Name = "Compatibility" Value = "Handheld" /> </CustomAttributes> </QualityLevel> <!-- Chunks --> <c t = "0" d = "19680000" /> <c n = "1" t = "19680000" d="8980000" /> </StreamIndex> </SmoothStreamingMedia>
Most commonly used on Microsoft platforms, SSTP is one of the older ABS technologies and aims to provide minimal buffering and a fast start-up time.
HLS stands for HTTP Live Streaming and was developed by Apple in 2009 alongside the release of the iPhone 3 as an alternative to the popular Adobe Flash format.
HLS divides the video into 10-second chunks indexed in a separate playlist file and is the only supported standard on Apple devices with iOS and OSX.
A sample HLS playlist is as follows:
#EXTM3U #EXT-X-PLAYLIST-TYPE:VOD <!-- Video duration --> #EXT-X-TARGETDURATION:10 #EXT-X-VERSION:4 #EXT-X-MEDIA-SEQUENCE:0 <!-- Chunk duration (10 seconds) --> #EXTINF:10.0, <!-- URL to request chunk --> http://example.com/movie1/fileSequenceA.ts #EXTINF:10.0, http://example.com/movie1/fileSequenceB.ts #EXTINF:10.0, http://example.com/movie1/fileSequenceC.ts #EXTINF:9.0, http://example.com/movie1/fileSequenceD.ts #EXT-X-ENDLIST
HLS’s main benefit is that it is the only native ABS format for Apple devices. If you want to achieve video playback on your iOS device, HLS is your only option.
Dynamic Adaptive Streaming over HTTP (DASH) is a fairly new technology that aims to provide support across all devices, avoiding the unnecessary complication of having to implement multiple technologies, such as MSS and HLS, for the same video source.
After a proposal by MPEG in 2009, over 50 major companies — including Google and Microsoft — collaborated to come up with the MPEG-DASH standard, which was eventually published in 2012.
Essentially, DASH aims to combine all of the current technologies into one, providing the benefits of each standard and reducing technical headaches. Typically, a DASH video is split into two to four second video chunks allowing for faster video download and better performance.
Below is a sample DASH manifest:
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" profiles="urn:mpeg:dash:profile:full:2011"> <Period duration="PT10M"> // Period Duration <BaseURL>main/</BaseURL> <AdaptationSet mimeType="video/mp2t"> <BaseURL>video/</BaseURL> <!-- 1st Bitrate --> <Representation id="720p" bandwidth="3200000" width="1280" height="720"> <BaseURL>720p/</BaseURL> <!-- Chunk List --> <SegmentList timescale="90000" duration="5400000"> <RepresentationIndex sourceURL="representation-index.sidx"/> <SegmentURL media="segment-1.ts"/> <SegmentURL media="segment-2.ts"/> <SegmentURL media="segment-3.ts"/> <SegmentURL media="segment-4.ts"/> <SegmentURL media="segment-5.ts"/> <SegmentURL media="segment-6.ts"/> <SegmentURL media="segment-7.ts"/> <SegmentURL media="segment-8.ts"/> <SegmentURL media="segment-9.ts"/> <SegmentURL media="segment-10.ts"/> </SegmentList> </Representation> <!-- 2nd Bitrate --> <Representation id="1080p" bandwidth="6800000" width="1920" height="1080"> <BaseURL>1080/</BaseURL> <!-- Chunk List --> <SegmentList timescale="90000" duration="5400000"> // Segment duration <RepresentationIndex sourceURL="representation-index.sidx"/> <SegmentURL media="segmentl-1.ts"/> <SegmentURL media="segmentl-2.ts"/> <SegmentURL media="segmentl-3.ts"/> <SegmentURL media="segmentl-4.ts"/> <SegmentURL media="segmentl-5.ts"/> <SegmentURL media="segmentl-6.ts"/> <SegmentURL media="segmentl-7.ts"/> <SegmentURL media="segmentl-8.ts"/> <SegmentURL media="segmentl-9.ts"/> <SegmentURL media="segmentl-10.ts"/> </SegmentList> </Representation> </AdaptationSet> </Period> </MPD>
Now that you have an understanding of the different ABS technologies, we can look at the various JavaScript player frameworks available to accommodate them. Although it seems like the industry is moving towards DASH, it is still a relatively new technology, and systems running MSS and/or HLS are still present in our video infrastructure, particularly on Apple devices where HLS is the only option.
Let’s look at some of the most popular JavaScript video player frameworks, the ABS technologies they support, and how they can be implemented in React.
The first technology that we will look at is arguably one of the most popular open source video player frameworks available today. Video.js was built from the ground up in 2010 with the JavaScript world in mind and is used on approximately 500,000 websites worldwide.
Video.js’ main selling point is that it aims to support all types of video formats, including adaptive video formats such as HLS and DASH.
Used by companies such as Tumblr and LinkedIn, Video.js is easy to style, cross-functional, and easy to implement. But how does it hold up in the React world?
Thankfully, implementing Video.js isn’t too much of a headache in React and can be up and running within minutes. To get started, download Video.js or import it using npm with npm i video.js
.
From there, the Video.js player needs to be instantiated on componentDidMount
before it is available for use:
import React from 'react'; import videojs from 'video.js' export default class VideoPlayer extends React.Component { componentDidMount() { this.player = videojs(this.videoNode, this.props, function onPlayerReady() { console.log('Video.js Ready', this) }); } componentWillUnmount() { if (this.player) { this.player.dispose() } } render() { return ( <div> <div data-vjs-player> <video ref={ node => this.videoNode = node } className="video-js"></video> </div> </div> ) } }
You may notice that the player is wrapped in a data-vjs-player
div. This extra step ensures that an additional wrapper isn’t created in the DOM. Once your component is created, it can be triggered with various options to initiate playback.
Check out the full list of available options on Video.js:
const videoJsOptions = { autoplay: true, controls: true, sources: [{ src: '/path/to/video.mp4', type: 'video/mp4' }] } return <VideoPlayer { ...videoJsOptions } />
Video.js offers one solution for playing HLS content, but a player framework that is gaining traction as one of the better options for handling the Apple format is HLS.js. Released in 2015, HLS.js is now in production across thousands of high profile websites, including Twitter and the New York Times.
The attraction of HLS.js is its simplicity in implementation and tiny footprint (it is just half the size of the other players mentioned in this article at 71.1KB). Relying on HTML5 video and MediaSource Extensions to achieve playback, you can deliver reliable HLS playback in the browser quickly and efficiently.
Your first step to implementing HLS.js in React is to download the latest library and include it in your React project, or install it from npm with npm i hls.js
. From there, we create a standard <video>
tag in our render function.
We will also give the player a reference for this.player
so that we can use it later to instantiate our player framework:
import React from "react"; import Hls from "hls.js"; export default class VideoPlayer extends React.Component { state = {}; render() { return ( <video className="videoCanvas" ref={player => (this.player = player)} autoPlay={true} /> ); } }
Once the video tag is in place, rendering a video in HLS.js is as simple as updating componentDidUpdate
to attach the media:
import React from "react"; import Hls from "hls.js"; export default class VideoPlayer extends React.Component { state = {}; componentDidUpdate() { const video = this.player; const hls = new Hls(); const url = "https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8"; hls.loadSource(url); hls.attachMedia(video); hls.on(Hls.Events.MANIFEST_PARSED, function() { video.play(); }); } render() { return ( <video className="videoCanvas" ref={player => (this.player = player)} autoPlay={true} /> ); } }
Here you can see that componentDidUpdate
is loading the source stream, attaching it to the video player, and attaching a listener to manifest events in order to know when to play the video. The full documentation for HLS.js, as well as the many events that can be triggered during playback, can be found here.
DASH.js was created by the DASH Industry Forum to design a video player framework that allows developers to build video players using the increasingly popular MPEG-DASH format that is both browser-agnostic and robust in a production environment.
The first step to implementing the DASH.js video player framework is to import the library into your project, the latest of which can be found here.
As with our other players, you need to create your <video>
tag and place it in your render function. This is what DASH.js will target to render your video.
Once again, we will give the video tag a reference of this.player
so we can use it later to initialize DASH.js:
import React from "react"; import * as dashjs from "dash.js"; export default class VideoPlayer extends React.Component { state = {}; render() { return ( <video ref={player => (this.player = player)} autoPlay={true} /> ); } }
The final step to achieve playback is to instantiate your player on componentDidUpdate
and provide it with your target URL:
import React from "react"; import * as dashjs from "dash.js"; export default class VideoPlayer extends React.Component { state = {}; componentDidUpdate() { const url = "https://dash.akamaized.net/envivio/EnvivioDash3/manifest.mpd"; const video = this.player; const dashjs = dashjs.MediaPlayer().create(); dashjs.initialize(video, url, true); } render() { return ( <video ref={player => (this.player = player)} autoPlay={true} /> ); } }
At this point, you should be seeing some video playback! There are many settings, events, and customization options available to DASH.js, which can be found in their documentation.
ReactPlayer is a popular open source library that provides a React component for easily integrating video playback into React applications. It simplifies the process of working with various video sources and formats, offering a unified API and a range of customizable options.
The library also offers a set of intuitive props and callbacks that enable you to customize the appearance and behavior of the video player. It provides features like play/pause controls, seeking, volume control, fullscreen mode, and support for subtitles. Additionally, ReactPlayer handles cross-browser compatibility and provides a consistent experience across different platforms and devices.
To implement ReactPlayer for video playback in your project, import the ReactPlayer component, and then pass in some props to it:
import React from 'react'; import ReactPlayer from 'react-player'; const VideoPlayer = () => { return ( <div> <h2>Video Player</h2> <ReactPlayer url="https://www.youtube.com/watch?v=dQw4w9WgXcQ" controls={true} width="800px" height="450px" /> </div> ); }; export default VideoPlayer;
ReactPlayer doesn’t have built-in support for loading multiple URL sources simultaneously. The url
prop in ReactPlayer expects a single video URL as a string value.
However, it’s possible to bypass this by creating a separate ReactPlayer component for each video source and managing their state independently. You can use state management libraries like Redux or React’s built-in useState
Hook to handle the state of each video player component:
import React, { useState } from 'react'; import ReactPlayer from 'react-player'; const VideoPlayer = () => { const [videoSources, setVideoSources] = useState([ 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', 'https://www.youtube.com/watch?v=3tmd-ClpJxA', 'https://www.youtube.com/watch?v=JGwWNGJdvx8' ]); const renderVideoPlayers = () => { return videoSources.map((url, index) => ( <div key={index}> <ReactPlayer url={url} controls={true} width="800px" height="450px" /> </div> )); }; return ( <div> <h2>Video Player</h2> {renderVideoPlayers()} </div> ); }; export default VideoPlayer;
Video-React is another popular open source library built on top of React that relies on HTML5 video capabilities for working with video sources and handling player controls. Video-React supports common video formats such as MP4, WebM, and Ogg, and also allows you to play videos from external sources like YouTube and Vimeo.
Video-React offers a range of features and controls, including play/pause, seek, volume control, fullscreen mode, and a customizable player UI. It also provides a straightforward integration process, allowing you to wrap your video component with the necessary player controls and configure them according to your requirements.
Video-React has a simple and declarative API, making it accessible to both beginners and experienced React developers. To use it, you first have to install the library:
npm install --save video-react react react-dom redux
After you’ve done that, you can import the player component from the library and set up your video playback. Here’s an example:
import React from 'react'; import { Player } from 'video-react'; export default props => { return ( <Player playsInline poster="/assets/poster.png" src="https://media.w3.org/2010/05/sintel/trailer_hd.mp4" /> ); };
While Video-React was heavily inspired by Video.js, most developers use it as a ReactPlayer alternative because both players having similar features. They are often used interchangeably based on the developer’s personal preference, but there’s little difference between them:
ReactPlayer | Video-React | |
---|---|---|
Supported formats | Supports a wide range of video formats including MP4, WebM, YouTube, Vimeo, and more | Supports common video formats such as MP4, WebM, Ogg, as well as playing videos from external sources like YouTube and Vimeo |
API and components | Provides a React component for video playback and control | Provides a set of React components for video playback and a customizable player UI |
Customization | Offers a range of customizable options and properties for controlling playback, appearance, and behavior | Provides a flexible and customizable UI with various control components for controlling playback and appearance |
Cross-browser support | Handles cross-browser compatibility and ensures consistent video playback experience across different platforms and devices | Supports HTML5 video capabilities, which have wide cross-browser support |
Features | Provides features like play/pause controls, seeking, volume control, fullscreen mode, and support for captions and subtitles | Offers features such as play/pause controls, progress control, volume control, fullscreen toggle, and more |
Documentation | Provides comprehensive documentation, examples, and usage guidelines | Offers detailed documentation, API reference, and examples for easy integration and customization |
As you can see, ReactPlayer and Video-React are very similar video playback tools, so while ReactPlayer may be the more popular of the two, Video-React still serves as an excellent ReactPlayer alternative.
While most developers use the above-mentioned frameworks for video playback in React, it’s still possible to deploy a normal HTML video in React using HTML tags. It’s the default form and while it may not be very pretty, it’s still functional.
To play a local video using an HTML tag, you just have to import the video into your page and pass it in the video tag:
import React from 'react'; import video from './Videos.video1.mp4' const VideoPlayer = () => { return ( <div> <h2>Video Player</h2> <video src={video} width="800" height="400" controls /> </div> ); }; export default VideoPlayer;
The src
attribute of the <video>
tag specifies the URL of the video file you want to play. In this example, we’re importing a video file from the local disk, but you can replace it with an external URL of your choice and it’ll work just fine.
This article explained the basics of video playback and what happens behind the scenes once a user hits the play button. We reviewed three of the most popular ABS formats, and the applications for each of them while also reviewing some popular React video players and their various implementations.
With video being the number one method of information consumption for the vast majority of the internet’s users, there is no better time to start delving into the wonderful world of video playback. I hope this article gets you thinking the next time you see that buffering icon on your favorite streaming service.
For further reading, I recommend “Remotion: A framework for making videos in React,” which explores how to generate video content in React using the open source Remotion library.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to implement one-way and two-way data binding in Vue.js, using v-model and advanced techniques like defineModel for better apps.
Compare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
One Reply to "A guide to video playback in React"
Why does the logo on LogRocket’s blog not have a spraypainted B over the rocket glyph so it read BLogRocket? 🤦