logo
Build a UGC Live Streaming App with Amazon IVS: Inviting Chat Users to Join a Stream (Lesson 8.2)

Build a UGC Live Streaming App with Amazon IVS: Inviting Chat Users to Join a Stream (Lesson 8.2)

Welcome to Lesson 8.2 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 3, 2024

In lessons 4.3 and 4.4, we learned how users can invite other users to join them in a low-latency or real-time live stream. To invite other users to join them, StreamCat uses Amazon IVS chat to send invites to viewers. In this lesson, we'll learn how this works.

As mentioned in lesson 8.1, the broadcaster of a live stream is presented an 'admin' menu next to each chat message that contains actions that can be taken by the broadcaster. This lets a broadcaster delete a message, disconnect a user, and invite a user to join them during a live stream.
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
26
27
28
<template x-if="isAdmin">
<div class="dropdown">
<ul class="dropdown-menu">
<template x-if="Number(msg.Sender.UserId) !== Number(userId)">
<li>
<a href="#" class="dropdown-item"
x-on:click="disconnectUser(msg.Sender.UserId)">

Disconnect User
</a>
</li>
</template>
<li>
<a href="#" class="dropdown-item"
x-on:click="deleteMessage(msg.Id)">

Delete Message
</a>
</li>
<template x-if="isAdmin && isMultihost && msg.Sender.Attributes.isGuest !== 'true' && Number(msg.Sender.UserId) !== userId">
<li>
<a href="#" class="dropdown-item"
x-on:click="inviteUserToStage(msg.Sender.UserId, msg.Sender.Attributes.username)">

Invite to Stream
</a>
</li>
</template>
</ul>
</div>
</template>
The 'Invite to Stream' action invokes a function called inviteUserToStage().
1
2
3
4
5
6
7
8
9
10
11
12
async inviteUserToStage(userId, username) {
await fetch('/api/multihost/invite', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
userId,
username,
broadcastType,
chatArn: this.chatArn,
}),
});
}
As we learned in earlier lessons, each user in a real-time stream needs a stage participant token. The /api/multihost/invite endpoint handles generating a token. It also sends a message to that user via the Amazon IVS chat room to notify them that they have been invited to join the stream.
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
Route.post('/multihost/invite', async ({ auth, request, response }) => {
const body = request.body();
const userId = body.userId;
const username = body.username;
const chatArn = body.chatArn;
const broadcastType = body.broadcastType;
if (!userId || !username) throw Error('Invalid multihost token request');
await auth.user?.load('stage');
const stageArn = auth.user?.stage.arn;
if (auth.user && stageArn) {
let token = await RealTimeService.createStageToken(userId, username, stageArn, ['PUBLISH', 'SUBSCRIBE']);
// prettier-ignore
await StageToken.create({
participantId: token.participantToken?.participantId,
token: token.participantToken?.token,
userId: Number(token.participantToken?.userId),
expiresAt: DateTime.fromJSDate(token.participantToken?.expirationTime!),
stageId: auth.user?.stage.id,
});
ChatRoomService.sendChatEvent(chatArn, 'StreamCat:MultihostInvite', { userId, broadcastType, stage: auth.user?.stage.name });
return response.created();
} else {
throw Error('Invalid multihost token request');
}
})
The chat event is sent via the sendChatEvent() method of the ChatRoomService.
1
2
3
4
5
6
7
8
public async sendChatEvent(roomArn: string, eventName: any, attributes: any) {
const request: SendEventCommand = new SendEventCommand({
roomIdentifier: roomArn,
eventName,
attributes,
});
return await this.ivsChatClient.send(request);
}
This sends a custom event called StreamCat:MultihostInvite to all users who are connected to the chat room. The chat room listens for this event, and displays a toast notification to the intended user.
1
2
3
4
5
6
7
if (data.EventName === 'StreamCat:MultihostInvite') {
if (this.userId === Number(data.Attributes.userId)) {
this.stageName = data.Attributes.stage;
this.inviteType = data.Attributes.broadcastType;
bootstrap.Toast.getOrCreateInstance(document.getElementById('invite-notification')).show();
}
}
And the toast notification contains a link that the invited user can click to join the stream.
1
2
3
4
5
6
<div id="invite-notification">
<div class="toast-body">
You have been invited to <a x-bind:href="`/multihost/${inviteType}/${stageName}`">join this stream</a>!
</div>
<button type="button" class="..." data-bs-dismiss="toast" aria-label="Close"></button>
</div>
Since the user has a valid stage participant token, they are granted access to join the live stream when they click on the link.

In this lesson, we learned how the StreamCat application allows broadcasters to invite chat users to join a live stream. In the next lesson, we'll look at retrieving and displaying viewer counts for a live stream.


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