Simulate a Streaming Event in Gatsby.js

Odewole Babatunde Samson

Introduction

Live streaming events have become more of the norm these past few years. They give a sense of urgency to your content, boost online interaction between you and your users, and help reach a wider audience.

This tutorial will walk through handling video player events by building a live streaming event in Gatsby.js.

What we will be building

The live streaming event mimics live events, where we want to play a video starting from a specified time. The video starting position for the user is adjusted based on how much time has passed since the actual video started. For example, a video that is 1 hour long but started 45 minutes ago would have any new user that visits the page automatically start at the 45-minute mark on the video timeline.

After the recorded video is complete, we want an overlay showing the text "Live event has ended" and our native player controls hidden.

CodeSandbox

We completed this project in a CodeSandbox. To get started quickly, fork it or run the project.

1https://codesandbox.io/s/ecstatic-jennings-ndeiog?file=/src/pages/index.js:116-128

You can find the GitHub repository here.

Prerequisites

To get the most out of this tutorial, you’ll need the following:

  • A basic understanding of CSS, JavaScript, React, and GraphQL.
  • Node and its package manager, npm. Run the command node -v && npm -v to verify that you have them installed, or install them from here.
  • Gatsby command-line interface (CLI) installed.
  • Understanding Gatsby.js would help us follow through with this tutorial.

Setting up a Gatsby environment

Gatsby a Static Site Generator, is a React-based open-source framework for creating websites and apps.

To create our Gatsby.js app, we’ll go to our terminal or command prompt using the git cd command and perform the following steps:

  1. We need the Gatsby CLI on our computer; let's run this command:
1npm install -g gatsby-cli
  1. Create a new site:
1gatsby new

It’ll ask for a site title and the name of the project’s directory. Continue following the prompts to choose our preferred language (JavaScript or TypeScript), CMS, styling tools, and additional features.

  1. Upon downloading everything, we'll see a message with instructions for navigating to our site and running it locally.

The CLI created the site as a new folder with the name you chose in Step 1. Start by going to the directory with:

1cd my-gatsby-site

Let's start the local development server with:

1gatsby develop

Gatsby will start a hot-reloading development environment accessible by default at http://localhost:8000.

  1. Now we’re ready to make changes to our site!

    Let's try editing the home page in src/pages/index.js.

NOTE: Saved changes will automatically reload in the browser.

Installing dependencies

We will install React Player to handle our video and video player events in this part of the tutorial.

React Player

React Player is a React component for rendering a variety of video URLs. React Player allows us to create and personalize our video player with callback props for almost every player event. It also offers an excellent media experience in web applications.

To install React Player in our app, we run the following command.

1npm install react-player
2# or
3yarn add react-player

Creating the video player

To create our video player, we first create a component folder in the src of our app. In this folder, we will create our video-player.js file.

To use the ReactPlayer component, we import it from the react-library into our video-player.js file.

1import React from 'react'
2import ReactPlayer from 'react-player'

This ReactPlayer component allows us to use various props. We then pass values into these props to personalize our player.

In the next piece of code, we use the url prop, the controls prop, and, finally, the playing prop.

The url prop takes in a value that points to the media path we want to play. To display the native player controls, we use the controls prop. This prop takes in a Boolean value. When the controls prop is set to true, the controls are displayed and hidden when set to false.

Next, we have the playing prop. The playing prop plays or pauses the media when set to true or false.

The ReactPlayer component also allows us to set the width and height of the player using the width and height props, respectively. Failing to do so sets our video player to this default dimensions width: 640px; height: 360px; which we will use in this tutorial.

1import React from 'react';
2import ReactPlayer from 'react-player';
3const VideoPlayer = () => {
4 return (
5 <div className="video-player">
6 <ReactPlayer
7 url="https://res.cloudinary.com/beswift-hub/video/upload/v1648105334/videoplayback_rz8dhu.mp4"
8 playing={true}
9 controls={true}
10 />
11 </div>
12 );
13}
14export default VideoPlayer;

By setting our playing and controls prop to true, our video player plays our video as it renders on our screen and displays our native player controls.

Next, we import our video player to our pages/index.js file to see our video player in our browser.

1// Step 1: Import React
2import * as React from "react";
3import VideoPlayer from "../component/video-player";
4// Step 2: Define your component
5const IndexPage = () => {
6 return (
7 <main>
8 <title>Live Streaming</title>
9 <h1>Welcome to my Gatsby site Streaming event</h1>
10 <p>I'm making a streaming event with Gatsby</p>
11 <VideoPlayer/>
12 </main>
13 );
14};
15// Step 3: Export your component
16export default IndexPage;

With that, we have our video player set up.

Creating a Streaming event

To create a live streaming event in our app, we start by importing React and the useState hook in our pages/index.js file.

The useState hook allows us to add states to our functional components.

1import React, { useState } from "react";

Next, using the useState hook, we create pieces of state to control different properties of our video player.

1const [startTime, setStartTime] = useState(1630430724714);
2const [controls, setControls] = useState(true);
3const [ended, setEnded] = useState(false);
4const [duration, setDuration] = useState(null);
5const [playing, setPlaying] = useState(true);
  • startTime : Set to an initial value of 1630430724714; this is the time in milliseconds we want our ‘live event’ to start (we shall discuss how to find the time in milliseconds in the functions section of this tutorial below).
  • controls : Set to an initial value of true, this property sets the controls prop on the ReactPlayer component.
  • ended : Set to an initial value of false. It will be set to true when the video ends. We’ll use the ended variable to render our overlay conditionally.
  • duration : Stores the duration of the video being played in seconds.
  • playing : Controls when our video starts or stops playing. It is set to an initial value of true, as we want our video to be playing when it mounts, unless the video has ended.

Next, our control functions.

1let date = new Date();
2let currentTime = date.getTime();
3let timePlayed = (currentTime - startTime) % 1000;
4const endVideo = () => {
5 if (controls === false && ended === true) {
6 if (playing === false) {
7 return;
8 } else {
9 setPlaying(false);
10 }
11 } else {
12 setControls(false);
13 setEnded(true);
14 setPlaying(false);
15 }
16};
17const videoDuration = (num) => {
18 setDuration(num);
19};
20if (timePlayed > duration) {
21 endVideo();
22}
23const restartLive = () => {
24 let newDate = new Date();
25 let newStartTime = newDate.getTime();
26 setStartTime(newStartTime);
27 setEnded(false);
28 setPlaying(true);
29 setControls(true);
30};

Getting the current time in milliseconds

The date variable in the code block above obtains the current date using the JavaScript new Date() method. We then get the current time in milliseconds using the JavaScript getTime() method and store it in the currentTime variable. The timePlayed variable gets the difference between the time our ‘live event’ started and the current time in seconds; this variable will be used to tell our video player what time in the player we want to seek to.

What happens when our video ends?

The endVideo function will get called when our video ends, even long after. The endVideo function has an if else block. This if else conditional checks whether the controls variable is already false and the ended variable true, if they are, we go further to check if the playing variable is false. if our code passes all these checks, then we want to return from the function.

If, however, our code does not pass all these checks, we want to set

  • playing to false to stop playing the video, and
  • controls to false to hide the native player controls.

We created a videoDuration function that takes in a num parameter, this parameter represents the duration of the media. This videoDuration function uses the num parameter to update the duration state variable.

Next, we have an if block of code, this checks whether the timePlayed variable (containing how much time has passed since the start of the live) is greater than the duration. If it is, we run the endVideo function.

Restarting the video

The restartLive function is used to restart the live event simulation. The newDate variable gets the date that the restartLive function ran, and the newStartTime variable stores the exact time in milliseconds this function ran. We pass in the new``S``tartTime to the setStartTime function to reset the startTime variable.

Finally, we set our ended variable to false, as we just started our simulation over again.

Next, we add a button to run this restartLive function, with the onClick event handler.

1<button className= 'reset-button' onClick = {restartLive}>Restart Streaming event</button>

By now, our pages/index.js should look like this:

The module imports and methods

1// Step 1: Import React
2import React, { useState } from "react";
3import VideoPlayer from "../component/video-player";
4// Step 2: Define your component
5const IndexPage = () => {
6
7const [startTime, setStartTime] = useState(1630430724714);
8const [controls, setControls] = useState(true);
9const [ended, setEnded] = useState(false);
10const [duration, setDuration] = useState(null);
11const [playing, setPlaying] = useState(true);
12
13let date = new Date();
14let currentTime = date.getTime();
15let timePlayed = (currentTime - startTime) % 1000;
16const endVideo = () => {
17 if (controls === false && ended === true) {
18 if (playing === false) {
19 return;
20 } else {
21 setPlaying(false);
22 }
23 } else {
24 setControls(false);
25 setEnded(true);
26 setPlaying(false);
27 }
28};
29const videoDuration = (num) => {
30 setDuration(num);
31};
32if (timePlayed > duration) {
33 endVideo();
34}
35const restartLive = () => {
36 let newDate = new Date();
37 let newStartTime = newDate.getTime();
38 setStartTime(newStartTime);
39 setEnded(false);
40 setPlaying(true);
41 setControls(true);
42};

The rendered component

1return (
2 <main>
3 <title>Live Streaming</title>
4 <h1>Welcome to my Gatsby site Streaming event</h1>
5 <p>I'm making a streaming event with Gatsby</p>
6 <div className="live-event-container">
7 {/* Our VideoPlayer component */}
8 <VideoPlayer
9 ended={ended}
10 timePlayed={timePlayed}
11 controls={controls}
12 endVideo={endVideo}
13 playing={playing}
14 videoDuration={videoDuration}
15 />
16 </div>
17 {/* Our Restart button */}
18 <button className="reset-button" onClick={restartLive}>
19 Restart Streaming event
20 </button>
21 </main>
22 );
23};

Passing the variable to our React player

We passed our timePlayed variable, controls variables, endVideo function, and our videoDuration function to the VideoPlayer component housing our ReactPlayer component.

Create a video-player.js file in the component directory and paste the code below.

1<VideoPlayer
2timePlayed ={timePlayed}
3controls={controls}
4endVideo={endVideo}
5playing={playing}
6videoDuration={videoDuration}
7/>

In the src/component/video-player.js file, we define a player variable; we’ll use this variable later to set the ref on our ReactPlayer, and we do this to reference the component.

Next, we pass the variables we received to their respective props, the controls variable to the controls prop, and the playing variable to the playing prop.

The ReactPlayer component allows us to use an onEnded callback prop, which runs the function passed into it when the video ends, so we pass in the endVideo function.

The onStart callback prop takes a function that runs when the video is mounted and ready to play. We use this to call the getDuration() method on the player object we obtain from the ReactPlayer component. This method is used to retrieve the duration of the video in seconds.

Next, we write another function using the seekTo() method on the player object. The seekTo() method takes in a time parameter in seconds that indicates where we want to skip to in the video. We then pass the timePlayed variable (the difference between the current time and the start time in seconds) as the time parameter into the seekTo() method.

Our src/component/video-player.js should look like this.

1import React from "react";
2import ReactPlayer from "react-player";
3let player;
4const VideoPlayer = ({
5 endVideo,
6 timePlayed,
7 controls,
8 playing,
9 videoDuration
10}) => (
11 <div className="video-player">
12 <ReactPlayer
13 ref={(ref) => {
14 player = ref;
15 }}
16 url="https://res.cloudinary.com/beswift-hub/video/upload/v1648105334/videoplayback_rz8dhu.mp4"
17 playing={playing}
18 controls={controls}
19 onStart={() => {
20 videoDuration(player.getDuration);
21 player.seekTo(timePlayed);
22 }}
23 onEnded={endVideo}
24 />
25 </div>
26);
27export const MemoizedVideoPlayer = React.memo(VideoPlayer);

Creating the video overlay

To make our overlay, we create a video-overlay.js file in the src/component folder.

For our overlay, we use a div element, a header, and a p tag.

1import React from "react";
2const VideoOverlay = () => (
3 <div className="video-overlay">
4 <h2>Live Event has finished</h2>
5 <p>Click the button below to restart simulation</p>
6 </div>
7);
8export default VideoOverlay;

With that, we have been able to stimulate streaming events.

Here's what it looks like:

Conclusion

In this article, we demonstrated how to create a video player and handle player events with React Player using Gatsby.js. We specified what should happen when a user starts watching the 'live video' and how to place them at a specific point of the video depending on how much time has passed since the video began.

Try to modify the video’s start time relative to your current time and see how far into the live video you get!

Resources

You may also find these resources helpful.

Odewole Babatunde Samson

Software engineer and Technical writer

I am a self-driven and self-motivated software engineer in the blockchain development space and I love to impact more knowledge to people that is why I write about Javascript, React.js, web3.js, and Solidity