Weight

The word being spoken swells from a light weight to a heavy one and relaxes as the voice moves on, with no layout shift

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

Usage

CaptionWeight takes a timed transcript and renders only the text block, so place it inside your own AbsoluteFill. See Positioning for safe placements and Get a transcript for producing captions.json.

Each word reserves the width of its heaviest weight, so the line never moves while a word gains weight. The ramp is only as smooth as the weights your font has: a variable font interpolates every step, a static family snaps to the nearest loaded weight. With @remotion/google-fonts, load the variable version of the family so every weight in between exists.

tsx
import { loadVariableFont } from "@remotion/google-fonts/Inter";
import { AbsoluteFill } from "remotion";
import { CaptionWeight } from "@/components/remocn/caption-weight";
import captions from "./captions.json";
 
const { fontFamily } = loadVariableFont("normal", { subsets: ["latin"] });
 
export const MyScene = () => (
  <AbsoluteFill
    style={{
      justifyContent: "flex-end",
      alignItems: "center",
      paddingBottom: 108,
      paddingInline: 192,
    }}
  >
    <div style={{ fontFamily }}>
      <CaptionWeight captions={captions} />
    </div>
  </AbsoluteFill>
);

Props9

PropTypeDefault
captions
Caption[]—

The timed transcript, in the `Caption` shape from `@remotion/captions`. Times are relative to the start of the surrounding `Sequence`.

combineTokensWithinMilliseconds
number1200

How 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
number600

How 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.

fontSize
number64

Font size in pixels.

fontWeight
number400

Resting weight of every word that is not being spoken.

activeWeight
number900

Weight the spoken word ramps to over about 150ms, then relaxes from when the next word starts.

color
string"#ffffff"

Text colour.

shadow
booleantrue

A tight text shadow that keeps the caption legible over bright footage.

className
string—

Classes for the text block — width, font family, `uppercase`.

  • captionsCaption[]

    The timed transcript, in the `Caption` shape from `@remotion/captions`. Times are relative to the start of the surrounding `Sequence`.

    Default—

  • combineTokensWithinMillisecondsnumber

    How 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).

    Default1200

  • holdMsnumber

    How 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.

    Default600

  • fontSizenumber

    Font size in pixels.

    Default64

  • fontWeightnumber

    Resting weight of every word that is not being spoken.

    Default400

  • activeWeightnumber

    Weight the spoken word ramps to over about 150ms, then relaxes from when the next word starts.

    Default900

  • colorstring

    Text colour.

    Default"#ffffff"

  • shadowboolean

    A tight text shadow that keeps the caption legible over bright footage.

    Defaulttrue

  • classNamestring

    Classes for the text block — width, font family, `uppercase`.

    Default—