On / Off Camera - Flutter
Any participant can turn on or off his camera in the room using below methods.
enableCam()
-
By using
enableCam()function ofRoomobject, local participant can publish video to other participants. -
You can call this method when the local participant is not broadcasting any video to others.
-
You can pass customised video track in
enableCam()by using Custom Video Track. -
Video stream of the participant can be accessed from the
streamsproperty ofParticipantobject.
On Android, the SDK does not ask for camera permission. Call VideoSDK.requestPermissions() before enableCam(). Without the permission, the camera stays off: enableCam() throws error 3017, and the same error reaches Events.error.
disableCam()
-
By using
disableCam()function ofRoomobject, local participant can stop publish video to other participants. -
You can call this method when the local participant is broadcasting any video to others.
enableCam() and disableCam() return a Future that throws a VideoSDKError when the SDK refuses the call, for example 3054 when the camera is already on or off, or 3055 while another camera change is still running. await them inside try/catch. On Android, a call made while the room reconnects is reported on Events.error instead of being thrown, so keep an Events.error handler too.
Example
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() {
super.initState();
...
}
@override
Widget build(BuildContext context) {
return Column(
children:[
ElevatedButton(
onPressed: () async {
try {
await _room.enableCam();
} on VideoSDKError catch (error) {
print("enableCam failed: ${error.code} ${error.name}");
}
},
child: const Text("Enable Camera"),
),
ElevatedButton(
onPressed: () async {
try {
await _room.disableCam();
} on VideoSDKError catch (error) {
print("disableCam failed: ${error.code} ${error.name}");
}
},
child: const Text("Disable Camera"),
),
]
);
}
}
To learn, how to render video in the room, follow this detailed guide.
Getting Participant Camera Status
- You can get the local participant's media status by going through the
streamsMap of theParticipantobject. - If
streamscontains a value wherekindisMediaType.VIDEOthen the participant's camera is active else it is disabled. - Stream events are delivered on the
Room, so pass theRoomto the widget.participant.on()delivers the same events for one participant.stream.participantIdis the id of the participant the stream belongs to.
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
class ParticipantTile extends StatefulWidget {
final Room room;
final Participant participant;
const ParticipantTile(
{super.key, required this.room, required this.participant});
@override
State<ParticipantTile> createState() => _ParticipantTileState();
}
class _ParticipantTileState extends State<ParticipantTile> {
RTCStream? videoStream;
@override
void initState() {
super.initState();
// initial video stream for the participant
//Check if camera stream is already present
videoStream = widget.participant.streams.values
.where((stream) => stream.kind == MediaType.VIDEO)
.firstOrNull;
_initStreamListeners();
}
//Change state according to the events received
void _initStreamListeners() {
widget.room.on(Events.streamEnabled, _onStreamEnabled);
widget.room.on(Events.streamDisabled, _onStreamDisabled);
}
bool _isVideoOfThisParticipant(RTCStream stream) =>
stream.participantId == widget.participant.id && stream.kind == MediaType.VIDEO;
void _onStreamEnabled(RTCStream stream) {
if (_isVideoOfThisParticipant(stream)) {
setState(() => videoStream = stream);
}
}
void _onStreamDisabled(RTCStream stream) {
if (_isVideoOfThisParticipant(stream)) {
setState(() => videoStream = null);
}
}
@override
void dispose() {
// The room outlives the tile, so remove the handlers from it.
widget.room.off(Events.streamEnabled, _onStreamEnabled);
widget.room.off(Events.streamDisabled, _onStreamDisabled);
super.dispose();
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Current Camera status of ${widget.participant.displayName} is ${videoStream !=null ? "Active": "Disable"}")
);
}
}
Events associated with enableCam
- Every Participant will receive a callback on
Events.streamEnabledof theRoomobject withRTCStreamobject.stream.participantIdis the id of the participant who turned the camera on.
Events associated with disableCam
- Every Participant will receive a callback on
Events.streamDisabledof theRoomobject withRTCStreamobject.stream.participantIdis the id of the participant who turned the camera off.
Listen for these events with room.on(). You can also listen with participant.on(), which delivers only that participant's streams.
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
class ParticipantTile extends StatefulWidget {
final Room room;
final Participant participant;
...
}
class _ParticipantTileState extends State<ParticipantTile> {
@override
void initState() {
super.initState();
...
_initStreamListeners();
}
//Change state according to the events received
void _initStreamListeners() {
widget.room.on(Events.streamEnabled, _onStreamEnabled);
widget.room.on(Events.streamDisabled, _onStreamDisabled);
}
void _onStreamEnabled(RTCStream stream) {
if (stream.participantId == widget.participant.id && stream.kind == MediaType.VIDEO) {
//Camera Turned On
}
}
void _onStreamDisabled(RTCStream stream) {
if (stream.participantId == widget.participant.id && stream.kind == MediaType.VIDEO) {
//Camera Turned Off
}
}
@override
void dispose() {
widget.room.off(Events.streamEnabled, _onStreamEnabled);
widget.room.off(Events.streamDisabled, _onStreamDisabled);
super.dispose();
}
@override
Widget build(BuildContext context) {
return YourParticipantWidget();
}
}
API Reference
The API references for all the methods and events utilised in this guide are provided below.
Got a Question? Ask us on discord

