On / Off Camera - Flutter
This feature enables hosts to turn their cameras on or off to share their video stream with other hosts and audience members during the livestream. Only hosts (in SEND_AND_RECV mode) can broadcast their camera feed, while audience members (in RECV_ONLY mode) can view it in real time.
enableCam()
-
By using the
enableCam()function of theRoomclass, the host can publish their video to other hosts and audience members. -
You can also pass a customised video track in
enableCam()by using Custom Video Track. -
Video stream of the participant can be accessed from the
streamsproperty ofParticipantobject. -
room.isCamEnabledtells you whether your own camera is on.
disableCam()
- By using the
disableCam()function of theRoomClass, the host can stop publishing their video to other hosts and audience members.
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 livestream reconnects is reported on Events.error instead of being thrown, so keep an Events.error handler too.
Events associated with enableCam
- Every Participant will receive a callback on
Events.streamEnabledof theRoomobject withRTCStreamobject.stream.participantIdis the id of the host 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 host who turned the camera off.
streamEnabled and streamDisabled also reach handlers added with participant.on() on the participant who owns the stream.
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();
}
Future<void> enableCam() async {
try {
await widget.room.enableCam();
} on VideoSDKError catch (error) {
print("enableCam failed: ${error.code} ${error.name}");
}
}
Future<void> disableCam() async {
try {
await widget.room.disableCam();
} on VideoSDKError catch (error) {
print("disableCam failed: ${error.code} ${error.name}");
}
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Text("Camera of ${widget.participant.displayName} is ${videoStream != null ? "on" : "off"}"),
// The buttons act on your own camera, so show them on your own tile.
if (widget.participant.isLocal) ...[
ElevatedButton(
onPressed: enableCam,
child: const Text("Enable Camera"),
),
ElevatedButton(
onPressed: disableCam,
child: const Text("Disable Camera"),
),
],
],
);
}
//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();
}
}
Video Permissions
- If permissions are not granted, use the
requestPermissions()method of theVideoSDKclass to prompt users to grant access to their devices. - On Android, the SDK does not ask for camera permission. Call
requestPermissions()beforeenableCam(). Without the permission, the camera stays off:enableCam()throws error3017, and the same error reachesEvents.error. - To enable requesting of camera permission on iOS devices, add the following to your
Info.plist, located at<project root>/ios/Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>$(PRODUCT_NAME) Camera Usage!</string>
In case permissions are blocked by the user, the permission request dialogue cannot be re-rendered programmatically. In such cases, consider providing guidance to users on manually adjusting their permissions.
Future<void> requestMediaPermissions() async {
try {
//For requesting just video permission.
Map<String, bool> reqVideoPermissions =
await VideoSDK.requestPermissions(Permissions.VIDEO);
if (reqVideoPermissions['video'] != true) {
// The user did not allow the camera.
}
} catch (ex) {
print("Error in requestPermission ");
}
}
- Requesting permissions if not already granted:

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

