val isCameraEnabled by call.camera.isEnabled.collectAsState()
val isMicrophoneEnabled by call.microphone.isEnabled.collectAsState()
CallLobby(
call = call,
modifier = Modifier.fillMaxWidth(),
isCameraEnabled = isCameraEnabled,
isMicrophoneEnabled = isMicrophoneEnabled,
)Call Lobby
The call lobby displays a local video preview before joining a call. It allows you to control the camera, microphone, and permissions before joining. The call lobby consists of these components:
- videoPreviewModifier: Modifier applied to the box that wraps the local video preview. Override to control size, shape, padding, or background.
- onRenderedContent: A video renderer, which renders a local video track before joining a call.
- onDisabledContent: Content is shown that a local camera is disabled. It displays user avatar by default.
- participantLabelContent: Slot for the participant label overlaid on the preview. Pass
{}to hide it or override to supply custom content and positioning. - lobbyControlsContent: Content is shown that allows users to trigger different actions to control a preview call.
- onCallAction: Handler when the user triggers a Call Control Action.
Here's how to implement a basic call lobby:
After running your project, you'll see the result below:

Control Actions
Similar to CallContent, and CallLobby supports these main action handlers with the onCallAction lambda:
CallLobby(
call = call,
modifier = Modifier.fillMaxWidth(),
isCameraEnabled = isCameraEnabled,
isMicrophoneEnabled = isMicrophoneEnabled,
onCallAction = { action ->
when (action) {
is ToggleCamera -> call.camera.setEnabled(action.isEnabled)
is ToggleMicrophone -> call.microphone.setEnabled(action.isEnabled)
else -> Unit
}
}
)You can customize the control actions by implementing your own composable for the lobbyControlsContent like the code below:
CallLobby(
call = call,
modifier = Modifier.fillMaxWidth(),
isCameraEnabled = isCameraEnabled,
isMicrophoneEnabled = isMicrophoneEnabled,
lobbyControlsContent = {
ControlActions(
call = call,
actions = listOf(
{
ToggleCameraAction(
isCameraEnabled = isCameraEnabled,
onCallAction = { }
)
},
{
ToggleMicrophoneAction(
isMicrophoneEnabled = isMicrophoneEnabled,
onCallAction = { }
)
}
)
)
},
..
)Then you'll see the result below:

Permission Requests
The call lobby needs to get permission to access the camera and microphone. CallLobby implements the permission request by default, so you don't need to do anything to request permission from your side. If you implement the CallLobby composable, it will ask you to grant camera and microphone permission like the image below:

You can also customize what permission you want to ask by passing a list of permission to the permission parameter like the example below:
CallLobby(
permissions: VideoPermissionsState = rememberCallPermissionsState(
call = call,
permissions = listOf(
android.Manifest.permission.CAMERA,
android.Manifest.permission.RECORD_AUDIO,
..
),
),
..
)If you don't want to let CallLobby request permissions and want to handle them manually from your side, you can just pass an empty list like the code below:
CallLobby(
permissions: VideoPermissionsState = rememberCallPermissionsState(
call = call,
permissions = listOf()
),
..
)Preview For Disabled Camera
The CallLobby component displays a user avatar when the camera lacks permission or is disabled.

You can customize the preview component by implementing your own composable to the onDisabledContent composable parameter:
CallLobby(
call = call,
modifier = Modifier.fillMaxWidth(),
onDisabledContent = {
Box(modifier = Modifier.fillMaxSize()) {
Text(
modifier = Modifier.align(Alignment.Center),
text = "Camera is disabled",
color = VideoTheme.colors.textHighEmphasis
)
}
},
..
)After building the project, you'll see the result below:

Preview Box Size and Shape
By default, the preview box uses a responsive height (180/280/200dp depending on screen size and orientation), full width, and a 12dp rounded corner clip. Override the box modifier via videoPreviewModifier to control size, shape, padding, or background independently of the surrounding layout:
CallLobby(
call = call,
videoPreviewModifier = Modifier
.height(360.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(24.dp)),
)The modifier parameter is applied to the outer Column that wraps the preview, spacer, and control actions; videoPreviewModifier is applied to the inner box that wraps the video preview only. Use videoPreviewModifier when you want to size or shape the preview without affecting the controls below it.
Participant Label
The CallLobby overlays a participant label (user name and microphone state) on the bottom-start of the preview by default. Pass participantLabelContent = {} to hide it, or override the slot to provide custom content and positioning:
CallLobby(
call = call,
participantLabelContent = {
Text(
modifier = Modifier
.align(Alignment.TopEnd)
.padding(VideoTheme.dimens.spacingM),
text = "You",
color = VideoTheme.colors.basePrimary,
)
},
)participantLabelContent is a BoxScope-receiver lambda, so use Modifier.align(...) inside to position the content within the preview box.
Customization
The CallLobby component has more options when it comes to customization. It exposes the following parameters that let you change its UI:
@Composable
public fun CallLobby(
modifier: Modifier = Modifier,
call: Call,
user: User = StreamVideo.instance().user,
isCameraEnabled: Boolean,
isMicrophoneEnabled: Boolean,
video: ParticipantState.Video,
permissions: VideoPermissionsState,
onRenderedContent: @Composable (video: ParticipantState.Video) -> Unit,
onDisabledContent: @Composable () -> Unit,
videoPreviewModifier: Modifier,
participantLabelContent: @Composable BoxScope.() -> Unit,
onCallAction: (CallAction) -> Unit,
lobbyControlsContent: @Composable (modifier: Modifier, call: Call) -> Unit
)modifierThe standard Jetpack Compose modifier applied to the outerColumnwrapping the preview, spacer, and lobby controls.callThe call includes states and will be rendered with participants.userA user to display their name and avatar image on the preview.videoA participant video to render on the preview renderer.permissionsAndroid permissions that should be required to render a video call properly.onRenderedContentA video renderer, which renders a local video track before joining a call.onDisabledContentContent is shown that a local camera is disabled. It displays user avatar by default.videoPreviewModifierModifier applied to the box that wraps the local video preview. Override to control the preview's size, shape, padding, or background independently of the surrounding layout.participantLabelContentSlot for the participant label overlaid on the preview. Pass{}to hide it or override to supply custom content and positioning.onCallActionHandler when the user triggers a Call Control Action.lobbyControlsContentContent is shown that allows users to trigger different actions to control a preview call.