Simulcast
This guide shows how to enable simulcast (multi-quality video streaming) so that senders publish multiple quality variants and receivers can independently choose which variant to receive.
Prerequisites
Before configuring simulcast, you must be connected to a room with video enabled.
For a conceptual overview of how simulcast works, including when to use it and how variants flow through the server, see Simulcast.
Step 1: Configure sent qualities (sender side)
Pass sentQualities in the videoConfig prop of FishjamProvider to control which quality variants the sender publishes.
- React (Web)
- React Native (Mobile)
functionApp () { return ( <FishjamProvider fishjamId ={fishjamId }videoConfig ={{sentQualities : [Variant .VARIANT_LOW ,Variant .VARIANT_MEDIUM ,Variant .VARIANT_HIGH , ], }} > {/* your app */} </FishjamProvider > ); }
functionApp () { return ( <FishjamProvider fishjamId ={fishjamId }videoConfig ={{sentQualities : [Variant .VARIANT_LOW ,Variant .VARIANT_MEDIUM ,Variant .VARIANT_HIGH , ], }} > {/* your app */} </FishjamProvider > ); }
To disable simulcast entirely, pass false:
functionApp () { return ( <FishjamProvider fishjamId ={fishjamId }videoConfig ={{sentQualities : false }} > {/* your app */} </FishjamProvider > ); }
Step 2: Select received quality (receiver side)
Remote tracks expose setReceivedQuality, which tells the server which variant to forward for that track.
- React (Web)
- React Native (Mobile)
functionRemoteVideos () { const {remotePeers } =usePeers (); return ( <div > {remotePeers .map ((peer ) =>peer .tracks .map ((track ) => ( <div key ={track .trackId }> <VideoPlayer stream ={track .stream } /> <QualitySelector track ={track } /> </div > )), )} </div > ); }
functionRemoteVideos () { const {remotePeers } =usePeers (); return ( <ScrollView > {remotePeers .map ((peer ) =>peer .tracks .map ((track ) => ( <View key ={track .trackId }> {track .stream && <RTCView mediaStream ={track .stream } />} <QualitySelector track ={track } /> </View > )), )} </ScrollView > ); }
Step 3: Call setReceivedQuality based on your needs
In practice, you would call setReceivedQuality based on your application's state. For example, you could request high quality for a full-screen participant and low quality for thumbnails in a grid. The manual quality selector below is a simplified example to illustrate the API:
- React (Web)
- React Native (Mobile)
importReact from "react"; import { typeRemoteTrack ,Variant } from "@fishjam-cloud/react-client"; constvariants = [ {label : "Low",value :Variant .VARIANT_LOW }, {label : "Medium",value :Variant .VARIANT_MEDIUM }, {label : "High",value :Variant .VARIANT_HIGH }, ]; functionQualitySelector ({track }: {track :RemoteTrack }) { return ( <div > {variants .map (({label ,value }) => ( <button key ={label }onClick ={() =>track .setReceivedQuality (value )}> {label } </button > ))} </div > ); }
constvariants = [ {label : "Low",value :Variant .VARIANT_LOW }, {label : "Medium",value :Variant .VARIANT_MEDIUM }, {label : "High",value :Variant .VARIANT_HIGH }, ]; functionQualitySelector ({track }: {track :RemoteTrack }) { return ( <View style ={styles .row }> {variants .map (({label ,value }) => ( <Pressable key ={label }style ={styles .pill }onPress ={() =>track .setReceivedQuality (value )} > <Text >{label }</Text > </Pressable > ))} </View > ); } conststyles =StyleSheet .create ({row : {flexDirection : "row",gap : 8,marginTop : 4 },pill : {paddingHorizontal : 12,paddingVertical : 6,borderRadius : 16,backgroundColor : "#e0e0e0", }, });
Type differences: Track vs RemoteTrack
When using usePeers, the track types differ between local and remote peers:
localPeer.tracksare typed asTrack(no quality selection methods)remotePeers[].tracksare typed asRemoteTrack(extendsTrackwithsetReceivedQuality)
This means setReceivedQuality is only available on tracks from remote peers, which is the correct behavior. You don't need to select a quality variant for your own video.
See also
- Simulcast explanation: conceptual overview of how simulcast works
- Connecting to a room: prerequisite for using simulcast