Sustained Glitch

Hold a scene under scheduled bursts of broadcast corruption, resting clean in between

Installation
$ pnpm dlx shadcn@latest add @remocn/sustained-glitch

Usage

SustainedGlitch is a wrapper. Put a scene inside it and the frame stays clean until a burst fires: slices tear sideways on their own beats, the colour channels pull apart, and blocks fill with picture dragged in from somewhere else in the frame. The burst decays over a few frames and the scene goes back to untouched until the next one.

This is the one filter in the pack that is not a steady texture. That is the point — a constant glitch stops reading as a fault and starts reading as a material.

tsx
import { SustainedGlitch } from "@/components/remocn/sustained-glitch";
 
export const MyScene = () => (
  <SustainedGlitch>
    <Scene />
  </SustainedGlitch>
);

How the bursts are scheduled

Time is cut into slots — one per second at frequency={1}, shorter as you raise it. Most slots fire a burst, at a position and length seeded inside the slot, and the whole schedule is a function of the frame number, so it is identical on every render.

Two knobs shape it. frequency sets how often the frame can break; intensity scales how hard it breaks when it does, and at 0 nothing fires at all.

Landing a hit on a beat

intensity is a plain number read every frame, so interpolate it. To put damage on a specific beat, raise frequency until bursts are effectively continuous and let the envelope decide when they are visible.

tsx
import { interpolate, useCurrentFrame } from "remotion";
import { SustainedGlitch } from "@/components/remocn/sustained-glitch";
 
export const MyScene = () => {
  const frame = useCurrentFrame();
  const intensity = interpolate(
    frame,
    [40, 44, 52],
    [0, 1.6, 0],
    { extrapolateLeft: "clamp", extrapolateRight: "clamp" },
  );
 
  return (
    <SustainedGlitch intensity={intensity} frequency={6}>
      <Scene />
    </SustainedGlitch>
  );
};

Props5

PropTypeDefault
intensity
number1

How hard a burst hits. Read every frame, so it can be interpolated to script the damage. At 0 no burst is visible and the scene passes through untouched.

frequency
number1

How often the frame can break, in bursts per second at 30fps. Around 6 the slots are short enough that the tearing is effectively continuous, which is what you want when intensity is driving the timing instead.

slices
number24

How many horizontal slices the frame tears into. Low counts read as chunky tape damage, high counts as fine scanline tearing.

seed
number1

Shifts the whole schedule and the per-slice pattern. Change it when two scenes in one video should not break up in the same rhythm.

children
React.ReactNode—

The scene the filter wraps and re-reads every frame.

  • intensitynumber

    How hard a burst hits. Read every frame, so it can be interpolated to script the damage. At 0 no burst is visible and the scene passes through untouched.

    Default1

  • frequencynumber

    How often the frame can break, in bursts per second at 30fps. Around 6 the slots are short enough that the tearing is effectively continuous, which is what you want when intensity is driving the timing instead.

    Default1

  • slicesnumber

    How many horizontal slices the frame tears into. Low counts read as chunky tape damage, high counts as fine scanline tearing.

    Default24

  • seednumber

    Shifts the whole schedule and the per-slice pattern. Change it when two scenes in one video should not break up in the same rhythm.

    Default1

  • childrenReact.ReactNode

    The scene the filter wraps and re-reads every frame.

Notes

Between bursts the filter writes the scene through unchanged, so a scene wrapped at intensity={0} costs a texture read and nothing else visually.

The CSS fallback keeps the same shape — clean, then a burst of shifted bands, then clean — but its schedule is its own. If you have timed something against a specific burst in Chrome, check it once on the fallback path before shipping.

The corrupted blocks pull picture from a displaced coordinate, which is why this needs the canvas: the block does not tint or mask what was already under it, it shows a piece of somewhere else in the frame.