Effects
Effects were introduced in Replay format v3.3.0. Every visual layer (image, text, shape, group, video, visual) carries an ordered effect stack at props.effects. Audio layers do not support effects.
The array order is the apply order: the first effect in the array is applied first, and each subsequent effect is applied on top of the previous result.
A replay created before v3.3.0 has no effects property. The migration from v3.2.0 to v3.3.0 adds an empty effect stack ([]) to every visual layer (including fallback layers and layers added by actions), so no effect is applied until one is added. Downgrading from v3.3.0 to v3.2.0 only lowers the format version — the effects property is left in place for forward compatibility.
Design: a typed, format-owned catalog
An effect shares the same envelope as an animation — uuid, id, renderer — but, unlike the open animation payload, the effect catalog is closed and fully typed by the format. IReplayEffect is a discriminated union of one named interface per effect (IReplayLutEffect, IReplayGaussianBlurEffect, …); the id field is the discriminant, and each variant declares its own typed params and its own mask capability.
What the format guarantees:
- Envelope — every effect has a
uuid(instance identity), anid(the effect kind — the discriminant a renderer dispatches on), and arendererreference. Effect stacks are ordered arrays on visual layers. - Typed params — each effect kind declares exactly which parameters it accepts, their value types, ranges, enum options and defaults. Params are flat and independent — no parameter's presence depends on another's value. Narrowing an
IReplayEffectby itsidyields the exactparamsshape for that kind. Some effects have noparamsat all. - A first-class mask vocabulary — masking is defined by the format, not by a renderer. Each effect declares its mask capability: an optional compositing mask, no mask, or a segment mask that is the operation.
- Unknown effects — a reader that does not recognize an
id(e.g. a newer effect kind) skips that effect rather than failing the replay.
The renderer defaults to the built-in system effects package (system.effects, version 1.0.0), but any effect can name a different implementation.
IReplayLayerEffects
- Web
- Android
- IOS
import type { IReplayLayerEffects } from '@picsart/web-replay-sdk';
Not supported yet.
Not supported yet.
This interface describes the effects property mixed into every visual layer's props.
| Property | Type | Required | Description |
|---|---|---|---|
| effects | IReplayLayerProperty<IReplayEffect[]> | yes | The layer's ordered effect stack, carried as a wrapped layer property (so it can be locked and hold meta, and be step-changed across keyframes). Array order is apply order. Defaults to [] |
IReplayEffect
- Web
- Android
- IOS
import type { IReplayEffect } from '@picsart/web-replay-sdk';
Not supported yet.
Not supported yet.
IReplayEffect is the discriminated union of every effect kind. Every variant extends the shared envelope below and adds its own id, params and mask. Narrow by id to get a variant's exact shape.
Envelope
| Property | Type | Required | Description |
|---|---|---|---|
| uuid | UUIDString | yes | The instance identity — unique per effect in a stack. Two effects of the same kind have different uuids |
| id | string | yes | The effect kind and the union discriminant (e.g. gaussian_blur). One of the catalog ids. Not unique within a stack |
| renderer | IRenderer | yes | The renderer package that owns this effect and the version that reads its params. Defaults to { packageId: "system.effects", version: "1.0.0" } |
| params | object | per kind | The typed parameters for this effect kind. Absent for effects that take none (e.g. remove_segment). See each kind below |
| mask | IReplayEffectMask | IReplaySegmentMask | per kind | Restricts where the effect applies. Optional, absent, or required depending on the effect's mask capability |
uuid vs iduuid answers which one (instance identity — used to reference, reorder or update a specific effect). id answers what kind. renderer.packageId picks the engine, id picks the effect within it.
Effect catalog
The format defines the following effect kinds. Mask shows the effect's mask capability: optional = an IReplayEffectMask may be attached, none = the effect takes no mask, required = a IReplaySegmentMask must be attached (the mask defines the operation). Defaults are the values createReplayEffect fills in, and the full scheme (defaults, ranges, options, usable masks) is served at runtime by getEffectCatalog.
| id | params | Mask |
|---|---|---|
adjust | fade, brightness, contrast, saturation, hue | optional |
black_white | fade | optional |
face_hide | fade, padding, smoothing, texture | none |
film_grain | fade, intensity, size, seedMode, seed | optional |
gaussian_blur | fade, blur | optional |
glitch | fade, intensity, seedMode, seed | optional |
lut | fade, preset, resource | optional |
negative | fade | optional |
page_curl | fade, progress | none |
pixelate | fade, pixelSize | optional |
remove_segment | (none) | required |
vhs | fade, chromaShift, scanlines, noise, rolling, seedMode, seed | optional |
vintage_film | fade, grain, vignette, seedMode, seed | optional |
Numeric ranges below are the engine's validation bounds. fade (present on every effect that has params) is the dry/wet mix in the range 0–100: 0 = effect fully applied, 100 = original untouched. Other numeric params have their own ranges (shown per effect); many strength params are 0–1.
adjust
Tone adjustments. params:
| Param | Type | Min | Max | Default | Description |
|---|---|---|---|---|---|
| fade | number | 0 | 100 | 0 | Dry/wet mix — 0 = full effect, 100 = original |
| brightness | number | -1 | 1 | 0 | Bipolar; 0 = no change |
| contrast | number | -1 | 1 | 0 | Bipolar; 0 = no change |
| saturation | number | -1 | 1 | 0 | Bipolar; 0 = no change |
| hue | number | -1 | 1 | 0 | Hue rotation; maps to -180°–180° |
black_white
Desaturates to grayscale. params:
| Param | Type | Min | Max | Default | Description |
|---|---|---|---|---|---|
| fade | number | 0 | 100 | 0 | Dry/wet mix. Inverted for this effect: 0 = full grayscale, 100 = original color |
face_hide
Covers detected faces with a texture. Mask capability: none. params:
| Param | Type | Min | Max | Default | Description |
|---|---|---|---|---|---|
| fade | number | 0 | 100 | 0 | Dry/wet mix — 0 = full effect, 100 = original |
| padding | number | -90 | 100 | 0 | Padding around each detected face (may be negative to inset) |
| smoothing | number | 0 | 1 | 0.3 | Edge feathering of the cover |
| texture | IReplayEffectResource | — | — | — (required) | The image drawn over each face (.png/.webp/.jpg) |
film_grain
Adds film grain. Seeded. params:
| Param | Type | Min | Max | Default | Description |
|---|---|---|---|---|---|
| fade | number | 0 | 100 | 0 | Dry/wet mix — 0 = full effect, 100 = original |
| intensity | number | 0 | 1 | 0.5 | Grain strength |
| size | number | 1 | 10 | 1 | Grain size |
| seedMode | 'rolling' | 'fixed' | — | — | rolling | Grain randomness control — see Seeded effects |
| seed | number | 0 | 100 | 0 | Frozen randomness value; used when seedMode is fixed |
gaussian_blur
Gaussian blur. params:
| Param | Type | Min | Max | Default | Description |
|---|---|---|---|---|---|
| fade | number | 0 | 100 | 0 | Dry/wet mix — 0 = full effect, 100 = original |
| blur | number | 0 | 100 | 20 | Blur radius in pixels |
glitch
Digital glitch. Seeded. params:
| Param | Type | Min | Max | Default | Description |
|---|---|---|---|---|---|
| fade | number | 0 | 100 | 0 | Dry/wet mix — 0 = full effect, 100 = original |
| intensity | number | 0 | 1 | 0.5 | Glitch strength |
| seedMode | 'rolling' | 'fixed' | — | — | rolling | Glitch randomness control — see Seeded effects |
| seed | number | 0 | 100 | 0 | Frozen randomness value; used when seedMode is fixed |
lut
Applies a color LUT — a built-in preset, or an external .cube resource that overrides the preset when present. params:
| Param | Type | Min | Max | Default | Description |
|---|---|---|---|---|---|
| fade | number | 0 | 100 | 0 | Dry/wet mix — 0 = full effect, 100 = original |
| preset | IReplayLutPreset | — | — | golden_hour | A built-in LUT preset |
| resource | IReplayEffectResource | — | — | — (optional) | An external .cube LUT; when present it overrides preset. Not yet implemented by the system.effects engine — see note below |
Custom LUTs via resource are part of the format type but the system.effects engine does not render them yet — only the built-in preset LUTs are currently supported. Until custom LUTs ship, use preset.
LUT presets
golden_hour, airy_pastel, arctic_blue, autumn_glow, bleach_bypass, clean_bright, cold_neon, cool_blue, creamy_portrait, cross_process, crushed_contrast, dark_academia, emerald_forest, faded_film, instant_fade, kodachrome_vibe, moody_noir, neon_cyberpunk, silver_bw, symmetric_pastel, teal_orange, tropical_saturated, tungsten_night, vhs_retro, warm_sunset, lut_1972.
negative
Inverts colors. params:
| Param | Type | Min | Max | Default | Description |
|---|---|---|---|---|---|
| fade | number | 0 | 100 | 0 | Dry/wet mix — 0 = full effect, 100 = original |
page_curl
Page-curl transition. Mask capability: none. params:
| Param | Type | Min | Max | Default | Description |
|---|---|---|---|---|---|
| fade | number | 0 | 100 | 0 | Dry/wet mix — 0 = full effect, 100 = original |
| progress | number | 0 | 1 | 0 | Curl progress |
pixelate
Pixelation. params:
| Param | Type | Min | Max | Default | Description |
|---|---|---|---|---|---|
| fade | number | 0 | 100 | 0 | Dry/wet mix — 0 = full effect, 100 = original |
| pixelSize | number | 1 | 100 | 20 | Pixel block size |
remove_segment
Removes the masked region. The segment mask is the operation, so mask is required and there are no params.
{
"uuid": "e5f6a7b8-0000-4000-8000-000000000003",
"id": "remove_segment",
"renderer": { "packageId": "system.effects", "version": "1.0.0" },
"mask": { "provider": "scene", "segments": ["person"], "invert": false }
}
vhs
VHS look. Seeded. params:
| Param | Type | Min | Max | Default | Description |
|---|---|---|---|---|---|
| fade | number | 0 | 100 | 0 | Dry/wet mix — 0 = full effect, 100 = original |
| chromaShift | number | 0 | 1 | 0.5 | Chroma / color-channel shift |
| scanlines | number | 0 | 1 | 0.5 | Scanline strength |
| noise | number | 0 | 1 | 0.3 | Noise amount |
| rolling | number | 0 | 1 | 0.3 | Rolling-distortion amount |
| seedMode | 'rolling' | 'fixed' | — | — | rolling | Noise randomness control — see Seeded effects |
| seed | number | 0 | 100 | 0 | Frozen randomness value; used when seedMode is fixed |
vintage_film
Vintage film look. Seeded. params:
| Param | Type | Min | Max | Default | Description |
|---|---|---|---|---|---|
| fade | number | 0 | 100 | 0 | Dry/wet mix — 0 = full effect, 100 = original |
| grain | number | 0 | 1 | 0.5 | Grain amount |
| vignette | number | 0 | 1 | 0.5 | Vignette strength |
| seedMode | 'rolling' | 'fixed' | — | — | rolling | Grain/noise randomness control — see Seeded effects |
| seed | number | 0 | 100 | 0 | Frozen randomness value; used when seedMode is fixed |
Seeded effects
Noise-based effects (film_grain, glitch, vhs, vintage_film) carry a seed control in their params — two plain, independent parameters:
| Param | Default | Behavior |
|---|---|---|
seedMode: 'rolling' | ✓ (default) | Randomness is re-rolled every frame; seed is ignored |
seedMode: 'fixed' | Randomness is frozen at seed (0–100), so the effect is deterministic across frames and renders |
{ "seedMode": "rolling", "seed": 0 }
{ "seedMode": "fixed", "seed": 42 }
Masks
A mask restricts where an effect applies, selecting one or more segments produced by a segmentation provider. segments must be non-empty, and invert flips the selection (apply to everything except the segments).
| provider | Segments |
|---|---|
portrait | background, hair, body_skin, face_skin, clothes, accessories |
scene | background, airplane, bicycle, bird, boat, bottle, bus, car, cat, chair, cow, table, dog, horse, motorcycle, person, plant, sheep, sofa, train, tv |
There are two mask shapes, distinguished by whether the mask composites around an effect or defines the operation itself.
IReplayEffectMask
A compositing mask, used by effects whose mask is optional (adjust, black_white, film_grain, gaussian_blur, glitch, lut, negative, pixelate, vhs, vintage_film). Because the effect runs and then composites against the mask, ordering matters — hence mode.
| Property | Type | Required | Description |
|---|---|---|---|
| provider | 'portrait' | 'scene' | yes | The segmentation source |
| segments | string[] | yes | Non-empty list of segments (from the provider's set above) |
| invert | boolean | yes | Apply to everything except the selected segments |
| mode | IReplayMaskMode | yes | Whether the mask is applied before or after the effect |
IReplayMaskMode
| Value | Description |
|---|---|
BeforeEffect | The mask is applied to the input, then the effect runs on the masked region |
AfterEffect | The effect runs on the full frame, then the mask composites the result back |
{
"uuid": "b1e2c3d4-0000-4000-8000-000000000001",
"id": "gaussian_blur",
"renderer": { "packageId": "system.effects", "version": "1.0.0" },
"params": { "fade": 0, "blur": 20 },
"mask": { "provider": "portrait", "segments": ["background"], "invert": false, "mode": "AfterEffect" }
}
IReplaySegmentMask
An operation mask, used only by remove_segment, where the mask is the operation. It has no mode (there is no effect-vs-mask ordering to choose).
| Property | Type | Required | Description |
|---|---|---|---|
| provider | 'portrait' | 'scene' | yes | The segmentation source |
| segments | string[] | yes | Non-empty list of segments |
| invert | boolean | yes | Operate on everything except the selected segments |
Creating effects
The web SDK provides a typed builder — createReplayEffect — that stamps the uuid, defaults the renderer to system.effects, and fills each effect kind's default params so you pass only what you set. params is typed by id: an unknown param, a wrong value type, or a missing no-default param (like face_hide's texture) is a compile error.
import { createReplayEffect } from '@picsart/web-replay-sdk/context';
// params fully defaulted → pass nothing
const negative = createReplayEffect({ id: 'negative' });
// override only what you need
const blur = createReplayEffect({ id: 'gaussian_blur', params: { blur: 40 } });
// freeze a seeded effect's randomness
const grain = createReplayEffect({
id: 'film_grain',
params: { intensity: 0.7, seedMode: 'fixed', seed: 42 },
});
const teal = createReplayEffect({ id: 'lut', params: { preset: 'teal_orange' } });
// remove_segment: no params, mask required
const cutout = createReplayEffect({
id: 'remove_segment',
mask: { provider: 'scene', segments: ['person'], invert: false },
});
Effects are passed to layer creators via props.effects (apply order = array order):
const layer = createReplayImageLayer({
name: 'photo',
mediaType: 'IMAGE',
props: { image, effects: [blur, negative] },
});
To drive an effects UI (sliders from ranges, dropdowns from options, mask pickers from providers), the SDK serves the whole catalog as plain data via getEffectCatalog.
Evolution and compatibility
- The effect catalog, params and mask vocabulary are part of the format. Adding a new effect kind, a new parameter, or a new mask segment is a format change and travels with
meta.replayVersionand the migration pipeline. - Readers narrow an effect by its
id. An unrecognizedid(from a newer format) is skipped, not fatal. renderer.versionidentifies the implementation that draws an effect; it does not redefine the params — those are format-owned.