Skip to main content
Version: 2.x.x

Optimize Video Tracks - React Native

Set the video track's quality to match your layout and network.

You can pass a custom video track for a participant's media before and during the room.

  1. Custom Video Track
  2. Custom Screen Share Track
note

This page uses the following asynchronous methods. Refer to their API reference for the errors each Promise may reject with, and handle these rejections appropriately based on your use case.

Custom Video Track​

This feature allows you to incorporate custom video encoder configurations, set the video quality profile (bitrateMode), control simulcast behavior (maxLayer), and choose the video codec, then send these modifications to other participants.

Once you set a custom video track created using createCameraVideoTrack(), VideoSDK remembers its settings and automatically reuses them whenever the webcam is turned back on. To change the track configuration, call disableCam(), then pass a new track created using createCameraVideoTrack() to enableCam(). VideoSDK accepts only tracks created using createCameraVideoTrack().

How to Create a Custom Video Track ?​

  • You can create a Custom Video Track using createCameraVideoTrack() method of @videosdk.live/react-native-sdk.
  • This method can be used to create video track by specifying parameters like video resolution, camera facing mode, and the quality controls (bitrateMode and maxLayer).
  • The camera opens when you call this method, so you can preview the track before the room joins. The method does not ask the user for camera access, so get it first with requestPermission() from useMediaDevice(). If you don't pass the track to the room, call stop() on it to close the camera.
  • You can choose video resolution from the below mentioned list of values for the encoder config:
Encoder ConfigResolutionOptimized (kbps)Balanced (kbps)High Quality (kbps)
h90p_w160p160x904090120
h180p_w320p320x18060120180
h360p_w640p640x360300450600
h540p_w960p960x5406009001200
h720p_w1280p1280x720100015002000
h1080p_w1920p1920x1080150022002700
h120p_w160p160x1204090120
h180p_w240p240x18090120180
h240p_w320p320x240100150200
h360p_w480p480x360270360540
h480p_w640p640x480350600900
h720p_w960p960x72090012001600
h1080p_w1440p1440x1080150020002700

Example​

import { createCameraVideoTrack } from "@videosdk.live/react-native-sdk";

let customTrack = await createCameraVideoTrack({
// It will be the id of the camera from which the video should be captured.
cameraId: "camera-id", // OPTIONAL

// This will accept the resolution (height x width) of video you want to capture.
encoderConfig: "h720p_w960p", // "h360p_w640p" | "h480p_w640p" ... // Default : "h720p_w1280p"

// It will specify whether to use front or back camera for the video track.
facingMode: "front", // "back", Default : "front"

// This parameter will be discussed in the next step.
multiStream: true, // false, Default : true

// Optional: This controls the video quality and bandwidth usage.
bitrateMode: "HIGH_QUALITY", // "BANDWIDTH_OPTIMIZED" | "BALANCED" , Default : "BALANCED"

// Optional: This specifies the maximum number of simulcast layers (maxLayer) to publish.
maxLayer: 2, // 3 , Default: 3

// Optional: This specifies the video codec used to encode this track.
codec: "VP8", // "H264" | "VP9" | "AV1" , Default : "VP8"
});
caution

The camera on the device limits how sharp the video can be. For example, if you set the encoder configuration to 1080p but the camera only supports 720p:

  • On Android, the track uses the highest resolution the camera can capture, which in this case is 720p.
  • On iOS, VideoSDK captures at the highest resolution the camera supports and scales it up. The video is sent at 1080p, but it is not sharper than what the camera captured.
What is multiStream?​
  • This parameter specifies whether the stream should send multiple resolution layers or a single resolution layer. It is true by default for a track created with createCameraVideoTrack().
  • If you don't pass a custom track, the camera that VideoSDK opens for you takes multiStream from the config of RoomProvider instead, where it also defaults to true.

Refer to the Simulcast (Adaptive Bitrate) guide for the layers a track publishes and for how participants select the layer they receive.

What is BitrateMode?​

BitrateMode lets you decide whether to prioritize sharp details, save internet data, or find a good balance between the two.

You can choose from three distinct modes:

  • BANDWIDTH_OPTIMIZED: Prioritizes lower bandwidth usage over video quality. Ideal for users with poor or unstable network conditions.
  • BALANCED: The default setting. It balances clear video against bandwidth use, and suits most cases.
  • HIGH_QUALITY: Prioritizes video quality over bandwidth usage. Use this when high-fidelity video is essential and viewers are expected to have strong network connections.
What is maxLayer?​
  • This parameter caps how many layers a track publishes, and accepts 2 or 3. It applies only when multiStream is true, and defaults to 3.

Refer to the Simulcast (Adaptive Bitrate) guide for what each value publishes.

What is codec?​
  • This parameter specifies the video codec used to encode your stream. VideoSDK supports VP8 (default), H264, VP9, and AV1. Pass the codec as one of the strings "VP8", "H264", "VP9", or "AV1".
  • VideoSDK doesn't support multiStream for H264, VP9, and AV1. multiStream defaults to true, so set multiStream: false when you create an H264, VP9, or AV1 track. Otherwise VideoSDK sets it to false for you and reports ERROR_MULTISTREAM_NOT_SUPPORTED (3046) through the onError callback.

Refer to the Video Codecs guide to compare the four codecs, to check which codec a room is actually using, and to handle the cases where a codec is not supported.

How to Setup a Custom Video Track ?​

The custom track can be configured both before and after the room is initialized. Following are the methods that help in doing so:

  1. Setting up a Custom Track during the initialization of a room
  2. Setting up a Custom Track with methods
1. Setting up a Custom Track during the initialization of a room​

If you are enabling the webcam (camEnabled: true) in the config of RoomProvider and wish to use custom tracks from the start of the room, you can pass a custom track in the config as demonstrated below.

caution

Custom Track will not apply on the camEnabled: false configuration.

Example​
import { useEffect, useState } from "react";
import {
Constants,
createCameraVideoTrack,
RoomProvider,
useMediaDevice,
} from "@videosdk.live/react-native-sdk";

function App() {
const { requestPermission } = useMediaDevice();

const getTrack = async () => {
// createCameraVideoTrack() does not ask for access, so ask first.
await requestPermission(Constants.permission.AUDIO_AND_VIDEO);
const track = await createCameraVideoTrack({
encoderConfig: "h720p_w960p",
facingMode: "front",
multiStream: true,
bitrateMode: "HIGH_QUALITY",
maxLayer: 2,
codec: "VP8",
});
setCustomTrack(track);
};

let [customTrack, setCustomTrack] = useState(null);

useEffect(() => {
getTrack();
}, []);

return (
customTrack && (
<RoomProvider
config={{
roomId,
participantName: "John Doe",
micEnabled: true,
//If true, it will use the passed custom track to turn webcam on
camEnabled: true,
//Pass the custom video track here
customCameraTrack: customTrack,
}}
token={token}
>
<RoomView />
</RoomProvider>
)
);
}

2. Setting up a Custom Track with methods​

To switch tracks during the room, you need to pass the CustomStreamTrack to the enableCam() method of useRoom.

tip

Make sure to call the disableCam() method before you pass a new track to enableCam(). While the camera is on, enableCam() rejects with ERROR_ALREADY_IN_REQUESTED_STATE (3054). To replace the track while the camera is on, pass it to changeCam().

Example​
import {
createCameraVideoTrack,
useRoom,
} from "@videosdk.live/react-native-sdk";
import { TouchableOpacity, Text } from "react-native";

const RoomControls = () => {
const { isCamEnabled, enableCam, disableCam } = useRoom();

const handleEnableWebcam = async () => {
if (isCamEnabled) {
try {
await disableCam();
} catch (err) {
console.error("disableCam failed:", err);
}
} else {
try {
let customTrack = await createCameraVideoTrack({
encoderConfig: "h720p_w960p",
facingMode: "front",
multiStream: true,
bitrateMode: "HIGH_QUALITY",
maxLayer: 2,
codec: "VP8",
});

await enableCam(customTrack);
} catch (err) {
console.error("enableCam failed:", err);
}
}
};

return (
<>
<TouchableOpacity
onPress={() => {
handleEnableWebcam();
}}
>
<Text>Enable Webcam</Text>
</TouchableOpacity>
</>
);
};
info

Pass only tracks created with the createCameraVideoTrack() method. RoomProvider, enableCam() and changeCam() do not accept other objects. A stopped or released track is refused with ERROR_INVALID_CUSTOM_VIDEO_TRACK (3029).

Which configuration is suitable for the Device ?​

The chart below shows the encoder resolution and multiStream setting to use for each participant count.

Custom Screen Share Track​

This feature enables the customization of screenshare streams with predefined encoder configuration (resolution + FPS) for specific use cases, which can then be sent to other participants.

How to Create Custom Screen Share Track ?​

  • You can create a Video Track using createScreenShareVideoTrack() method of @videosdk.live/react-native-sdk.
  • This method enables the creation of a video track with different encoding parameters.
  • On Android, the screen capture consent dialog appears when you create the track. On iOS, enableScreenShare() opens the system broadcast picker, and sharing starts when the user taps Start Broadcast.

Example​

import { createScreenShareVideoTrack } from "@videosdk.live/react-native-sdk";

let customShareTrack = await createScreenShareVideoTrack({
// This will accept the height & FPS of video you want to capture.
encoderConfig: "h720p_15fps", // `h360p_30fps` | `h1080p_30fps` // Default : `h720p_15fps`

// It will publish the profile's three bitrate layers instead of a single layer.
multiStream: false, // true, Default : false

// Android only: It will also share the system audio.
withAudio: true, // false, Default : false
});
  • encoderConfig accepts h360p_30fps, h480p_15fps, h480p_30fps, h720p_5fps, h720p_15fps, h720p_30fps, h1080p_15fps and h1080p_30fps.
  • multiStream publishes the profile's three bitrate layers as simulcast layers instead of a single layer. It is false by default.
  • withAudio works on Android 10 and later. The system audio is mixed into your microphone track, so muting the mic mutes both. On iOS, it has no effect.

How to Setup Custom Screen Share Track ?​

In order to switch tracks during the room, you have to pass the CustomStreamTrack to the enableScreenShare() or toggleScreenShare() method of useRoom.

note

Make sure to call the disableScreenShare() method before you create a new track. While you are sharing, enableScreenShare() rejects with ERROR_ALREADY_IN_REQUESTED_STATE (3054), and toggleScreenShare() turns screen share off without using the track.

A stopped or released track is refused with ERROR_INVALID_CUSTOM_VIDEO_TRACK (3029).

Example​
import {
createScreenShareVideoTrack,
useRoom,
} from "@videosdk.live/react-native-sdk";
import { TouchableOpacity, Text } from "react-native";

const RoomControls = () => {
const {
isScreenSharing,
enableScreenShare,
disableScreenShare,
toggleScreenShare,
} = useRoom();

const handleToggleScreenShare = async () => {
if (isScreenSharing) {
try {
await toggleScreenShare();
} catch (err) {
console.error("toggleScreenShare failed:", err);
}
} else {
try {
let customTrack = await createScreenShareVideoTrack({
encoderConfig: "h720p_15fps",
});

await toggleScreenShare(customTrack);
} catch (err) {
console.error("toggleScreenShare failed:", err);
}
}
};

const handleEnableScreenShare = async () => {
if (isScreenSharing) {
try {
await disableScreenShare();
} catch (err) {
console.error("disableScreenShare failed:", err);
}
}

try {
let customTrack = await createScreenShareVideoTrack({
encoderConfig: "h720p_15fps",
});

await enableScreenShare(customTrack);
} catch (err) {
console.error("enableScreenShare failed:", err);
}
};

return (
<>
<TouchableOpacity
onPress={() => {
handleToggleScreenShare();
}}
>
<Text>Toggle ScreenShare</Text>
</TouchableOpacity>

<TouchableOpacity
onPress={() => {
handleEnableScreenShare();
}}
>
<Text>Enable ScreenShare</Text>
</TouchableOpacity>
</>
);
};

API Reference​

The API references for all the methods and events utilised in this guide are provided below.

Got a Question? Ask us on discord