How To Build A Low Latency Live Shopping App

Devin Dixon
BingeWave
Published in
12 min readOct 27, 2022

When building live shopping solutions, latency will determine the experiences you can make for your users. For example, can you have a real-life countdown until a product sells out? Or does that 10 to 40-second delay make true real-time experiences impossible?

In this tutorial, we will cover how to develop a shopping application with a standard latency of around 20 seconds and then an app with a latency that is down to milliseconds. The goal of low-latency shopping applications will be to develop more interactive experiences between hosts and end-users.

The tool we will be using is BingeWav’e Live Media Platform. BingeWave is a Live Media as a Service platform that allows the creation of fully custom video conferencing, audio conferencing, augmented reality and live streaming solutions to be built with no-code and low-code.

Understanding Latency And Protocols

Before getting into coding, the first thing to understand is the concept of latency and how different protocols for live video affect it. Latency is the amount of time that passes from when an action occurs on the video to when the user watches that action. For example, a user might say “Hello!” and the people watching see the person saying “Hello” 15 seconds later.

In others words, we are always watching the past. But how much of the past we watch can depend on the live video delivery protocol. There are three common protocols used:

  • WebRTC — A light way protocol with latency down to milliseconds but is very expensive to scale.
  • RTMP — An old protocol from the Flash era that is still used today for primarily transporting video from one source to another.
  • HLS — A video protocol introduced by Apple with excellent buffering and scalability but often can have 10 to 40 seconds of latency.

In this tutorial, we will focus on the delivery methods of HLS and WebRTC to build live-streaming applications.

Creating Our Live Shopping Interface

To start, we will need to create a live shopping interface for the hosts and the users. If you have not created an organizer account, you must create one here. Creating one takes a few seconds.

After your organization account is created, head to the dashboard of your organizer account:

Because this is live shopping, we will need to create a product. First, enable merchandizing. Click on the COG:

From there, you will see a Merchandise section. Click into it and enter the information for enabling merchandising.

Now, head over to the products section and create one.

After a product has been created, click on the Templates section:

And create a new template. Now you can customize an experience. This part of the tutorial will be on your own as you learn how to use the interface builder, but please try to execute the following:

  1. For the host and panelist roles, set the video layout to be a Gallery, with the Gallery participants per row being three people.
  2. For the Broadcaster/Recorder role, set the layout to be User In Center with Audience at the bottom.
  3. Enable dominant toggling for all the users.
  4. On the widgets section, add the video On/Off, Audio Mute/Unmute, Broadcast, Heart Emojis, Text Chats and On-Screen Products widgets to the interface.
  5. Set the Video/on and Audio/on for both the hosts and panelist roles and position the widgets in the Footer Center.
  6. Set the Broadcast widget for the host and position it in the Footer Center.
  7. Position the On Screen Products widget in the Aside Right Top and activate for only the host role.
  8. Position the Text Chat widget in the Aside Right Right, and only enable for the participant and streamer roles.
  9. Set the Heart widget only for the streamer and in the Footer Center.
  10. In the Alignments tab, align the items in the footer appropriately (center, left, right).
  11. In the Streaming Tab, select if you want this to be 4k, Standard or Low Latency streaming.
  12. Finally, click the Advanced tab, and if you know some CSS, add some padding to the header and footer to center the contents and turn the background black.

As an example, your Widget selection should look something like the below:

The above steps should be an exercise in playing around with the interface builder. Once you get a decent understanding of the tool, you can customize items as you wish.Now it is time to test the template. Scroll down to the test area and join the session to see yourself appear on the screen.

Then click the ‘Start Broadcast’.

In the test area, click on the Broadcast tab, and in about 20 seconds, you will see a broadcast of yourself appear.

Go back to the Video Conferencing tab in the test area and send a product on-screen with the On-Screen Products widget.

Remember to save your template! Returns to the main area for templates and find the ID of the template you just created.

Remember where this ID is located, as you will need it later for future steps.

Required Step: Enable The WebRTC For Localhost

Before moving on to the next steps, you must enable the WebRTC for localhost. By default, browsers will block WebRTC connections that are not behind an SSL website, and you will get an error message that says something like:

getUserMedia Permission Denied

To get around this limitation, read here on how to enable WebRTC for localhost. Afterward, your local host will work fine for video and audio connections.

React Frontend

We will only use a React front end to keep this tutorial as brief as possible. Therefore, some of the practices we will implement the code here that SHOULD NOT be used in production and are only for testing purposes.

Start by making a React Application called live-shopping.

npx create-react-app live-shopping
cd live-shopping

Now we are going to install some required libraries. First, install the Invirtu React Widgets:

npm install invirtu-react-widgets --save

Next, install the Invirtu Javascript API:

npm install invirtu-javascript-api --save

For navigation, we are going to install React Router Version 6

npm install react-router-dom@6 --save

And the final package we are going to install is BootStrap 5:

npm install react-bootstrap bootstrap --save

With all the required packages installed, we can begin to develop your basic application. First, with your favorite editor, in the src/index.js file of the application, we are going to import Boostrap for styling:

import ‘bootstrap/dist/css/bootstrap.min.css’;

Import the BrowserRouter for routing

import { BrowserRouter } from “react-router-dom”;

And then wrap the App in the BrowserRoute.

<BrowserRouter>
<App />
</BrowserRouter>

The completed src/index.js will look like this:

We are going to create five pages for the application. On the command line, you can enter the following:

mkdir -p src/pagestouch src/pages/HomePage.jstouch src/pages/EventsPage.jstouch src/pages/WatchPage.jstouch src/pages/VideoPage.jstouch src/pages/StreamPage.jstouch src/pages/CreatePage.js

With your favorite editor, enter the following in each to start:

src/pages/HomePage.js

src/pages/EventsPage.js

src/pages/WatchPage.js

src/pages/VideoPage.js

src/pages/CreatePage.js

src/pages/StreamPage.js

Finally, in the src/App.js, we need to add the routes to the App can switch pages. Start by removing the other imports in the header and import the React Router Components:

import { Routes, Route, Link } from “react-router-dom”;

Then import the pages:

import CreatePage from “./pages/CreatePage”;import EventsPage from “./pages/EventsPage”;import HomePage from “./pages/HomePage”;import VideoPage from “./pages/VideoPage”;import WatchPage from “./pages/WatchPage”;import StreamPage from “./pages/StreamPage”;

Remove everything from inside the App’s return function and replace it with the routes to the pages defined above:

<Routes>
<Route path=”/” element={<HomePage />} />
<Route path=”/events” element={<EventsPage />} />
<Route path=”/create” element={<CreatePage />} />
<Route path=”/video/:id” element={<VideoPage />} />
<Route path=”/watch/:id” element={<WatchPage />} />
<Route path=”/stream/:id” element={<StreamPage />} />
</Routes>

And finally, above the routes, add some bootstrap navigation to switch between pages:

The completed App.js should resemble the following:

In your command line, run ‘npm start’, and your App should boot up with the ability to switch between pages. Now we can get into some of the meat of the application.

Getting The API Token

Before going into the next part of the application, we will need to get the API keys. First, go to the Organizers section of the application:

From The Organizer Site:

From The Developers Site:

Click into the Tokens section and generate a new token.

Once the token is generated, we will create an .env file and place the information inside.

touch .env

WARNING: What we are about to do should NEVER be done in production as this is sensitive data and should never be exposed in the front end. In the env file, place the following:

REACT_APP_AUTH_TOKEN=[REPLACE WITH ORGANIZER JWT]REACT_APP_ORGANIZER_ID=[REPLACE WITH ORGANIZER ID]

As the values suggest, replace the placeholder for the token with the Auth Token generated above. Also, replace the organizer_id with the ID of the organizer.

Next, we need to get your user token to authenticate you as a user. Click on your Person icon at the top of the screen to load your account information. Click on the Tokens tab, and you will be brought to a page with a list of your JWT Tokens.

If you have not already created a token, create one. Afterward, copy the token into the .env file as such:

REACT_APP_USER_AUTH_TOKEN=[REPLACE WITH USER JWT]

Finally, go back to the templates and find your template ID from the previous step. Enter the template ID into the .env as well.

REACT_APP_TEMPLATE_ID=[REPLACE WITH THE TEMPLATE ID]

Please keep in mind this current implementation is only for testing and demonstration purposes; this is very insecure for a production website.

High Latency Live Shopping App

The first implementation of the Live Shopping App is going to be the version with high latency (meaning it will be slow for users), but it will be much easier to scale and more cost-efficient. The protocol this version will be using is HLS.

The process will be:

  1. The host will have their live shopping experience with others using WebRTC Video Conferencing
  2. The WebRTC is converted to an RTMP stream that is sent to server endpoints to consume
  3. The servers at the destination endpoint convert the RTMP to HLS
  4. Users watch the HLS stream on their page

A diagram that shows how the process works is below:

Next, we will implement a page for creating a live event. In BingeWave, all video conferencing, audio conferencing, live streams, and AR experiences are considered live events. The documentation for creating a live event is here:

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

The required fields are the organizer_id and the type, and we are going to add the template_id to copy the interface we created into the live event The list of types can be found here, and the type we are going to use is an Instant Event.

Using the Javascript API installed earlier, we do not have to worry about the other parts of calling the API beyond the data that should be passed. In the src/pages/CreatePage.js, start by importing the API:

import { Config, Events } from “invirtu-javascript-api”;
import { Link } from "react-router-dom";

Next, we want to pass the Organizer Token into the Config. This should NOT be done in production as it will expose sensitive information. Now we can add a function for creating the event.

Config.setAuthToken(process.env.REACT_APP_AUTH_TOKEN);

When the function returns a result, we will then add that result to the main area. Finally, we update the render section to call the create function and also render its contents when a successful live event has been created.

The final src/pages/CreatePage.js should look like this:

Now let us create a page to retrieve all the events that have been created in the past. We are going to call the getEvents function and populate the current page with only recent events. In the src/pages/EventsPage.js, paste the following:

There are two pages we should start to input content into now, the VideoPage and the StreamPage. The video page will serve as the page where hosts are able to join. We can use the Widget library we imported before for the widget and the useParams from the React Router.

import { VideoConferencing } from “invirtu-react-widgets”;
import { useParams } from ‘react-router’;

The ID of the event we will retrieve from the useParams function, but we want to log the user into the Video Conferencing session correctly. For that to occur, we need to pass in their authentication token in the widget. In a prior step, we associated your auth token with REACT_APP_USER_AUTH_TOKEN. That token will not be passed into the VideoConferencing widget as such:

<VideoConferencing id={id} auth_token={process.env.REACT_APP_USER_AUTH_TOKEN} />

Your complete video page should look like this:

And when a user loads the page and joins, they should appear on-screen. Test out the implementation to see yourself appear in the video area you designed in the interface builder.

Next, let’s flush out the stream page. On this page, the users can watch the stream as it is broadcasted from the video chat. We are going to use the broadcast widget, and we are not going to pass a JSON Web Token because we do not need to authenticate. Your stream page will resemble the one below.

To fully test out the broadcast, join the video page in one window and watch the stream in another window. Test out the functionality by sending a few products to appear on-screen using the On-Screen Product Widget you placed in the right aside per the earlier instructions.

You will notice in the stream there is a delay of around 10 to 40 seconds based on a variety of factories and latency settings you previously set. Now let’s make an improvement to go really low latency.

Ultra Low Latency Live Shopping

To obtain millisecond latency for a live shopping experience, we are going to make a few changes; one of them is we won’t be using HLS at all anymore for video streaming. Instead, we will have everyone connect via WebRTC but hide the other users.

Start by going back to the template for your living shopping experience, click on the interface builder, and click on the Video Layout tab. Scroll down until you reach a spot that says Video/Audio Off:

This option means that when a user who falls into one of the roles joins a session, they will not be prompted for their video or audio and therefore join the video session as an invisible user. Set the role participant to have their video/audio off when joining a call and save the template.

Now inside the watch page at src/pages/WatchPage.js, it will look just like the video page with one exception; we will not pass the JWT Auth Token.

Without a JWT Token, the default user that will be registered is an anonymous user, and their role will be a participant. In an incognito window, open up the watch page. Incognito is being used so as not to share the browser’s cookie information. When the session is joined in the incognito window, your video will not show up, but the host video will! The best part, the latency is not noticeable.

You are invisibly watching, and the latency will be in milliseconds because the video will be delivered through WebRTC. This approach is amazing! What is the catch?

This approach is more costly to scale. Unlike the HLS approach, where the user downloads the files, which uses fewer resources on the servers, the WebRTC approach pushes the stream to the users. Therefore the server has to do more work when every user connects, which becomes more costly to scale.

Download The Code

To download the code the tutorial, you can visit this Github Url: https://github.com/Invirtu-Tutorial-Examples/Low-Latency-Live-Shopping

--

--