Make footage look like a CRT, a worn VHS tape, a thermal camera or a 1-bit screen.
Draws <PopArt> <Blobs> <HalftonePoster> <Fragments> <Reticle>
What it does
VJ makes a picture look like it came from a screen, a tape or a sensor. Brightness stands in for heat and depth, so these are looks, not measurements. It also draws tracking marks on whatever moves, cuts a person into a pop-art poster and builds a camera fly-through of clips.
Screens and tapes
A CRT with curved glass that switches off, a worn VHS tape, a 1-bit screen, and a pixel magnifier that resolves into red, green and blue stripes.
Thermal and depth
Brightness becomes a thermal-camera palette or a depth-map look.
Flash looks
Acid heat, night vision, screen glow and grainy black and white, to cut on the beat.
PopArt
Footage of a person cuts to an anime poster of them: blue tones, ink lines and rim light over a halftone. It needs a matte of the person, which a bundled tool makes once per clip.
Tracking
A tracker runs once and saves where things moved. Blobs draws boxes and links on every frame. Reticle marks one point.
Fragments
Clips show only through windows: boxes round the people and animals in them, tiles of sky, round holes. Each clip sits on its own plane at its own depth, and a camera flies through so near pieces slide past faster than far ones. Boxes carry name tags with a flickering confidence figure. Whoever edits the video names the boxes; no detection model runs.
Demos
Studio panels
Ready-made scenes for the Hexed, Paper, VJ and caption panels in Studio. Edit a value and the preview redraws.
Compositions HexedLook PaperMatchCut PaperCutOut PaperScrapline PaperFoldOut TypeCaptions VjLook
VJ looks and tracking
Blob tracking over a 1-bit picture and over a thermal camera, a CRT switching off and a VHS tape, on archive film.
Compositions Blobs Thermal Crt Vhs PopArt
Reference
Exports, props and examples, for wiring it into a project.
Ships with
What it exports
Components
Drawn as JSX inside a composition.
<PopArt />
The pop-art cut-in on any clip of a person.
Place it in a <Sequence> to start the clip later.
| Prop | What it does |
|---|---|
| src | the clip of the person |
| matte | its person matte (white = person), from tools/matte.mjs |
| track? | where the person is on every frame, from tools/matte.mjs --track; without it the rays start mid-frame |
| rate? | the clip's playback rate |
| cuts? | when to cut to the poster; without cuts the poster is on throughout |
| flash? | frames that flash to a single yellow card |
| title? | the three title rows; null for none |
| chest? | how far below the person's centre the rays and shapes start, px (1920x1080 space) |
| id? | a prefix for the layer ids, unique per <PopArt> on screen |
| seed? | string |
<Blobs />
Boxes, labels and links on a tracked clip's blobs.
Put it over the clip, the same size.
| Prop | What it does |
|---|---|
| track | BlobTrack |
| from? | The composition frame the tracked clip starts on. Default 0. |
| width? | The overlay's size: the clip's picture, filling it. Default the composition's. |
| height? | number |
| box? | How each blob is marked: a full box, the box's corners, a cross on its centre, or nothing. Default frame. |
| label? | The text beside each box: its id, its centre as 0..1 coordinates, both, or nothing. Default both. |
| links? | BlobLinks |
| reach? | For links="all": how far apart two blobs may be and still be linked, as a fraction of the diagonal. |
| invert? | 0..1: the share of blobs (picked by id) filled solid in difference blending, inverting the picture under them. |
| min? | Blobs smaller than this fraction of the frame are left out. |
| max? | The biggest this many are kept. |
| color? | string |
| blend? | How the boxes, lines and labels sit on the picture. difference keeps them readable on white and black alike (a 1-bit picture); normal keeps color as it is. Default normal. |
| stroke? | Line width, px. |
| fontSize? | number |
| id? | Prefix of the layer ids. |
<HalftonePoster />
A clip printed as a halftone poster: panels of ink-on-paper dots, the person over flat ground, an off-register shadow and a title.
| Prop | What it does |
|---|---|
| src | string |
| matte? | The person's matte (white = person), timed as src. Without it the whole picture is printed. |
| width? | number |
| height? | number |
| rate? | number |
| trimBefore? | number |
| panels? | Side by side; default one panel, blue on yellow. |
| changes? | Panel sets that cut in on composition frames, as a poster series flicking over. |
| size? | number |
| angle? | number |
| punch? | number |
| bias? | number |
| shape? | 'circle' | 'line' | 'square' |
| offset? | With a matte: the person's silhouette in each panel's shadow colour, this many px off. Without a matte: a second print of the picture in shadow ink, multiplied over, this far off. |
| backdrop? | With a matte: the ground flat, or the clip behind the person faintly in the panel's ink. Default flat. |
| title? | PosterTitle |
| steps? | Drawings a second; the picture holds between them. 0 for every frame. Default 12. |
| id? | string |
<Fragments />
Clips seen through windows on planes at different depths, with a camera moving through them.
| Prop | What it does |
|---|---|
| pieces | Piece[] |
| camera? | Keys the camera eases between (x, y in px, z in depth units), or a function of the frame. Default: a slow push from z 0 to 0.5 over the composition. |
| colors? | Colours of the tags by name; other names get one from a set, the same each time. |
| fontSize? | Tag text size, clip px. Default 22. |
| fog? | 0..1: how much a piece dims per unit of depth past 1. Default 0.25. |
| inspect? | Show piece inspect flat, whole and filling the frame, at its clip's own frame (its from ignored), with every box's id, every spot's name and a grid in clip pixels: render stills of it to name the ids and place spots. |
| id? | string |
<Reticle />
A box with corner ticks and a label, on the tracked point.
| Prop | What it does |
|---|---|
| track | PointTrack |
| from? | number |
| width? | number |
| height? | number |
| size? | The box's side, px. |
| label? | The text under the box. A confidence figure flickers beside it. |
| color? | string |
| jitter? | px the box shakes by each frame, as a lock that is never quite still. |
Effects (9)
Layer effects: put them in a layer's effects.
acid()
Brightness to hue: from hue (degrees) round the colour wheel cycles times (negative runs the other way) as the picture brightens, gamma under 1 spending more of the turn on the shadows, at full saturation, the brightest parts washed to white: the acid heat camera.
adaptiveCut()
A hard black and white cut that follows the footage: each pixel is cut against the mean brightness of a wide patch round it (reach, a fraction of the frame height), times bias, so bright footage and dark footage both split into big black and white shapes instead of going all white or all black.
acidHeat()
Acid heat camera.
1 and 4 soft blobs, folded; 2 sharp, warm shadows; 3 sharp, teal shadows.
fold()
One half folded onto the other. axis 0: left onto right, 1: top onto bottom. box is the picture on the canvas ([x, y, w, h], px); without it, the whole canvas.
grainyBW()
Grainy black and white.
1 soft and high-key, 5 high-key with grain; 2-4 a hard cut that follows the footage's brightness (3 and 4 folded), 6 the cut smeared down.
nightVision()
Night vision: lime phosphor with lifted blacks, a little noise.
1-5 smeared by the camera's move, 6 still.
screenGlow()
Screen glow: the picture's own colours pushed bright and blue-cyan into a big bloom.
1-3 bright (3 soft), 7 deep blue and crushed, 8 nearly clean, a little cool; 4-6 are 1 with room for an overlay (FLASH_OVERLAY).
streak()
A blur along one direction (degrees), as a fast pan or a shake smears it.
halftonePoster()
The halftone look as layer effects: the layer printed as ink dots on paper.
Functions (12)
crt()
A colour tube: curved glass, scanlines, aperture grille, misconvergence, a rolling bar, static and dark corners.
| Prop | What it does |
|---|---|
| cx? | The tube face's centre and half-size on the canvas, px. The default is the whole layer. |
| cy? | number |
| hw? | number |
| hh? | number |
| curve? | How far the glass bends. 0 is flat. |
| pitch? | Source pixels per scanline. |
| scan? | 0..1: how dark between the lines. |
| grille? | Screen pixels per grille stripe. |
| mask? | 0..1: how strong the grille is. |
| conv? | Pixels the red and blue guns land off green. |
| noise? | number |
| glass? | number |
| offx? | 1 is on. Switching off: offy falls to 0 first (a line), then offx (a dot). |
| offy? | number |
depthLook()
A depth map's look: near is white, far is black, smooth, no texture.
Brightness stands in for nearness.
lookEffects()
The effects for a vjLookSchema value (from the Studio panel): <Layer effects={lookEffects(look)}>.
oneBit()
One bit a pixel: grey, hard contrast, an ordered dither in cells of size px, printed in ink on paper.
pixels()
A magnifier: blocks, then red, green and blue subpixel stripes as the zoom grows.
switchOff()
The tube switching off over t 0..1, as crt()'s offx and offy: the picture folds to a bright line over the first 60%, and the line to a dot over the rest.
Spread it into the options: crt({ ...switchOff(t) }).
thermal()
A thermal camera's palette on the picture's brightness, a little soft.
vhs()
A worn tape: line wobble, late smeared colour, a head-switch tear, a drifting tracking band, snow and dropouts.
| Prop | What it does |
|---|---|
| jitter? | number |
| wobble? | number |
| trackAt? | 0..1: where the tracking band is, top to bottom. |
| trackW? | Half-height of the band, px. |
| track? | 0..1: how bad the tracking is. |
| bleed? | How wide the colour smears, px, and how late it lands. |
| delay? | number |
| sat? | number |
| snow? | number |
| drops? | 0..1: chance per line per frame of a dropout. |
blobsAt()
The blobs on composition frame frame (at fps) of a clip that starts on frame from, scaled to width x height.
The track may run at another rate than the composition: it is read by time. Past the clip's end: none.
linksOf()
cameraAt()
The camera on frame: eased between the keys, held before the first and after the last.
| Prop | What it does |
|---|---|
| pieces | Piece[] |
| camera? | Keys the camera eases between (x, y in px, z in depth units), or a function of the frame. Default: a slow push from z 0 to 0.5 over the composition. |
| colors? | Colours of the tags by name; other names get one from a set, the same each time. |
| fontSize? | Tag text size, clip px. Default 22. |
| fog? | 0..1: how much a piece dims per unit of depth past 1. Default 0.25. |
| inspect? | Show piece inspect flat, whole and filling the frame, at its clip's own frame (its from ignored), with every box's id, every spot's name and a grid in clip pixels: render stills of it to name the ids and place spots. |
| id? | string |
pointAt()
The tracked point on composition frame frame (at fps) of a clip that starts on from, scaled to width x height; held at the first or last point outside the clip.
Constants (7)
IRON
A thermal camera's palette (iron: cold violet through red to white-hot), a little soft as such sensors are.
RAINBOW
The other common one: cold blue through green to hot red and white.
FLASH_OVERLAY
Which screen-glow variants lay an overlay on (screen blend), and how strongly.
The overlay is the caller's.
LOOK_KINDS
The looks lookEffects knows, none included.
blobStyleSchema
How <Blobs> marks the blobs: its props other than the track.
Spread it into <Blobs>.
vjLookSchema
One look and the settings of each, so switching looks keeps what was set on the others.
MONO
Looks
The look kinds the Studio panel can switch between, and the export that draws each.
- none
- No look.
- crt crt
- A colour tube: curved glass, scanlines, aperture grille, misconvergence, a rolling bar, static and dark corners.
- vhs vhs
- A worn tape: line wobble, late smeared colour, a head-switch tear, a drifting tracking band, snow and dropouts.
- oneBit oneBit
- One bit a pixel: grey, hard contrast, an ordered dither in cells of size px, printed in ink on paper.
- thermal thermal
- A thermal camera's palette on the picture's brightness, a little soft.
- depth depthLook
- A depth map's look: near is white, far is black, smooth, no texture.
- pixels pixels
- A magnifier: blocks, then red, green and blue subpixel stripes as the zoom grows.
- glow screenGlow
- Screen glow: the picture's own colours pushed bright and blue-cyan into a big bloom.
- acid acidHeat
- Acid heat camera.
- night nightVision
- Night vision: lime phosphor with lifted blacks, a little noise.
- grainy grainyBW
- Grainy black and white.
- halftone halftonePoster
- The halftone look as layer effects: the layer printed as ink dots on paper.
Examples
import { Blobs, thermal, type BlobTrack } from '@kinetographdev/vj';
import track from './track/clip-blobs.json' with { type: 'json' };
<Layer id="clip" effects={thermal()}>
<Video src={staticFile('clip.mp4')} width={1920} height={1080} fit="cover" muted />
</Layer>
<Blobs track={track as BlobTrack} box="corners" links="chain" /># finds what moved since the last frame; --debug writes every 10th frame with its boxes
node plugins/vj/tools/blobs.mjs --in public/clip.mp4 --out track/clip-blobs.json --debug out/blobs
# follows one patch (x, y, w, h on the first frame)
node plugins/vj/tools/track.mjs --in public/clip.mp4 --box 900,300,120,120 --out track/clip-point.jsonIn Studio
Panel
Studio gets a VJ panel with a card for each look and that look's own sliders and colours. Switching looks keeps the settings of the others. On the preview you drag and resize the CRT screen and drag the magnifier's centre. A second panel sets how the tracking marks look: box style, labels, links, blend, how many blobs to show, line width and colour.
Tracking runs on your own machine ahead of time, so the panel only styles the result. The plugin adds no agent tools. The skill walks an agent through tracking a clip, checking the debug images, tuning the tracker and rendering a still to check. For Fragments it has the agent name the boxes from stills of each clip.
It is a package in the source repository. Its skill comes with it, so an agent can use it without being taught.