Loading...
Loading...
Apply, configure, and modulate WebGPU post-processing shaders, cinematic color grading, tone mapping, procedural VFX, and on-device vision (object tracking, instance segmentation, pose, person mattes) in gitframes. Use when adding blur, grain, LUTs, relighting, curves, greenscreen color keying, subject cutouts, or tracking-driven effects in gitframes compositions.
npx skill4agent add gatewai-dev/gitframes gitframes-effectsgitframesgitframesgitframesEffectSignalimport { Layer, Curves, Vignette, Blur } from "gitframes";
const videoLayer = Layer.video("assets/footage.mp4", { fit: "cover" })
.withEffect(new Curves({
master: [{ x: 0, y: 0.05 }, { x: 0.5, y: 0.52 }, { x: 1, y: 0.95 }]
}))
.withEffect(new Vignette({ strength: 0.4, radius: 0.85, softness: 0.6 }))
.withEffect(new Blur({ strength: 8, blurType: "Gaussian" }));import { Composition, FilmGrain, ColorBalance } from "gitframes";
const comp = new Composition({ width: 1920, height: 1080, fps: 30 });
// Shared organic 35mm grain applied across titles, background video, and vector graphics
comp.apply(new FilmGrain({
strength: 0.06,
size: 1.5,
monochrome: true,
animated: true,
speed: 1.0,
}));
comp.apply(new ColorBalance({
shadows: { cyanRed: 4, yellowBlue: -6 },
highlights: { cyanRed: 2, yellowBlue: -4 },
preserveLuminosity: true,
}));comp.sectionLayer.section// Box blur on a tracked object or explicit bounding rectangle
const blurredPlate = comp.section({
source: "assets/interview.mp4",
x: 400,
y: 200,
width: 300,
height: 300,
borderRadius: 150,
effects: [new Blur({ strength: 25, blurType: "Gaussian" })],
});Mediaimport { Media, ApplyLUT, Crop } from "gitframes";
const clip = Media.video("assets/raw_log.mp4")
.apply(new ApplyLUT({ lutUrl: "assets/luts/cinematic.cube", intensity: 1.0 }))
.apply(new Crop({ cropType: "rectangle", topPercentage: 10, heightPercentage: 80 }));
const pngBuffer = await clip.renderFrame({ atMs: 1500 });CurveshueVsHuehueVsSatlumVsSatsatVsSatColorBalancepreserveLuminosityLevelsSelectiveColorGradientMapstops: [{ position: 0, color: "#000" }, { position: 1, color: "#FFF" }]ShadowsHighlightsApplyLUT.cubeModulatehuebrightnesscontrastexposuresaturationsepiaFilmGrainVignetteBlur"Gaussian""Box""Median""Motion""Bilateral""Edge-preserving""Radial""Zoom"UnsharpMaskHighPassHalftoneScreen"Circle""Diamond""Line""Square""Monochrome""CMYK"TileOffset"wrap""clamp""mirror""transparent"MotionBlurTemporalDeflickerRelight3DSSAOPBRGlassDepthOfFieldColorKeyCropgitframes$GITFRAMES_MODELS_DIR~/.cache/gitframes/models| Option | Model | Gives you |
|---|---|---|
| RTMDet-Ins | COCO-80 boxes, tracked over time → |
| RTMDet-Ins (same pass) | Soft per-instance masks → |
| RTMO | 17 COCO keypoints per person → |
| Selfie Segmenter | Fast person alpha → |
variant: "t" | "s" | "m""s"confidenceclasses: ["person", ...]// Whole composition: returns the reactive bundle
const vision = comp.withVision({ enableSegmentation: true, enablePose: true });
// One layer: renders through a node mode
Layer.video("assets/dancer.mp4").withVision({ mode: "matte", enableSegmentation: true });passthroughmaskmattecropskeletonboxestrackingmaskmattecropmatteSource: "instance""selfie"onnxruntime-node| Task | | | |
|---|---|---|---|
| detect / segment (one shared pass) | 150–300 ms | 200–340 ms | 420–700 ms |
| pose | ~50 ms | ~120 ms | ~280 ms |
| matte (Selfie Segmenter) | ~20 ms | ~20 ms | ~20 ms |
"s""m""t"enableDetectionenableSegmentationmatteSource: "instance"confidence0.50.3classesrenderVideomaskmattecrop| Symptom | Fix |
|---|---|
| Part of a fast-moving garment drops out of the cutout | |
| Cutout is the wrong object | Set |
| Faint halo around the cutout on dark backgrounds | Lower |
| Renders offline / in CI | Pre-download with |
| Check the models themselves | |
comp.addSubjectSandwich({
source: "assets/dancer.mp4",
behind: [
Layer.text("HEADLINE BEHIND", {
fontSize: 120,
fill: "#FF5A1F",
fontWeight: 900
})
],
feather: 4,
fit: "cover"
});const vision = comp.withVision({ enableDetection: true });
comp.addSmartFraming({
source: "assets/action.mp4",
target: vision.objects.primary,
targetAspect: 9 / 16,
damping: 0.15,
leadHeadroom: 0.1
});const vision = comp.withVision({ enableSegmentation: true });
comp.addSubjectOutline(vision.segmentation.subject, {
source: "assets/character.mp4",
color: "#FF5A1F",
width: 6,
blur: 12
});const vision = comp.withVision({ classes: ["person"] });
layer.blurRegion(vision.objects.byCategory("person"), { strength: 30 });const report = await comp.analyzeVisionSequence("assets/street.mp4", {
tasks: ["detect", "pose"],
categories: ["person"]
});
report.tracks; // [{ trackId, category, frames: [start, end], centerPath, ... }]EffectSignalimport { Layer, Blur, sineSignal, computed } from "gitframes";
// Oscillating breath blur
const blurSignal = sineSignal({
frequencyHz: 0.5,
min: 0,
max: 20
});
const layer = Layer.image("assets/bg.jpg")
.withEffect(new Blur({
strength: blurSignal,
blurType: "Gaussian"
}));FilmGrain0.04–0.08Vignette0.2–0.45CurvesColorBalanceBlurDepthOfFieldFilmGrainanimated: falseFilmGrain