Developer Experience Guidelines - Flutter
This section provides best practices for creating a smooth and efficient development process when working with VideoSDK. From handling errors gracefully to managing resources and event subscriptions, these guidelines help developers build more reliable and maintainable applications. Following these practices can simplify troubleshooting, prevent common pitfalls, and improve overall application performance.
Initiate Key Features After Room Join Event
Start specific features only after the roomJoined event has been triggered.
-
Trigger Key Actions After Joining the Room : Initiating crucial actions after the
roomJoinedevent helps avoid errors. If your application utilizes any of the following features or you want to perform any action as soon as room joins, it's recommended to call them only after the room has successfully started:Chat Subscription: To enable in-room chat functionality, subscribe to the chat topic after theroomJoinedevent is triggered. This ensures that messages are reliably received by participants. A PubSub call made before the room is joined throws aVideoSDKErrorwith code3035.
// Register the handler before you joinroom.on(Events.roomJoined, () async {try {// Subscribe only after the room is joinedawait room.pubSub.subscribe("CHAT",PubSubMessageListener(onMessageReceived: (PubSubMessage message) {log("${message.senderName}: ${message.message}");},),);} on VideoSDKError catch (error) {log("Could not subscribe: ${error.code} ${error.name}");}});try {await room.join();} on VideoSDKError catch (error) {log("Could not join: ${error.code} ${error.name}");}-
Device Management: If you need users to use specific audio or video devices when the room is first joined, you can utilize the custom track. Pass thecameraIdto the createCameraVideoTrack() method for video, and themicrophoneIdto the createMicrophoneAudioTrack() method for audio. Take the ids fromVideoSDK.getCameras()andVideoSDK.getMics(): an id that matches no device makes the method throw3071. Once the track is created, provide it to the createRoom() method. -
Recording and Transcription: To automatically start recording or transcription as soon as the room begins, configure theautoStartConfigin thecreateRoomIdAPI. For detailed information, refer to the documentation here.
Stop Custom Tracks When Necessary
Stopping custom tracks you no longer need frees the camera and microphone. Once you pass a custom track to the room, the SDK manages it for you. Until then, the track keeps the camera or microphone open, so in the cases below you need to call stop() on the track yourself:
-
When Enabling/Disabling the Camera on a Precall Screen:
- If your application includes a precall screen and you want to ensure that the device's camera is not used when the camera is disabled, you must stop the custom video track. Otherwise, the device’s camera will continue to be used even when the camera is off.
- Additionally, remember to create a new track when the user enables the camera again.
- If you don’t need to manage the camera's usage on the device level (i.e., you’re okay with the camera being used whether it’s enabled or disabled), you can skip this step.
createCameraVideoTrack()does not ask for camera permission. CallVideoSDK.requestPermissions()before you create the track.- Here's how you can manage customTrack on a precall screen :
class _JoinScreenState extends State<JoinScreen> with WidgetsBindingObserver {bool isCameraOn = false;CustomStreamTrack? cameraTrack;// Renderer to display the camera video feedRTCVideoRenderer? cameraRenderer;@overrideWidget build(BuildContext context) {// Build the UI components for the join screen//...}Future<void> toggleCamera() async {if (isCameraOn){await cameraTrack?.stop(); // Releases the camerasetState(() {cameraRenderer = null;cameraTrack = null;isCameraOn = false;});}else {try {// Create a new camera track and rendererCustomStreamTrack track = await VideoSDK.createCameraVideoTrack(// passes deviceId of the user's selected devicecameraId: selectedVideoDevice?.deviceId);RTCVideoRenderer render = RTCVideoRenderer();render.srcObject = track.mediaStream; // Set the media stream from the camera tracksetState(() {cameraTrack = track;cameraRenderer = render;isCameraOn = true;});} on VideoSDKError catch (error) {// For example 3017 (no camera permission) or 3023 (camera in use)log("Could not turn on the camera: ${error.code} ${error.name}");}}}}
Use a New Room for Each Session
A Room is single-use. Once the roomLeft event is delivered, the room removes every handler and releases itself. There is nothing to dispose.
- Call
leave()before the screen that owns the room goes away. Leaving is what ends the room for this device. - A room that has left cannot join again:
join()throws aStateError. Create a newRoomwithVideoSDK.createRoom()for the next session.
Listen for Error Events
Listening to error events enables your application to handle unexpected issues efficiently, providing users with clear feedback and potential solutions. Error codes pinpoint specific problems, whether from configuration settings, account restrictions, permission limitations, or device constraints. Here are recommended solutions based on common error categories:
-
Errors associated with Organization: If you encounter errors related to your organization (e.g., account status or participant limits), reach out to support at support@videosdk.live or reach out to us on Discord for assistance.
-
Errors associated with Token: For errors related to authentication tokens, ensure the token is valid and hasn’t expired, then try the request again.
-
Errors associated with Room and Participant: Check that room ID and participantId are correctly passed and valid. Also, ensure each participant has a unique participantId to avoid duplicate entries.
-
Errors associated with Add-on Service: If you encounter errors with add-on services (such as recording or streaming), try restarting the service after receiving a failure event. For example, if a
START_RECORDING_FAILEDerror occurs, attempt to call thestartRecording()method again. If you're using webhooks, you can also retry on recording-failed hook. -
Errors associated with Media: Inform the user about media access issues, such as microphone or camera permissions. Design the UI to clearly indicate what is preventing the mic or camera from enabling, helping the user understand the problem.
-
Errors associated with Track: Ensure that the track you’ve created and passed to enable the mic or camera methods meets the required specifications.
-
Errors associated with Actions: If you need to perform actions as soon as a room joins, only initiate them after receiving the roomJoined event, otherwise it will not work well.
- Here's how to listen for the error event, and catch the error an action throws:
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
class RoomScreen extends StatefulWidget {
//Existing configuration
}
class _RoomScreenState extends State<RoomScreen> {
late Room room;
@override
void initState() {
super.initState();
//Existing configuration
setupRoomEventListener();
}
@override
Widget build(BuildContext context) {
return YourRoomWidget();
}
void setupRoomEventListener() {
room.on(Events.error, (VideoSDKError error) {
log("VIDEOSDK ERROR :: ${error.code} :: ${error.name} :: ${error.message}");
});
}
Future<void> joinRoom() async {
try {
await room.join();
} on VideoSDKError catch (error) {
log("VIDEOSDK ERROR :: ${error.code} :: ${error.name} :: ${error.message}");
}
}
}
- Actions such as
join()return aFuturethat throws aVideoSDKErrorwhen they fail. Await them insidetry/catch: a call you do not await turns a failure into an unhandled error. An error can reach your app as a thrownVideoSDKError, onEvents.error, or both. See Handling errors. - Track factories are not tied to a room, so their failures never reach
Events.error. Catch theVideoSDKErrorthatcreateCameraVideoTrack()andcreateMicrophoneAudioTrack()throw where you call them.
Got a Question? Ask us on discord

