Skip to main content
Version: 2.x.x

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 pipeline applies 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​

Returns​

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 } with pipeline: "GRAPH". Until you publish a subject, the video is sent without framing.
  • The values are fractions from 0 to 1 of the video that is sent, not of the raw camera image.
  • Pass 0 for width and height when 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) calls handler once a second with the measurements of the video effects, as a VideoEffectsStats object.
  • 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 variable VIDEOSDK_EFFECTS_STATS=1 for 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.

PropertyValuesDefaultDescription
pipeline"LEGACY" | "GRAPH""LEGACY"Effects run only with "GRAPH".
framing.enabledBooleanfalseTurns on auto-framing. See publishFramingSubject().
framing.maxZoom1.0 to 4.02.0How far the crop can zoom in.
lighting.enabledBooleanfalseTurns on low-light correction. It brightens the dark parts of the picture.
lighting.strength0.0 to 1.01.0How strong the correction is.
style.preset"OFF" | "POSTERIZE" | "VIVID""OFF"A look for the whole picture.
style.strength0.0 to 1.01.0How strong the look is.
style.levelsAn odd number from 3 to 175How many color steps "POSTERIZE" uses.
filter.lut"OFF" | "WARM" | "COOL" | "MONO""OFF"A color grade, applied last.
filter.strength0.0 to 1.01.0How strong the color grade is.
extraObjectnoneMore 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: true when the effects are running. It is false when 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 applied is false.
  • 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.

FieldType
fpsDeliveredNumber
fpsEncodedNumber
cpuMsP50Number
cpuMsP95Number
drops{ halSkipped, graphBackpressure, readbackStall, encoderDropped }, each a Number
geometryChangesNumber
thermalStatusNumber
thermalScaleString
appCpuPctNumber
encoderImplementationString
encoderBackend"auto" | "software" | "hardware"

Got a Question? Ask us on discord