Build Interactive Live Video Apps with Amazon IVS

Build your streaming channel using Amazon IVS, so you can host them on your website or applications.

Build Interactive Live Video Apps with Amazon IVS
Photo by Jakob Owens / Unsplash

Live streaming is becoming more popular than before as we explore new ways to connect during the restriction in a pandemic situation. In this article, I’ll show you how to build your streaming channel using Amazon IVS, so you can host them on your website or applications. Adding a bit of fun, I’ll also show you how to add an interactive element to your live streaming to engage your audiences even more.

Code for this article is available on this Github repo.


CHALLENGES ON RUNNING LIVE STREAMING PLATFORM

As we are constantly improving how we deliver information — especially in the current situation — live streaming has become one of the solutions. The idea of disseminating real-time information to (practically) unlimited audiences is one reason for running live streaming.

If we want to live stream into video platforms, i.e. YouTube, Vimeo, we can easily setup our OBS and start streaming. But, there’s a case if you want to provide more seamless experience with your business, or to add features that aren’t available in the video platform, you will need to host the libe stream on your website.

The biggest challenge in this case is the complexities of managing infrastructure to deliver low-latency videos. Not to mention how hard it is to bring interactivity into the stream. I’m not talking about greeting every viewer who joined the live stream. I’m talking about getting their responses to any questions in real-time.

Wouldn’t it be great if we can interact with our viewers? If only we can show some a popup dialog right in the stream and viewers can select the options without having to go to external apps or websites.

Or, in the case of e-commerce live streaming, it would be easier for viewers to shop with the presented items on the stream. They just need to click the item, added into their cart, and proceed with checkout.

Delivering the stream helps us to reach more audiences. Interactivity makes it live.


HERE’S AMAZON IVS

So, imagine that now you can set up your live stream channel with just several clicks. Even better, you can programmatically create the live stream channels for any number of the live stream that you’d like to deliver. These channels can also be embedded into your website or applications. You can also add quizzes, polling, or anything that requires feedback from your viewers.

And the good news is, that those features are what you can expect from Amazon IVS. Amazon Interactive Video Service (IVS), is a managed live streaming solution to create interactive video experiences.

Roughly speaking, this is how it works:

Working with Amazon IVS

First, you need to create a channel in Amazon IVS. You will get a stream key and URL as output from this step.

Second, you need to supply the stream key and URL to your favorite broadcasting channel. We have quite a few options — OBS, Streamlabs, XSplit — or you can even use an online live streaming studio such as Streamyard or Restream.

The third step is how you want to host the stream. You can use a website using SDK for Web or mobile applications — using SDK for iOS and Android — to host the stream.

The fourth step is optional if you want to add interactivity. You can send metadata payloads into the stream, and your website or mobile apps can receive and process it accordingly.

And that’s it. You don’t need to provision any infrastructures or expertise to run and scale the live streaming platform.


WHAT WE ARE GOING TO BUILD

If you like what you read so far, the next part will help you to get started. We are going to build a live stream video channel, serve the live stream on a website and send real-time metadata into the stream.

There are 4 main steps in this tutorial.

Steps in This Tutorial
  • Step 1: Provision the Amazon IVS channel.
  • Step 2: Broadcast a video. In this tutorial, I’m going to use the VLC app to ingest the video into Amazon IVS. You can also use OBS or other broadcasting tools, as long as it supports RTMP protocols.
  • Step 3: Run and host a website to serve the live video stream. A quick note in this tutorial, we are going to use a local website. In practice, you can host your website in other AWS services, such as AWS Amplify.
  • Step 4: Once everything is set up properly, the last step is to send metadata to demonstrate how we can add interactivity to the live stream.

REQUIREMENTS

This tutorial uses the following requirements and please make sure that your development environment satisfies all requirements described below:

NameVersionWhere to get
AWS CDK2.17.0github.com/aws/aws-cdk
Python3.8.13python.org/downloads/release/python-3813/
ffmpeg4.4ffmpeg.org/download.html
Sample videoN/Apeach.blender.org/download/

STEP 0: CLONE GITHUB REPO

If you’d like to do this tutorial, you can clone this repo: github.com/donnieprakoso/demo-ivs. Otherwise, carry on reading this tutorial if you’d like to get big pictures of how everything works.

To clone the Git repo, you can run this command on your development environment:

git clone github.com/donnieprakoso/demo-ivs

STEP 1: PROVISION IVS CHANNEL WITH AWS CDK

In this step, we are going to provision the IVS channel with AWS CDK. This tutorial uses AWS Cloud Development Kit (CDK) to provide consistent deployment between this tutorial and yours.

Provision IVS Channel with AWS CDK

CODE OVERVIEW

The cdk/app.py code is the main file to provision your IVS channel. Below is the redacted version of the source code, to point out important parts you need to understand.

First, we need to configure the channel. The code below uses the L1 construct of IVS. This channel uses the basic configuration of the IVS channel, without auto-record enabled to Amazon S3 bucket. Noticed that the authorized parameter is set to false, which translates to disabling playback authorization.

ivs_channel = ivs.CfnChannel(self, "{}-channel".format(id),
            authorized=False,
            latency_mode="LOW",
            name="demo-ivs-metadata",
            recording_configuration_arn="",
            type="STANDARD"
        )

Once we have the channel configured, we need to configure the stream key so we can ingest video into the channel. To pair with the channel, we pass the IVS channel ARN into the channel_arn parameter.

ivs_stream_key = ivs.CfnStreamKey(self, "{}-streamkey".format(id),
            channel_arn=ivs_channel.attr_arn,
        )

Once we have the channel and stream key configured, the next step is to define and instantiates the IVS stack to produce the AWS CloudFormation template. Noticed that we are injecting the account using the environment variable CDK_DEFAULT_ACCOUNT and using the us-east-1 region.

app = App()

env = _cdk.Environment(account=os.environ["CDK_DEFAULT_ACCOUNT"], region="us-east-1")
IvsChannel(app, "demo1-ivs-metadata", env=env)
app.synth()

DEPLOYMENT

To deploy the IVS stack using CDK, follow these steps:

cd 1-stream-channel-timed-metadata/cdk
pip install -r requirements.txt
cdk deploy

This will deploy the IVS channel and you’ll see the output below:

Outputs:
demo1-ivs-metadata.demo1ivsmetadataoutputchannelarn = arn:aws:ivs:us-east-1:XXXXXXXXXX:channel/XXXXXXXXXX
demo1-ivs-metadata.demo1ivsmetadataoutputchannelingest = XXXXXXXXXX.global-contribute.live-video.net
demo1-ivs-metadata.demo1ivsmetadataoutputchannelplayback = https://XXXXXXXXXX.us-east-1.playback.live-video.net/api/video/v1/us-east-1.XXXXXXXXXX.channel.XXXXXXXXXX.m3u8
demo1-ivs-metadata.demo1ivsmetadataoutputstreamkey = XXXXXXXXXX
Stack ARN:
arn:aws:cloudformation:us-east-1:XXXXXXXXXX:stack/demo1-ivs-metadata/XXXXXXXXXX

✨  Total time: 15.72s

These are the information and credential that you can use to start hosting your live stream. Take note of these pieces of information, as we need them in the next steps.

Quick overview of these variables:

  • channelarn is the ARN of your IVS channel. This is required to programmatically interact with your channel.
  • channelingest is the variable to ingest video into your channel.
  • channelplayback is the variable you need to pass into your website so it could play the video
  • streamkey is the key to initiating a live stream. Remember to store your stream key in a safe place as anyone who has the stream key can ingest the video stream into the channel.

STEP 2: INGEST VIDEO WITH FFMPEG

In this step, we are going to ingest video into the IVS channel. Once we have successfully ingested video into IVS channel, our website can start playing the video using the playback URL.

Ingest Video with FFMPEG

To ingest video into the IVS channel, you can use OBS, XSplit, or other broadcasting. In this tutorial, to simplify the demo, we are going to use FFMPEG to stream a video into the IVS channel.

CONFIGURE INGEST ENDPOINT

Before we run the FFMPEG command, we need to configure a few variables on video-stream/stream-video.sh file. You will need two variables: 1) channelingest and 2) streamkey, which you already obtained from deployment with CDK. Also, you need to have a video to ingest into your channel. A good starting point that you can use to test is “Big Buck Bunny” — which you can download from peach.blender.org/download/.

Once you have the required variables, you need to change the following lines on video-stream/stream-video.sh:

TEST_FILE="<YOUR_VIDEO_FILEPATH>.mp4"
STREAM_URL="rtmps://<YOUR_CHANNEL_INGEST>:443/app/<YOUR_STREAM_KEY>"

RUN FFMPEG

You also need to run the following command to make the script executable:

chmod +x stream-video.sh

To run the script, you can use the following command:

./stream-video.sh

And, it will start ingesting the video into your IVS channel.

STEP 3: PLAY VIDEO STREAM ON WEBSITE

At this stage, we already have the IVS channel created and configured with the stream key, and ingesting the video into IVS channel. The next part is to run the website to host the live video stream. With IVS, you can host your live stream on a website or mobile application.

Play video on website

In this tutorial, we use a website to host the live streaming by running the webserver on localhost. In practice, you will need to deploy the website so it can be accessible to your users. There are various ways to do this, two of my favorites approach are hosting it as a static website using AWS Amplify, or you can use Amazon ECS and AWS Fargate to host the dynamic website.

CONFIGURE VARIABLES

The website needs to have the playback URL to identify where it should retrieve the video stream. To do this, get your playback URL variable from the CDK output and open web/index.js, and change the following line:

var PLAYBACK_URL =
  "https://XXXXXXXXXX.us-east-1.playback.live-video.net/api/video/v1/us-east-1.XXXXXXXXXX.channel.XXXXXXXXXX.m3u8";

RUN WEBSERVER

Once you have your app configured, the next step is to run the webserver to host the web page.

Again, there are various ways to do this, and as we are working on Python, the easiest way is to run the following command to run the webserver:

cd web/
python -m http.server 8080

Then, open your browser and point the URL to http://localhost:8080. You will find a page below and watch the video ingested from IVS playing.

Demo Preview: Check live stream from web browser

If you can see a similar page like this, Congrats! You just successfully integrate your IVS channel and your web page. If you don’t, let me know in the comments below so I can help you out.

STEP 4: SENDING TIMED METADATA

In previous steps, we configured and ingested live video, and host a website to playback the video. These steps are the starting point for you to run a live streaming platform.

Now, we’d like to take it to the next level by adding an interactive element to your live stream. The key to interactivity is the ability to send out a message (or payload) into the live video stream. With IVS, you can send this message as timed metadata. In short, timed metadata is data about other data equipped with timestamps that are sent simultaneously to every viewer in any channel.

Send Timed Metadata

The implementation of timed metadata isn’t as complicated as its definition, and in this step, I’ll explain how you can implement it.

GENERATOR (APP) CODE OVERVIEW

The main application to send timed metadata into the IVS channel is located at timed-metadata/app.py. In this generator app, the payload we are going to send into the stream is a JSON data with the following structure:

{
  "current_time": "2022-Apr-14-153617",
  "question": "Question : 1",
  "answers": ["True", "False"]
}

This is just an example of a payload and all payloads are populated by the following code:

data = {
            "current_time": datetime.datetime.utcnow().strftime('%Y-%b-%d-%H%M%S'),
            "question": "Question : {}".format(i),
            "answers": [
                "True",
                "False"
            ]
        }

Once we have the payload, we can send it to particular IVS channel by calling put_metadata API from IVS. Following lines show how to send metadata into IVS channel:

response = ivs.put_metadata(
                channelArn=channel_arn,
                metadata=json.dumps(data)
            )

Once the request is successfully sent, the stream will receive the following metadata:

{
  "startTime": 3.458,
  "endTime": 3.458,
  "type": "TextMetadataCue",
  "description": "",
  "text": "{\"current_time\": \"2022-Apr-14-153617\", \"question\": \"Question : 8\", \"answers\": [\"True\", \"False\"]}"
}

With this data, you can build your interactive element by processing the metadata received on the text property.

RECEIVER (WEB) CODE OVERVIEW

In the previous step, we evaluated the generator app to send the timed metadata. We still need to receive the timed metadata on our web page. Let’s review how we can instantiate the IVS player and how to receive the metadata.

The web page itself is built with 2 files: web/index.html and web/index.js. The main logic to consume the timed metadata is on web/index.js.

The first thing that you need to configure on this file is the PLAYBACK_URL. Simply replace the variable value with the value you obtained from CDK deployment outputs.

var PLAYBACK_URL =
  "https://XXXXXXXXXX.us-east-1.playback.live-video.net/api/video/v1/us-east-1.XXXXXXXXXX.channel.XXXXXXXXXX.m3u8";

As for the IVS player, I’m using VideoJS integration, and the following lines show how to instantiate the player:

var player = videojs(
  "amazon-ivs-videojs",
  {
    techOrder: ["AmazonIVS"],
  },
  () => {
    player.src(PLAYBACK_URL);
  }
);

To receive the timed metadata, we need to add event_listener.

player
  .getIVSPlayer()
  .addEventListener(PlayerEventType.TEXT_METADATA_CUE, fn_metadata);

This way, we invoke the fn_metadata function whenever the player receives timed metadata from IVS.

SENDING TIMED METADATA

To demonstrate sending metadata into the stream, you will need your IVS channel ARN. Once you have the channel ARN, you can pass it as input to the timed-metadata/app.py application.

To send the metadata, you can run this command:

python app.py arn:aws:ivs:us-east-1:XXXXXXXXXX:channel/XXXXXXXXXX

To stop the application, you need to press Ctrl-C.

Once you successfully run the application, it will send the metadata into the IVS channel and it will be received by the web page. If you go to the web page, it will show the timed metadata on the right column.

Demo Preview: Website receives timed metadata

WHAT’S NEXT?

You’re probably wondering, what you can do with this metadata. This metadata is the raw form for adding interactivity. You can add pop-up dialog for running quizzes like the screenshot below using the metadata payload you configure from your application.

Demo Preview: Pop-up dialog

STEP 5: CLEANING UP

Don’t forget to remove all resources once you’re done with the tutorial. To do cleanup, do the following steps:

cd cdk/
cdk destroy

Choose “Yes” and CDK will remove all resources created.


WRAPPING UP

In conclusion, I found it’s easy to run low-latency live streaming with Amazon IVS. Equipped with a timed metadata feature, it provides a simple way to add interactive elements with viewers and take your live streaming experience to the next level.

I hope this tutorial provides you with a good understanding of how Amazon IVS works. In the next post, I’ll cover how to restrict playback access with authorization for a private channel.

Happy building!🤘🏻
— Donnie