# Subtitle
URL: https://remocn.dev/docs/captions/components/caption-subtitle

Classic broadcast subtitles, a whole phrase on a translucent plate, with no word-level animation at all

- Install: `npx shadcn@latest add @remocn/caption-subtitle`
- Vibe: clean
- Natural length: transcript-driven

## Installation

```bash
npx shadcn@latest add @remocn/caption-subtitle
```

## Usage

`CaptionSubtitle` is the subtitle you know from broadcast and streaming: a
whole phrase at a time, balanced across its lines, sitting on a tight
translucent plate that follows each line rather than one big box. Nothing
animates inside a phrase. A new phrase replaces the previous one on a hard
cut, and only fades in or out around silences.

Keep subtitles to two lines. The component wraps and balances its lines but
does not limit them, so give the block a width that fits two lines of your
longest phrase, or lower `combineTokensWithinMilliseconds` for shorter phrases.

The component renders only the text block. See [Positioning](/docs/captions/getting-started/positioning)
for safe placements and [Get a transcript](/docs/captions/getting-started/get-a-transcript)
for producing `captions.json`.

```tsx
import { AbsoluteFill } from "remotion";
import { CaptionSubtitle } from "@/components/remocn/caption-subtitle";
import captions from "./captions.json";

export const MyScene = () => (
  <AbsoluteFill
    style={{
      justifyContent: "flex-end",
      alignItems: "center",
      paddingBottom: 108,
      paddingInline: 384,
    }}
  >
    <CaptionSubtitle captions={captions} />
  </AbsoluteFill>
);
```

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `captions` | `Caption[]` | `—` | The timed transcript, in the `Caption` shape from `@remotion/captions`. Times are relative to the start of the surrounding `Sequence`. |
| `combineTokensWithinMilliseconds` | `number` | `2500` | How much speech one subtitle may span. Sized for a full phrase. Subtitles also break at the end of a sentence and on any pause of at least `holdMs` (300 ms minimum). |
| `holdMs` | `number` | `600` | How long a subtitle stays after its last word when the next one is not already due. It fades out at the end of the hold. |
| `fontSize` | `number` | `44` | Font size in pixels. |
| `fontWeight` | `number` | `600` | Font weight. The font itself is inherited. |
| `color` | `string` | `"#ffffff"` | Text colour. |
| `box` | `boolean` | `true` | Draw a translucent plate behind each line. When off, a text shadow keeps the subtitle legible instead. |
| `boxColor` | `string` | `"#000000"` | Colour of the plate. |
| `boxOpacity` | `number` | `0.72` | Opacity of the plate, from 0 to 1. |
| `className` | `string` | `—` | Classes for the text block — width, font family. |

## Use when
- Explainers, interviews and talking heads where the captions should be read, not watched — the accessibility-first option.
- Long sentences and dense information, where a full phrase on screen reads faster than words arriving one at a time.

## Don't use when
- Short-form social video that needs the caption to carry energy — use `caption-karaoke` or `caption-active-pop`.
- One short line at a time that keeps moving with the speaker — use `caption-slot`.
- On-screen copy with no voiceover — use `word-stream`.