logo
Build a UGC Live Streaming App with Amazon IVS: Displaying Stream Session Metrics (Lesson 9.1)

Build a UGC Live Streaming App with Amazon IVS: Displaying Stream Session Metrics (Lesson 9.1)

Welcome to Lesson 9.1 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.

TS
Todd Sharp
Amazon Employee
Published Jan 8, 2024

In this lesson, we'll look at how the StreamCat application retrieves and displays stream session playback metrics.

In lesson 7.1, we saw how StreamCat captures playback and session metrics during a live stream and persists that data to the database. Let's see how that data is queried and displayed to a user so they can gain insight into their streams and viewers.
StreamCat aggregates and provides insight into the following metric categories in the user's dashboard for all of their live streams:
  1. Viewers
  2. Chat Messages
  3. Viewer Browsers
  4. Viewer Operating System
  5. Playback Quality
  6. Playback Latency
  7. Playback Buffer
  8. Playback Bitrate

The following query is used to retrieve stream viewers over time. The data is aggregated at a 5 minute (300 seconds) interval.
1
2
3
4
5
6
7
8
9
10
const viewers = await Database.rawQuery(`
select
count(distinct ip) as viewers,
TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round(extract('epoch' from created_at) / 300) * 300 as time
from metrics
where stream_id = ?
group by TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round(extract('epoch' from created_at) / 300) * 300
order by TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round(extract('epoch' from created_at) / 300) * 300
`
, [params.streamId]
);
This data is used to create a line chart in the user's dashboard for each stream.
Unique Viewers
Unique Viewers

The following query is used to retrieve chat messages over time. The data is aggregated at a 5 minute (300 seconds) interval.
1
2
3
4
5
6
7
8
9
10
const chatMessages = await Database.rawQuery(`
select
count(distinct id) as messages,
TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round(extract('epoch' from sent_at) / 60) * 60 as time_period
from chat_messages
where stream_id = ?
group by TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round(extract('epoch' from sent_at) / 60) * 60
order by TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round(extract('epoch' from sent_at) / 60) * 60
`
, [params.streamId]
);
This data is presented in a bar chart.
Chat Messages
Chat Messages

The following query is used to retrieve viewer browsers.
1
2
3
4
5
6
7
8
9
const browsers = await Database.rawQuery(`
select
count(distinct ip) as viewers,
browser_name
from metrics
where stream_id = ?
group by browser_name
`
, [params.streamId]
);
The data is presented as a pie chart.
Browsers
Browsers

The following query is used to retrieve viewer operating systems.
1
2
3
4
5
6
7
8
9
const os = await Database.rawQuery(`
select
count(distinct ip) as viewers,
os
from metrics
where stream_id = ?
group by os
`
, [params.streamId]
);
This data is presented as a pie chart.
OS
OS

The following query is used to retrieve playback quality.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const quality = await Database.rawQuery(`
with total as (
select count(id) as total
from metrics
where stream_id = ?
)
select
quality,
case when total.total > 0
then round((count(id)::decimal / total.total::decimal) * 100, 2)
else 0
end as pct
from metrics, total
where stream_id = ?
group by quality, total.total
`
, [params.streamId, params.streamId]
);
This data is presented as a pie chart.
Playback Quality
Playback Quality

The following query is used to retrieve playback latency. The data is aggregated at a 5 minute (300 seconds) interval.
1
2
3
4
5
6
7
8
9
10
const avgLatency = await Database.rawQuery(`
select
avg(latency) as avg_latency,
TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round(extract('epoch' from created_at) / 300) * 300 as time_period
from metrics
where stream_id = ?
group by TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round(extract('epoch' from created_at) / 300) * 300
order by TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round(extract('epoch' from created_at) / 300) * 300
`
, [params.streamId]
);
This data is presented as a line chart.
Playback Latency
Playback Latency

The following query is used to retrieve playback buffer. The data is aggregated at a 5 minute (300 seconds) interval.
1
2
3
4
5
6
7
8
9
10
const avgBuffer = await Database.rawQuery(`
select
avg(buffer) as avg_buffer,
TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round(extract('epoch' from created_at) / 300) * 300 as time_period
from metrics
where stream_id = ?
group by TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round(extract('epoch' from created_at) / 300) * 300
order by TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round(extract('epoch' from created_at) / 300) * 300
`
, [params.streamId]
);
This data is presented as a line chart.
Playback Buffer
Playback Buffer

The following query is used to retrieve playback bitrate. The data is aggregated at a 5 minute (300 seconds) interval.
1
2
3
4
5
6
7
8
9
10
const avgBitrate = await Database.rawQuery(`
select
avg(bitrate / 1000) as avg_bitrate,
TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round(extract('epoch' from created_at) / 300) * 300 as time_period
from metrics
where stream_id = ?
group by TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round(extract('epoch' from created_at) / 300) * 300
order by TIMESTAMP WITH TIME ZONE 'epoch' + INTERVAL '1 second' * round(extract('epoch' from created_at) / 300) * 300
`
, [params.streamId]
);
This data is presented as a line chart.
Playback Bitrate
Playback Bitrate

In this lesson, we learned how the StreamCat application queries playback and session metric data from the database. This data is presented to stream broadcasters so that they can gain insight into their stream viewers. Your application may choose to aggregate the data at a higher level to gain insight into your application viewers technology choices and the performance of your user's streams.
This lesson concludes this course. I sincerely hope that you have found the content in this course valuable and that you've learned something new about building live streaming application with Amazon Interactive Video Service. If you have any comments or questions about the content in this course, please feel free to reach out to Todd Sharp on Twitter (@recursivecodes) or LinkedIn. To learn more about Amazon IVS, check out https://ivs.rocks.


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