To demonstrate how to build a UI to render a single video stream, imagine this scenario:
We have a LiveKit Room with three Participants who are constantly streaming a camera feed into the room. In our example, the Participants are not human, but webcams streaming from "Berlin", "New York" and "Tokyo". For unknown reasons, we only want to see the stream from "Tokyo".
We start by creating a new composable and get all the camera tracks with rememberTracks([Track.Source.Camera])
. In the returned array of TrackReferences
we look for the Tokyo stream. Since we know that all webcam participants are named after their cities, we look for the tokyo
participant.
import androidx.compose.runtime.Composableimport androidx.compose.runtime.collectAsStateimport io.livekit.android.compose.state.rememberTracksimport io.livekit.android.room.track.Trackimport io.livekit.android.util.flow@Composablefun CityVideoRenderer() {val trackRefs = rememberTracks(listOf(Track.Source.CAMERA))val tokyoCamTrackRef = trackRefs.find { trackRef ->trackRef.participant::name.flow.collectAsState().value == "tokyo"}// ...}
Now that we have found the correct stream, we can move on to building the UI to display it. We can do this by using the VideoTrackView
composable and passing it the track reference. If the Tokyo track reference is not found, we will display a UI to indicate this instead.
import androidx.compose.foundation.text.BasicTextimport androidx.compose.runtime.Composableimport androidx.compose.runtime.collectAsStateimport io.livekit.android.compose.state.rememberTracksimport io.livekit.android.compose.ui.VideoTrackViewimport io.livekit.android.room.track.Trackimport io.livekit.android.util.flow@Composablefun CityVideoRenderer() {val trackRefs = rememberTracks(listOf(Track.Source.CAMERA))val tokyoCamTrackRef = trackRefs.find { trackRef ->trackRef.participant::name.flow.collectAsState().value == "tokyo"}if (tokyoCamTrackRef != null) {VideoTrackView(trackReference = tokyoCamTrackRef)} else {BasicText(text = "Tokyo is offline")}}
With our UI in place, we need to provide rememberTracks with the proper scope to return the tracks of a LiveKit Room. We do this by nesting everything inside a RoomScope.
import androidx.compose.foundation.text.BasicTextimport androidx.compose.runtime.Composableimport androidx.compose.runtime.collectAsStateimport io.livekit.android.compose.local.RoomScopeimport io.livekit.android.compose.state.rememberTracksimport io.livekit.android.compose.ui.VideoTrackViewimport io.livekit.android.room.track.Trackimport io.livekit.android.util.flow@Composablefun CityVideoRenderer() {val trackRefs = rememberTracks(listOf(Track.Source.CAMERA))val tokyoCamTrackRef = trackRefs.find { trackRef ->trackRef.participant::name.flow.collectAsState().value == "tokyo"}if (tokyoCamTrackRef != null) {VideoTrackView(trackReference = tokyoCamTrackRef)} else {BasicText(text = "Tokyo is offline")}}@Composablefun MyPage() {RoomScope {CityVideoRenderer()}}