Glitch Cut
Tear a hard cut into displaced slices with channel split and corrupted blocks
This transition post-processes the real pixels of both scenes through the experimental html-in-canvas browser API. The preview above shows the true effect in Chrome 149+ with chrome://flags/#canvas-draw-element enabled (nested canvases need 152.0.7944.0+). Every other browser — Safari, Firefox, Chrome without the flag — falls back to a CSS approximation of the same cut, so the page and your video still play.
Rendering is supported through the CLI, Studio, Lambda and SSR with --gl=angle, or --gl=swangle on a machine without a GPU. Chrome may change or discontinue the API; the CSS fallback is what keeps your composition renderable if that happens.
Installation
$ pnpm dlx shadcn@latest add @remocn/glitch-cutUsage
glitchCut() is a Remotion transition presentation. Pass it to a
TransitionSeries.Transition between two sequences. The frame breaks into
horizontal slices that slide apart, the colour channels separate, and blocks of
the frame corrupt into the wrong scene — then each slice hands over to the
incoming scene on its own beat around the midpoint, so the cut itself is torn
rather than flat. Both ends of the transition settle to untouched pixels, so
nothing bleeds into the scenes on either side.
It is built for short timings. linearTiming({ durationInFrames: 12 }) is the
recommended default; past roughly 20 frames the tearing stops reading as an
artifact and starts reading as an effect.
import { TransitionSeries, linearTiming } from "@remotion/transitions";
import { glitchCut } from "@/components/remocn/glitch-cut";
export const MyVideo = () => (
<TransitionSeries>
<TransitionSeries.Sequence durationInFrames={45}>
<SceneA />
</TransitionSeries.Sequence>
<TransitionSeries.Transition
timing={linearTiming({ durationInFrames: 12 })}
presentation={glitchCut()}
/>
<TransitionSeries.Sequence durationInFrames={45}>
<SceneB />
</TransitionSeries.Sequence>
</TransitionSeries>
);Installing it also installs lib/remocn/canvas-presentation.tsx, the shared
scaffolding behind every canvas transition. It owns the support check, the
WebGL2 scene shader that receives both sides of the cut as textures, and the
routing that swaps in the CSS fallback where the browser has no html-in-canvas.
Determinism
Every pixel is a pure function of the transition's progress. The slice displacement, the block corruption and the per-slice handover all come from a hash seeded on the slice index and on a 22-step clock derived from progress — no wall-clock time, no state carried between frames. The same frame renders identically on every machine and in every chunk, so parallel and server-side renders come out seam-free.
Fallback
Where html-in-canvas is unavailable the presentation renders a CSS
approximation instead: the frame is clipped into bands that shift horizontally
on the same seeded clock, each band tinted alternately red and cyan to stand in
for the channel split, and each band hands over to the incoming scene at its own
staggered cut point. It reads as the same edit — a torn hard cut — without
touching pixels. slices still drives how many bands there are; blockNoise
has no effect there.
Props
glitchCut(props) accepts:
| Prop | Type | Default | Description |
|---|---|---|---|
intensity | number | 1 | Overall displacement. Scales how far slices and corrupted blocks slide sideways. 0 leaves the geometry intact and keeps only the channel split. |
slices | number | 24 | How many horizontal slices the frame is cut into. Low counts read as chunky tape damage, high counts as fine scanline tearing. |
rgbSplit | number | 1 | Chromatic separation of the red and blue channels at the peak of the glitch. 0 keeps the colour clean. |
blockNoise | number | 0.6 | How much of the frame corrupts into displaced blocks that leak the other scene. 0 keeps the tearing purely horizontal. |