Scramble

Each word arrives as random glyphs at the moment it is spoken and decodes left to right into the real letters

Installation
$ pnpm dlx shadcn@latest add @remocn/caption-scramble

Usage

CaptionScramble keeps each word hidden until the voice reaches it. The word then appears as random glyphs that resolve into the real letters from left to right, taking as long as the word is spoken for, capped at 300ms, so short words snap and long ones decode visibly. The glyphs re-roll every two frames and are seeded from the frame, so every render is identical. The real word reserves its space from the start, so the line never shifts while it builds. The component renders only the text block, so place it inside your own AbsoluteFill — see Positioning.

import { AbsoluteFill } from "remotion";
import { CaptionScramble } from "@/components/remocn/caption-scramble";
import captions from "./captions.json";
 
export const MyScene = () => (
  <AbsoluteFill
    style={{
      justifyContent: "flex-end",
      alignItems: "center",
      paddingBottom: 108,
      paddingInline: 192,
    }}
  >
    <CaptionScramble captions={captions} />
  </AbsoluteFill>
);

A monospaced font keeps the decoding glyphs exactly as wide as the letters they replace. With a proportional font the glyphs can run slightly past the word for a frame or two while it resolves.

Props
PropTypeDefaultDescription
captions
Caption[]—The timed transcript, in the `Caption` shape from `@remotion/captions`. Times are relative to the start of the surrounding `Sequence`.
combineTokensWithinMilliseconds
number1200How much speech one page may span before the next word starts a new page. Pages also break at the end of a sentence and on any pause of at least `holdMs` (300 ms minimum).
holdMs
number600How long a page stays after its last word when the next page is not already due. It fades out at the end of the hold.
glyphColor
string"#a3a3a3"Colour of the glyphs that have not resolved yet. Resolved letters use `color`.
fontSize
number64Font size in pixels.
fontWeight
number800Font weight. The font itself is inherited.
color
string"#ffffff"Colour of resolved letters.
shadow
booleantrueA tight text shadow that keeps the caption legible over bright footage.
className
string—Classes for the text block — width, font family, `uppercase`.