Pixelate Region

Cover rectangles of a scene with an opaque mosaic and leave the rest untouched

Experimental — html-in-canvas

This filter re-reads the real pixels of the scene it wraps 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, 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 fallback is what keeps your composition renderable if that happens.

Installation

$ pnpm dlx shadcn@latest add @remocn/pixelate-region

Usage

PixelateRegion is a wrapper. Give it rectangles in composition coordinates and everything inside them is resampled into an opaque mosaic — each cell takes the average of the picture under it — while the rest of the scene passes through untouched.

import { PixelateRegion } from "@/components/remocn/pixelate-region";
 
export const MyScene = () => (
  <PixelateRegion
    regions={[
      { x: 504, y: 332, width: 600, height: 72 },
      { x: 504, y: 444, width: 600, height: 72 },
    ]}
  >
    <Scene />
  </PixelateRegion>
);

Coordinates are in the same units as your composition — the width and height you gave <Composition> — with the origin at the top left. Read them straight off the frame you are covering.

The redaction guarantee

This component is a utility, not an effect, and it is built so that failing open is impossible.

Inside a region the output is always opaque. The untouched scene sits on a layer directly beneath the filter's output, so anything less than full coverage would show the original through — which for a mosaic over an API key is not a visual glitch, it is a leak. The mosaic is therefore composited over black and written at full alpha, every frame, on every path.

That includes the browsers that have no html-in-canvas at all. Where every other filter in the pack degrades to an approximation of its look, this one degrades to a plain opaque block over each region: less interesting, exactly as covering.

Passing more regions than can be covered at once throws rather than dropping the extras, for the same reason — a silently ignored region is a visible secret. Nest a second PixelateRegion if you need more than eight.

Choosing a cell size

cellSize is the width of one mosaic square in composition units. Text stops being readable well before it stops being recognisable, so err coarse: a cell around a third of the cap height of the text you are covering leaves nothing to reconstruct.

Props

PropTypeDefaultDescription
regions
PixelateRect[]Rectangles to cover, as { x, y, width, height } in composition coordinates from the top-left origin. Up to eight; more throws rather than silently dropping any.
cellSize
number24Width of one mosaic square in composition units. Cells are square, and each one is the average of the picture under it rather than a single sample.
children
React.ReactNodeThe scene the filter wraps and re-reads every frame.

Notes

Nothing here animates. The mosaic changes only when the scene under it does, so a region over static content is pixel-identical from frame to frame and a region over a moving dashboard tracks it.

The cell grid is anchored to each region's own top-left corner, so the mosaic starts cleanly at the edge of what you are covering instead of inheriting a grid from the frame.