Text Mask Video
Play video, a still, or a gradient inside letterforms, with a wipe reveal. Install with npx remotion-ui@latest add text-mask-video.
PrimitivePrimitivesAdvanced
$ npx remotion-ui@latest add text-mask-videoMedia seen through a word.
import { staticFile } from "remotion";
import { TextMaskVideo } from "@/remotion/primitives/text-mask-video";
<TextMaskVideo
text={"IN\nMOTION"}
src={staticFile("clips/skyline.mp4")}
fontSize={172}
fontWeight={900}
reveal="left"
/>Why a clip path, not background-clip
background-clip: text only takes a paint, so it can carry a gradient and it
can carry an image, but it can never carry a video. Clipping a real element with
an SVG clipPath of <text> means one code path covers all three: the media
underneath is a normal <OffthreadVideo> that seeks and trims like any other.
Set media explicitly to force a mode. It defaults to video when src is
set and gradient when it is not.
The reveal is a second clip
One element gets one clip-path, so the wipe lives on a child of the
letter-clipped layer. reveal takes left, right, up, down or none,
runs on the entrance and unwinds on the exit.
Sizing
width and height are the clip's coordinate space and the type is positioned
inside it arithmetically. Nothing is measured: a measured layout renders one
thing on frame 0 of a headless render and another on frame 1. Both default to
multiples of fontSize; set them when the copy is long.
Footage almost always needs lifting
A clip that reads fine full-frame is usually too dark once it is only visible
inside letterforms. mediaFilter takes any CSS filter — brightness(2.2) saturate(1.5) is a reasonable starting point for night footage.
An SVG clipPath on a real element, not `background-clip: text` — that only takes a paint, so it can never carry a video.
Agent notes
Install first, then import the copied source component locally. AI guide →
@/remotion/primitives/text-mask-video- Use when: frame-level motion primitives and reusable animation wrappers.
- Customize: text, src, media, gradient, plus copied source for timing, layout, colors, and typography.
- Rule: do not import this component from the
remotion-uinpm package; it is copied into your project.
Usage
import { staticFile } from "remotion";
import { TextMaskVideo } from "@/remotion/primitives/text-mask-video";
<TextMaskVideo
text={"IN\nMOTION"}
src={staticFile("clips/skyline.mp4")}
fontSize={172}
fontWeight={900}
/>API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| text | string | - | The letterforms the media is seen through. `\n` breaks a line. |
| src | string | - | Video or image source. Wrap local files in `staticFile()`. |
| media | "video" | "image" | "gradient" | video with a src, gradient without | Which layer is drawn behind the letters. |
| gradient | string | - | Any CSS background, used by `media="gradient"`. |
| mediaFilter | string | - | CSS filter on the media. Footage is usually too dark inside letterforms. |
| reveal | "left" | "right" | "up" | "down" | "none" | "left" | Which way the letters are uncovered. |
| width | number | - | Clip coordinate space. Defaults to a multiple of `fontSize`. |
| height | number | - | Clip coordinate space. Defaults from the line count. |
| drift | number | 26 | Peak sideways travel of the media, in px. |
| zoom | number | 0.12 | Extra scale the media breathes through. 0 holds it still. |
| startFrom | number | - | Frame offset into the video. |
| durationInFrames | number | 30 | Length of the reveal. |
| delayInFrames | number | 0 | Frames before the reveal starts. |
| exitAtInFrames | number | - | Frame the reveal starts unwinding on. |