Skip to main content
Version: 5.x.x

Manage Roles - Flutter

Roles with VideoSDK​

When doing interactive live streaming maintaining the role of users is quite important. To help manage these roles better, VideoSDK allows a participant with two types of modes:

1. SEND_AND_RECV When a participant is joining with mode set to SEND_AND_RECV, the participant sends media and receives the media of other participants, and can interact with them using the features like chat, poll etc.

2. SIGNALLING_ONLY When a participant is joining with mode set to SIGNALLING_ONLY, that participant neither sends nor receives media. They can still interact with other participants using chat, polls etc.

info

Important Changes Flutter SDK in Version v1.3.0

  • The following modes have been deprecated:
    • CONFERENCE has been replaced by SEND_AND_RECV
    • VIEWER has been replaced by SIGNALLING_ONLY

Please update your implementation to use the new modes.

⚠️ Compatibility Notice:
To ensure a seamless meeting experience, all participants must use the same SDK version.
Do not mix version v1.3.0 + with older versions, as it may cause significant conflicts.

manage-roles

When to use the Roles?​

1. Simple Adaptive Streaming​
  • Simple Adaptive Streaming (SAS) is a type of livestreaming that requires minimal interaction between the host and viewers.

  • It is particularly useful for events with a large number of viewers who prefer not to engage with the host.

  • In SAS, each speaker attends a VideoSDK room in SEND_AND_RECV mode, while viewers can simply watch the livestream using the playbackHlsUrl or livestreamUrl. Unlike the speakers, viewers do not need to join the room in SEND_AND_RECV or SIGNALLING_ONLY mode.

    • playbackHlsUrl - Live HLS with playback support
    • livestreamUrl - Live HLS without playback support
2. Adaptive Streaming with increased engagement​
  • If you're looking to increase engagement with your audience during a live streaming event, consider using Adaptive Streaming technology. With this approach, you can incorporate interactive features such as polls and conversations, and give viewers the ability to join and leave the livestream as the host decides.

  • To set this up, have all speakers join as SEND_AND_RECV mode participants, while the audience joins as SIGNALLING_ONLY mode participants. This way, everyone can participate in the interactive elements of the live stream and create a more dynamic and engaging experience for all.

Using roles​

The mode of the participants is set during the creating the room.

room.localParticipant.mode changes once the server applies a new mode, just before the participantModeChanged event fires. The example below reads it in that event.

import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class RoomScreen extends StatefulWidget {
final String roomId;
final String token;

const RoomScreen(
{super.key, required this.roomId, required this.token});

@override
State<RoomScreen> createState() => _RoomScreenState();
}

class _RoomScreenState extends State<RoomScreen> {
late Room _room;

Mode? localParticipantMode;

@override
void initState() {
super.initState();

//Creating a new Room based on the passed roomId and token from the Joining Screen
// create room
_room = VideoSDK.createRoom(
roomId: widget.roomId,
token: widget.token,
participantName: "John Doe",
micEnabled: true,
camEnabled: true,
defaultCamera: FacingMode.FRONT, // Camera to use when the room starts
mode: Mode.SEND_AND_RECV, // or Mode.SIGNALLING_ONLY; SEND_AND_RECV when left out
);

setRoomEventListener();

joinRoom();
}

Future<void> joinRoom() async {
try {
await _room.join();
} on VideoSDKError catch (error) {
log("Could not join the room: ${error.code} ${error.name}");
}
}

@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.black,
//Show Speaker view if mode is SEND_AND_RECV else show Viewer View
body: localParticipantMode != null
? localParticipantMode == Mode.SEND_AND_RECV
? ILSSpeakerView(room: _room)
: localParticipantMode == Mode.SIGNALLING_ONLY
? ILSViewerView(room: _room)
: null
: const Center(
child: Text("Joining...")),
),
);
}

void setRoomEventListener(){
_room.on(Events.roomJoined, (){
setState(()=>localParticipantMode = _room.localParticipant.mode);
});

_room.on(Events.participantModeChanged, (Map<String, dynamic> data){
if (data['participantId'] == _room.localParticipant.id) {
setState(() => localParticipantMode = _room.localParticipant.mode);
}
});
}
}

Getting Participant Mode​

You can identify the participants role by using mode property from Participant object. It is the participant's current mode, and it is already updated when participantModeChanged fires. Rebuild the participant's tile from that event.

import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class _RoomScreenState extends State<RoomScreen> {
late Room _room;

...

void setRoomEventListener(){
...

_room.on(Events.participantModeChanged, (Map<String, dynamic> data){
setState(() {}); // participant.mode is already updated
});
}

Widget buildParticipantTile(Participant participant) {
return ParticipantTile(
participant: participant,
mode: participant.mode,
);
}
}

class ParticipantTile extends StatelessWidget {
final Participant participant;
final Mode mode;
const ParticipantTile(
{super.key, required this.participant, required this.mode});

@override
Widget build(BuildContext context) {
return Text("${participant.displayName} is in ${mode.name}");
}
}

Changing Participant's Mode​

Let's say you are hosting a livestream and you want one of your viewer to join the livestream with you. In this case you can change the mode of the participant using the changeMode() of the Room object. changeMode() changes the mode of the local participant, and returns a Future that throws a VideoSDKError when the mode cannot be changed.

import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class RoomScreen extends StatefulWidget {
...
}

class _RoomScreenState extends State<RoomScreen> {
late Room _room;

@override
void initState() {
...
}

@override
Widget build(BuildContext context) {
return Column(
children:[
ElevatedButton(
onPressed: () async {
try {
await _room.changeMode(Mode.SIGNALLING_ONLY);
} on VideoSDKError catch (error) {
log("Could not change mode: ${error.code} ${error.name}");
}
},
child: const Text("Change Mode to Viewer"),
),
ElevatedButton(
onPressed: () async {
try {
await _room.changeMode(Mode.SEND_AND_RECV);
} on VideoSDKError catch (error) {
log("Could not change mode: ${error.code} ${error.name}");
}
},
child: const Text("Change Mode to Speaker"),
),
]
);
}
}

API Reference​

The API references for all the methods utilized in this guide are provided below.

Got a Question? Ask us on discord