Video Fallback

The video fallback appears when a participant's video track is unavailable.

ParticipantVideo and VideoRenderer display a user avatar as the default video fallback:

User Avatar Background

Here's an example of how to build your own video fallback. Let's say that you want to show a user avatar for video tracks that are not available.

// render a nice avatar as a fallback
VideoRenderer(
    call = call,
    video = video, // ParticipantState.Media (video or screenSharing)
    videoRendererConfig = videoRenderConfig(
        fallbackContent = { call ->
            val participants by call.state.participants.collectAsState()
            val user = participants.firstOrNull { it.sessionId == video?.sessionId }

            if (user != null) {
                val image by user.image.collectAsState()
                val name by user.name.collectAsState()
                UserAvatar(
                    userImage = image,
                    userName = name
                )
            }
        }
    )
)

If you use ParticipantVideo, which is built with the full participant information on top of the VideoRenderer, it will be much easier:

ParticipantVideo(
    call = call,
    participant = participant,
    videoFallbackContent = {
        val image by participant.image.collectAsState()
        val name by participant.name.collectAsState()
        UserAvatar(
            userImage = image,
            userName = name
        )
    }
)

Customization

If you want to customize the video fallback from higher-level components, such as CallContent, you can achieve it easily by implementing videoRenderer composable parameter like the example below:

CallContent(
    modifier = Modifier.background(color = VideoTheme.colors.appBackground),
    onBackPressed = { finish() },
    videoRenderer = { modifier, call, participant, style ->
        ParticipantVideo(
            modifier = modifier,
            call = call,
            participant = participant,
            style = style,
            videoFallbackContent = {
                val image by participant.image.collectAsState()
                val name by participant.name.collectAsState()
                UserAvatar(
                    userImage = image,
                    userName = name
                )
            }
        )
    },
    ..
)