Video Effects - React Native
The SDK can apply effects to your camera video before it is sent: auto-framing, low-light correction, a stylized look and a color grade. Import these functions from @videosdk.live/react-native-sdk.
v2.0.0 has no background blur or virtual background. To learn how to use the effects, see the Video Effects guide.
The room object from useRoom() also has setVideoEffects() and getAppliedVideoEffectsConfig(). They work the same as the functions on this page.
setVideoEffects()
setVideoEffects()applies the video effects configuration. You can call it before you join, and the effects start when your camera starts. You can also call it during the call.- Effects run only with
pipeline: "GRAPH". The default,"LEGACY", sends your camera video without effects. - Each call replaces the whole configuration. A section you leave out goes back to its default, so pass every effect you want to keep.
- A change to an effect applies on the next frame. A change of
pipelineapplies on the next frame on iOS. On Android, it applies the next time the camera starts, for example after you turn the camera off and on again or switch cameras.
Parameters
- config:
VideoEffectsConfig
Returns
Promise<AppliedVideoEffectsConfig>: the configuration in force, as described inAppliedVideoEffectsConfig.
Example
import { setVideoEffects } from "@videosdk.live/react-native-sdk";
const turnOnEffects = async () => {
try {
const result = await setVideoEffects({
pipeline: "GRAPH",
lighting: { enabled: true, strength: 0.8 },
filter: { lut: "WARM", strength: 0.6 },
});
if (result.applied !== true) {
console.warn("Video effects are not running:", result.reason);
}
} catch (err) {
console.error("setVideoEffects failed:", err);
}
};
getAppliedVideoEffectsConfig()
getAppliedVideoEffectsConfig()returns the configuration in force. It can differ from the configuration you asked for.
Returns
Promise<AppliedVideoEffectsConfig>
Example
import { getAppliedVideoEffectsConfig } from "@videosdk.live/react-native-sdk";
const checkEffects = async () => {
const current = await getAppliedVideoEffectsConfig();
console.log("Effects running:", current.applied === true, current.reason);
};
publishFramingSubject()
publishFramingSubject()tells auto-framing where the subject is. The SDK does not detect faces or people itself, so call it each time your own detection finds the subject.- Auto-framing must be on:
framing: { enabled: true }withpipeline: "GRAPH". Until you publish a subject, the video is sent without framing. - The values are fractions from
0to1of the video that is sent, not of the raw camera image. - Pass
0forwidthandheightwhen the subject is lost. The picture then eases back to the full frame.
Parameters
- cx:
Number, the horizontal center of the subject. - cy:
Number, the vertical center of the subject. - width:
Number, the width of the subject. - height:
Number, the height of the subject.
Returns
Promise<void>
Example
import { publishFramingSubject } from "@videosdk.live/react-native-sdk";
// box is the face your detector found, in pixels of a frame of frameWidth x frameHeight
const onFaceDetected = async (box, frameWidth, frameHeight) => {
await publishFramingSubject(
(box.x + box.width / 2) / frameWidth,
(box.y + box.height / 2) / frameHeight,
box.width / frameWidth,
box.height / frameHeight,
);
};
addVideoEffectsStatsListener()
addVideoEffectsStatsListener(handler)callshandleronce a second with the measurements of the video effects, as aVideoEffectsStatsobject.- It returns a function. Call that function to remove the listener.
- The measurements are for diagnosis and are off by default. They are sent only when you turn them on before the SDK starts: on Android, run
adb shell settings put global videosdk_effects_stats 1; on iOS, set the environment variableVIDEOSDK_EFFECTS_STATS=1for your app. No JavaScript call turns them on. - Nothing is sent before you join a room.
Parameters
- handler:
(stats: VideoEffectsStats) => void
Returns
() => void, the function that removes the listener.
Example
import { useEffect } from "react";
import { addVideoEffectsStatsListener } from "@videosdk.live/react-native-sdk";
function EffectsStatsLogger() {
useEffect(() => {
const removeListener = addVideoEffectsStatsListener((stats) => {
console.log("Encoded fps:", stats.fpsEncoded, "CPU ms (p95):", stats.cpuMsP95);
});
return removeListener;
}, []);
return null;
}
VideoEffectsConfig
Every property is optional. A property you leave out takes its default value.
| Property | Values | Default | Description |
|---|---|---|---|
pipeline | "LEGACY" | "GRAPH" | "LEGACY" | Effects run only with "GRAPH". |
framing.enabled | Boolean | false | Turns on auto-framing. See publishFramingSubject(). |
framing.maxZoom | 1.0 to 4.0 | 2.0 | How far the crop can zoom in. |
lighting.enabled | Boolean | false | Turns on low-light correction. It brightens the dark parts of the picture. |
lighting.strength | 0.0 to 1.0 | 1.0 | How strong the correction is. |
style.preset | "OFF" | "POSTERIZE" | "VIVID" | "OFF" | A look for the whole picture. |
style.strength | 0.0 to 1.0 | 1.0 | How strong the look is. |
style.levels | An odd number from 3 to 17 | 5 | How many color steps "POSTERIZE" uses. |
filter.lut | "OFF" | "WARM" | "COOL" | "MONO" | "OFF" | A color grade, applied last. |
filter.strength | 0.0 to 1.0 | 1.0 | How strong the color grade is. |
extra | Object | none | More settings, sent as they are. An entry here replaces the property with the same name. |
The effects run in this order: framing, lighting, style, then the color grade. A strength of 0.0 is the same as turning that effect off.
AppliedVideoEffectsConfig
The configuration the SDK holds, with the same properties as VideoEffectsConfig, plus these:
- applied:
truewhen the effects are running. It isfalsewhen the request could not be honored, for example on a device that cannot run the effects. Your video is then sent without effects. - reason: why
appliedisfalse. - pipeline: the pipeline in force,
"LEGACY"or"GRAPH". - tier (
String) and degradeLevel (Number): reported with the configuration in force.
The object can be empty, so check applied === true instead of !applied.
VideoEffectsStats
What addVideoEffectsStatsListener() receives each second. Every field is optional.
| Field | Type |
|---|---|
fpsDelivered | Number |
fpsEncoded | Number |
cpuMsP50 | Number |
cpuMsP95 | Number |
drops | { halSkipped, graphBackpressure, readbackStall, encoderDropped }, each a Number |
geometryChanges | Number |
thermalStatus | Number |
thermalScale | String |
appCpuPct | Number |
encoderImplementation | String |
encoderBackend | "auto" | "software" | "hardware" |
Got a Question? Ask us on discord

