Donnie Prakoso
Posted on April 25, 2022
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.
Github Repository for Demo(s)
Code for this article is available at github.com/donnieprakoso/demo-ivs
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 live 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:
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.
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:
Name | Version | Where to get |
---|---|---|
AWS CDK | 2.17.0 | github.com/aws/aws-cdk |
Python | 3.8.13 | python.org/downloads/release/python-3813/ |
ffmpeg | 4.4 | ffmpeg.org/download.html |
Sample video | N/A | peach.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.
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.
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.
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.
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.
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.
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.
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
Posted on April 25, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.