Select your cookie preferences

We use essential cookies and similar tools that are necessary to provide our site and services. We use performance cookies to collect anonymous statistics, so we can understand how customers use our site and make improvements. Essential cookies cannot be deactivated, but you can choose “Customize” or “Decline” to decline performance cookies.

If you agree, AWS and approved third parties will also use cookies to provide useful site features, remember your preferences, and display relevant content, including relevant advertising. To accept or decline all non-essential cookies, choose “Accept” or “Decline.” To make more detailed choices, choose “Customize.”

AWS Logo
Menu
Build a UGC Live Streaming App with Amazon IVS: Responding to Stream State Events (Lesson 3.5)

Build a UGC Live Streaming App with Amazon IVS: Responding to Stream State Events (Lesson 3.5)

Welcome to Lesson 3.5 in this series where we're looking at building a web based user-generated content live streaming application with Amazon IVS. This entire series is available in video format on the AWS Developers YouTube channel and all of the code related to the sample application used in this series can be viewed on GitHub. Refer to the links at the end of the post for more information.

Todd Sharp
Amazon Employee
Published Dec 14, 2023

Intro

In this lesson, we'll look at how StreamCat responds to stream state events to update a channel's state or publish a VOD asset for a previous broadcast. If you recall from lesson 1.4, StreamCat uses an Amazon EventBridge rule to listen for various state change events related to our Amazon IVS channels. This EventBridge rule triggers an AWS Lambda function, and that function persists and updates database records as necessary. In this lesson, we'll focus on how StreamCat handles the following events:
  1. Stream Start
  2. Stream End
  3. Recording Start
  4. Recording End
Let's look at how StreamCat responds to the various events.

Event Format

If you recall lesson 1.4, the Amazon EventBridge rule that is created for StreamCat listens for the following event types:
1
2
3
4
[
'IVS Stream State Change',
'IVS Recording State Change'
]
The event that is passed to our AWS Lambda function that is triggered by this rule varies slightly depending on the specific event that triggered it, but there are several values that are common between the various event types.
Here's a sample 'Stream Start' event:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"version": "0",
"id": "[redacted]",
"detail-type": "IVS Stream State Change",
"source": "aws.ivs",
"account": "[redacted]",
"time": "2023-05-16T15:54:09Z",
"region": "us-east-1",
"resources": [
"arn:aws:ivs:us-east-1:[redacted]:channel/[redacted]"
],
"detail": {
"event_name": "Stream Start",
"channel_name": "[redacted]",
"stream_id": "[redacted]"
}
}
And here's a 'Recording End' event:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
"version": "0",
"id": "[redacted]",
"detail-type": "IVS Recording State Change",
"source": "aws.ivs",
"account": "[redacted]",
"time": "2023-06-14T14:33:16Z",
"region": "us-east-1",
"resources": [
"arn:aws:ivs:us-east-1:[redacted]:channel/[redacted]"
],
"detail": {
"recording_status": "Recording End",
"recording_status_reason": "",
"recording_s3_bucket_name": "streamcat-vod-storage",
"recording_s3_key_prefix": "ivs/v1/[redacted]",
"recording_duration_ms": 1000,
"channel_name": "[redacted]",
"stream_id": "[redacted]",
"recording_session_id": "[redacted]",
"recording_session_stream_ids": [
"[redacted]"
]
}
}

Stream Start and End Events

When a stream begins on an Amazon IVS channel, StreamCat:
  • Updates the Channel to set isLive to true
  • Inserts a new Stream object in the database.
💡 Note: Refer to lesson 1 to learn more about StreamCat's schema and the relationship between Channel and Stream.
When the triggering event is either Stream Start or Stream End, we can use the event.detail.event_name property to determine the proper value to set Channel.isLive.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const isLive = event.detail.event_name === 'Stream Start';
const channelResult = await client.query(`
select id, title, category_id
from channels
where arn = $1`
,
[
event.resources[0]
]
);
const channelId = channelResult.rows[0].id;
await client.query(`
update channels
set is_live = $1
where id = $2`
,
[
isLive,
channelId
]
);
Next, we can either insert or update a Stream record depending on whether or not one exists for the given stream_id. This method captures the title, and category_id of the Channel when the broadcast began
1
2
3
4
5
6
7
8
9
10
11
12
13
await client.query(`
insert into streams (stream_id, channel_id, started_at, title, category_id )
values ($1, $2, $3, $4, $5)
on conflict(stream_id) do update set
${isLive ? 'started_at' : 'ended_at'} = $3`
,
[
event.detail.stream_id,
channelId,
event.time,
channelResult.rows[0].title,
channelResult.rows[0]?.category_id || null,
]
);

Recording Start Event

When a recording starts, StreamCat either inserts or updates the existing Stream to persist the recording_started_at, the recording_path, and the Channel's title at the time the recording began to the VOD recording for the given stream.
💡 Note: Technically, the Stream should already exist (since it's created on the Stream Start event), but sometimes these events fire nearly simultaneously, so it's best to handle the possibility that a Stream might not exist yet when the Recording Start event is handled.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
client.query(`
insert into streams (stream_id, channel_id, recording_started_at, title, recording_path)
values ($1, $2, $3, $4, $5)
on conflict(stream_id) do update set
recording_started_at = $3,
recording_path = $5`
,
[
event.detail.stream_id,
channelId,
event.time,
channelResult.rows[0].title,
event.detail?.recording_s3_key_prefix,
]
);

Recording End Event

When the Recording End event fires, StreamCat finalizes the Stream record to capture the recording_end_date, recording_duration_ms, and recording_path.
1
2
3
4
5
6
7
8
9
10
11
12
13
client.query(`
update streams set
recording_ended_at = $1,
recording_duration_ms = $2,
recording_path = $3
where stream_id = $4`
,
[
event.time,
event.detail?.recording_duration_ms,
event.detail?.recording_s3_key_prefix,
event.detail.stream_id,
]
);

Summary

In this lesson, we saw how StreamCat persists stream state change events to the database. These state changes give StreamCat several methods to help users discover content, such as listing currently 'live' channels, and searching for a past broadcast. In a future lesson, we'll see how chat messages are also persisted to the database when a stream ends.
This concludes lesson 3. In this lesson, we learned many concepts related to broadcasting low-latency live streams with the Amazon IVS SDK, as well as how StreamCat captures stream state change events. In lesson 4, we'll start to look how StreamCat enables broadcasting for real-time live streams.

Links

Any opinions in this post are those of the individual author and may not reflect the opinions of AWS.

Comments

Log in to comment