logo
Build a UGC Live Streaming App with Amazon IVS: Adding Chat Replay During VOD Playback (Lesson 8.5)

Build a UGC Live Streaming App with Amazon IVS: Adding Chat Replay During VOD Playback (Lesson 8.5)

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

TS
Todd Sharp
Amazon Employee
Published Jan 8, 2024

In this lesson, we'll look at how the StreamCat application provides chat replay during VOD playback.

In lesson 8.1, we saw how to add interactivity to a user's channel by adding live chat. We also learned how the application persists chat events to the database so that it can later be retrieved and replayed during VOD playback. Let's see how StreamCat retrieves those chat events and replays them.
As we saw previously, the streamId of the live stream is persisted for all chat messages. This means that we can query for all chat messages that contain this streamId.
1
2
3
4
const chatLog = await ChatMessage
.query()
.where('streamId', params.streamId)
.preload('sentBy');
VOD chat is rendered in a container that looks very similar to the "regular" chat container. The main change here is that all chat messages are rendered when playback starts, and the messages that should not yet be displayed are hidden until the point in time they were posted.
1
2
3
4
5
6
7
8
9
10
<div id="chat-container" x-data="chatmodel({{chatLog}})">
<div id="chat">
<template x-for="msg in chatLog" id="chat-msg-template">
<div x-show="new Date(msg.sentAt).getTime() <= currentTimestamp">
<span class="fw-bold chat-username" x-text="msg.sentBy.username"></span>:&nbsp;
<span class="msg" x-bind:data-msg-id="msg.id" x-text="msg.content"></span>
</div>
</template>
</div>
</div>
The x-show attribute that checks if the msg.sentAt property is less than or equal to the currentTimestamp is what determines if a message is visible or not. The currentTimestamp variable is updated in the model, and pulls that value from the VOD's metadata.
1
2
3
4
5
Alpine.raw(this.ivsPlayer).addEventListener(IVSPlayer.MetadataEventType.ID3, (evt) => {
const segmentMetadata = evt.find((tag) => tag.desc === 'segmentmetadata');
const segmentMetadataInfo = JSON.parse(segmentMetadata.info[0]);
this.currentTimestamp = segmentMetadataInfo['transc_s'];
});
This solution ensures that only the messages posted at or before the timestamp in the VOD is rendered. If a viewer seeks within the VOD, the next time the ID3 listener fires will update the currentTimestamp variable which means the chat will immediately "catch up" to the VOD. This event fires approximately every 1-3 seconds, so we can be confident that chat replay will stay up to date during VOD playback.

In this lesson, we learned how the StreamCat application replays user chat during VOD playback. In the next lesson, we'll look at how to retrieve and display stream session metrics.


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