Building A Live Streaming Movie App & Live TV Website Part 1 — ReactJS Setup

Devin Dixon
BingeWave
Published in
12 min readJul 22, 2021

--

BingeWave’s initial business started was showcasing film premieres in any venue, as the business was initially an Airbnb to Movie Theaters model. Working with the film vertical taught many valuable lessons working with pre-recorded content, aka films.

Today many use our technology to showcase their films virtually as we’ve showcased nearly 2000+ pieces of content ranging from documentaries, short films, web series to features. And people pay filmmakers and film festivals for live interactive virtual experiences.

Throughout our documentation, we use the term pre-recorded content a lot but think of it as virtual film premieres, live podcasts, and other forms of virtual and hybrid events that you can benefit from live engagement. This means everyone watches the same content at the same time.

This tutorial will be in 3 parts and guide you on making a virtual experience with pre-recorded content. The first part will set up the structure of your application and essential classes. The second part will focus on the UX/UI of the application and playing content. The final part will focus on Live TV content.

Technical Overview

Required Developer Skills

We recommend that the developers reading this tutorial have the following skills:

  • HTML/CSS
  • Basic Javascript
  • Basic React

Topics Covered:

  • Uploading Video Content
  • Uploading Images
  • RTMP & HLS Streaming

Code Repository: Download and run the completed code at https://github.com/BingeWave/Build-A-Livestreaming-App-For-Virtual-Movie-Premieres

Estimated Timed: 1 hour

Difficulty Level: Easy to Intermediate

The Tutorial

Step 1: Distributor Account

Like all of our tutorials, our starting point will be a distributor account. This will allow you to access all our API features. Please read the tutorial on Setting up a Distributor Account if you have not already; it should only take a minute or two.

Step 2: Setting Up Our React Application

Now let’s start to build our React application. This tutorial will assume you have NodeJS installed on your computer and have a basic understanding of the command line. Make a new folder, and we are going:

  1. Create a directory for your React Application
  2. Install React
  3. Install required components like Router, Bootstrap 5

Again, we are assuming you have node and npx already installed.

node install npx #if you don’t already have it installed
mkdir video-app
npx create-react-app video-app #installs the react application

Go into the folder and let’s install some required modules. You can use yarn if you wish, but this tutorial utilizes npm.

cd video-app
npm install bootstrap@5.0.0-alpha1 --save
npm install node-sass --save
npm install react-router-dom --save
npm install react-datetime-picker --save
npm install react-select -- save

This installed Bootstrap 5, React’s Router, A DateTime picker, and a GUI we will use for multi-select. Next, we are going to make a few folders that we are going to use to organize the application:

mkdir src/pages
mkdir src/components
mkdir src/util

Make one page within the pages folder called HomePage:

touch src/pages/HomePage.jsx

And add the following contents:

Finally, let’s modify your App.js to utilize the router and install Bootstrap 5 across our application. Create a src/main.scss file

touch src/main.scss

and import the Bootstrap source stylesheet into it like so:

@import “../node_modules/bootstrap/scss/bootstrap.scss”;

Then import the newly created main.scss file at the top of your src/index.js file like this:

import “../src/main.scss”;

Open src/App.js and import the HomePage from ./pages/HomePage at the very top. Delete everything in the return() function and replace it with <HomePage />. At this time, your code should look like this:

After run npm start and your application should boot to a page that says “My Home Page”.

npm start

Step 3: ENV File

The env file will setup our environment variables inside our application. Start by creating the .env file in your root directory.

touch .env

And we are going to copy and paste these values in there:

REACT_APP_BW_API_URL=https://bw.bingewave.com/REACT_APP_DISTRIBUTOR_ID=REACT_APP_BW_AUTH_TOKEN=

We are going to set your auth token to the REACT_APP_BW_AUTH_TOKEN and your distributor id to REACT_APP_DISTRIBUTOR_ID. You can find your auth token and distributor id here:

https://developers.bingewave.com/queries/distributors#list

Running the list command will give you a list of distributors you currently have. Pick one and use the id. Then, to obtain your Authorization token, click the Authorization Tab as in the picture below, and copy the Token:

IMPORTANT: THIS IS NOT PRODUCTION SAFE. Your auth token should be unique to only one user’s device. Storing a variable in REACT_APP_ as a variable will make this auth token available to everyone. DO NOT do this in production.

Step 4: Site Navigation

We are going to continue to set up our React Application by adding some navigation. Start by importing the router components at the very top of App.js:

import {
BrowserRouter as Router,
Switch,
Route,
} from “react-router-dom”;

Next, we will replace the main return in the App.js with Bootstrap 5 navigation and the rules for when a route is directed toward a page.

Breaking this down into sections:

  1. Router: The <Router> tag will now wrap around all your pages and will work with the <Switch> tag.
  2. HTML Navigation: The HTML with the class navbar, nav-item, nav-link, and other elements is standard Bootstrap 5 navigation. You can read more about it here.
  3. Switch: The Switch component can be thought of as a programmatic Switch statement. Depending on the path option specified inside each route, it loads a specific page.
  4. Home Page: Right now, the only page we have is the <HomePage /> tag. As we as more pages, we will add more routes to the <Switch> tag.

If you go back to the page in your web browser, you should see the navigation menu at the top with the home page text in the main content area.

Step 5: API Calls

We have to make a class for processing our API calls. In the util folder, create a file called Api.js.

touch src/util/Api.js

Inside, create an empty Api object like the below:

const API = {}export default API;

Next, we are going to add three functions. Each function will take a value from our .env specified in step 3 and retrieve it for usage in the app.

  1. getUrlWithApplicationDomain: the function will take whatever URL we pass in and append it to the URL of the API.
  2. _getAuthToken: This will get an authorization token stored in the .env file. IMPORTANT. This is very insecure and should NEVER be done in a production environment. Auth tokens should not be shared, and placing it in an .env file means anyone can have access to that token.
  3. _getDistributorID: Retrieves the id of the current distribution

Your functions should look like the below:

When we call our API, we want to standardize the process for every call. We do not want to do things like implementing our Auth token every single time. Therefore, we will write a function called _call that uses fetch to set up a repeatable way of calling the API with expected results.

This function will handle all the API calls by:

  1. Determining the method (GET, POST, PUT, DELETE)
  2. Retrieving the Auth token and appending it to the header
  3. Handling all the functions for the body
  4. Handing the success and error callback

Going deeper into the success and error callbacks in this part of the code:

.then(function (response) {
if(response.status === ‘success’){
successCallback(response.data); } else if(response.status === ‘failure’){ errorCallback(response.errors); }
})

BingeWave’s API only returns responses with an HTTP 200 status. This means you determine if the response was a success or failure through an if statement that checks the status of the response object. So you have to separate if the call was an error or a success and route them accordingly.

We have one more function to add to our API. An upload function for handling file uploads:

Make sure all these functions are included in your Api.js as its base.

Step 5: Create Video Content

Now that the base API code is complete, we can add calls to BingeWave’s API. Let’s begin with CRUD (Create, Update, View, Delete) for a video. Start by going to the documentation for creating a video:

https://developers.bingewave.com/docs/videos#create

According to the docs, the method is a POST request to bw.bingewave.com/videos. The required fields are title, description, type, and distributor_id.

We can test out the route in the query builder. Below is an example of how your input fields might look.

https://developers.bingewave.com/queries/videos#create

After getting it to work in the query builder, we are going to translate that call into code. Add the following code below to src/utils/API.js file.

First, we are going to create our endpoint. According to the docs, the endpoint for creating pre-recorded content is ‘/videos’. So pass that into _getUrlWithApiDomain will give the full path to the endpoint.

The data variable being passed in should be an object that contains the title, description, and type of content. Next, we are going to set the distributor_id in the data object and finally invoke the __call function we defined earlier. According to the docs, the create content takes a POST function that we are passing in, along with the URL, data, and the success + error callbacks. On successful completion, it will return a video object.

Step 6: Upload Video File

The video file we created in the previous step is just the metadata; we still have to upload the actual video. So we will begin by going to the docs for uploading a file.

https://developers.bingewave.com/docs/videomedia#mainvideo

According to the docs, the id of the video file and the actual file are the two required fields in the request. Head over to query builder to test uploading a file before turning the query into code:

https://developers.bingewave.com/queries/videomedia#mainvideo

Notice the request is a POST, and the URL is:

https://bw.bingewave.com/videos/{id}/setMainVideoFile

The setMainVideoFile is a command, and the command is set to modify the video resource with specified {id}. At the bottom of the query builder, you will see a dropdown of the movies you uploaded. Selecting the movie will modify the {id}. And finally, choose a video to upload. We provide examples to files to test here:

The form should look like this:

Get an upload working and check the request and response. Now let’s turn this into code:

We set the url the endpoint will connect too, and pass that to our _uploadFile function we creator earlier.

Step 7: List Video Files

For our final example, we are going to list any videos you have created. Start with the documentation for listing videos:

https://developers.bingewave.com/docs/videos#list

For getting a list of uploaded videos, a GET request is sent to bw.bingewave.com/videos with the distributor_id required in the parameters. Head over to the query builder:

https://developers.bingewave.com/queries/videos#list

You can select the distributor account you want from the dropdown list to set the parameter, and click Send to get a list of content.

Go through the response to see a list of videos. Finally, let’s turn the request into code, which should be added to you src/util/Api.js.

We define the URL, and add the distributor id as a query parameter, and finally pass it to our _call function has a GET request.

STEP 8: Implement Remaining API Calls

Those are the basics for taking reading through the documentation and query builder and turning it into code. Then, using those same concepts, we can build out the rest of the API. We will not have a detailed explanation of each function, but we strongly encourage you to study the functions and compare them to API. See the documentation and corresponding functions below:

  1. Get Single Video Docs — Get Single Video Query Builder
  2. Create Live Event DocsCreate Live Event Query Builder
  3. List Live Events DocsList Live Events Query Builder
  4. Start Stream DocsStart Stream Query Builder
  5. And other functions represented in code below

Using the docs to get the url path and the request method (GET, POST, PUT, DELETE) for an action, you basically build CRUD (Create, Read, Update, Delete). For example:

  • GET /videos — Retrieves all the video objects
  • GET /videos/id — Retrieves a single video by its id
  • POST /videos — Creates a video file
  • PUT /videos/id — Updates a video based on its ID
  • GET /events — Retrieves all of the events
  • GET /events/id — Retrieves a single event by its ID
  • POST /events — Creates an event
  • PUT /events — Updates a single event by its ID
  • POST /events/id/startStream — Starts an event stream using its id
  • POST /events/id/cancel — Cancels an event at the given id
  • POST /events/id/setWatermark — Sets a watermark to display over the event’s videos

These routes and their request methods can be turned into functions like so:

Step 9: Add Remaining Utilities

To finish up the utilities, we are going to need two more scripts. Start by making the file src/util/appendScript.js .

touch src/util/appendScript.js

Inside that file, copy and paste the following code:

And now create a script to remove code by creating a remove script file:

touch src/util/removeScript.js

And paste the following code:

We are going to need these two scripts to inject and remove BingeWave’s connector script on select pages.

Step 10: Components

The final part tutorial is creating three components. Make these three files:

touch src/components/errors.jstouch src/components/EventListings.jstouch src/components/VideLists.js

Errors.js

BingeWave’s API returns errors as JSON. In that JSON, it breaks down the field the error occurred in and the specific validation check that failed to give the developer more flexibility on how errors can be handled. This component will parse the JSON and return just the errors.

EventListings.js

The live events resource will be an array. This component will be used to display the contents of a live event resource and give your code greater flexibility as you can place this code anywhere. How do you know what content will be returned? You can see the documentation in the response here:

https://developers.bingewave.com/docs/events#list

We can take those returned values and pass them into a React component like the output in EventListing.js below:

Copy and paste the above code EventListing.js.

VideoListings.js

Similar to event listing, the video listings will display a list of video content. You can view the values returned in the response here:

https://developers.bingewave.com/docs/videos#view

Two key concepts to explore are:

  1. Processing State: When a video is uploaded to BingeWave, it can be any format. We convert to a format specialized live streaming, and the current state of the video is represented by numeric values. You see the values if you head over to our process state chart at: https://developers.bingewave.com/types#video_processing_state

2. API.startStream Function: This function calls our API object we created above, which calls the end point https://developers.bingewave.com/docs/eventcommands#startstream . This is used to play the uploaded video when it associated with an event. Matching up with the docs, we are playing a specific video

Copy and paste the above code into VideoListings.js. Also take the time to compare the response to the variables in the code.

Bonus Challenge

One of the functions we did no implement is chunk uploading. Movie files can be many gigabytes (10 GB, 20 GB or even 100 gigabytes). You do not want to upload the entire file but instead, do it in chunks. As a bonus challenge, write and implement a function for uploading chunked files to the API.

Next Steps — Part 2

This completes part one of Building a Live Streaming Movie APP & Live TV Website. Finally, we have the foundation for our application setup. Next, we will build out the pages and forms for uploading content and streaming movies in Part 2 located here.

If you want to review our other tutorials, please checkout our tutorials here!

--

--