Animated captions for your product

One renderFrame draws word-level animated captions on canvas: live over a <video> in the browser, and frame for frame into an MP4 with FFmpeg. No headless browser.

Read the docs

MIT licensed · React-free core · Node + FFmpeg for server renders

SamecaptionsinyourbrowserandinFFmpeg

Styles

Pick a look, ship it everywhere

Each preset is a plain object: use it as is or clone and tweak it. The same preset runs in the browser preview and in the FFmpeg render.

Every preview is rendered by the engine itself, the same way npx captions.js burn renders your video.

Karaokebounce
Focus Boxbox-word
Bangerpop
Acidnone
Lovlyscale
Marvelscale
Markerunderline
Neon Pulseslide-up
Beastypop
Crazynone
Safaribox
Poplinenone
Desertbounce
Hookunderline
Skyslide-left
Flamingoscale
Deep Diver B&Wbox
Newpop
Catchybounce
Frompop
Classicnone
Classic Bignone
Old Moneyslide-up
Cinemanone
Midnight Serifbox
Aurora Inkunderline

Use it

One renderer, four ways in

import captionsjs, { getPreset, toCaptions } from "captions.js";

const video = document.querySelector("video")!;

// Deepgram response or a plain [{ word, startTime, endTime }] array
const captions = toCaptions(transcript);

const instance = captionsjs({
  video,
  preset: getPreset("Karaoke"),
  captions,
});

// live updates, no remount
instance.preset(getPreset("Focus Box"));
instance.captions(editedCaptions);

instance.destroy();

Features

Kinetic captions, identical in both places

Preview equals export

The browser overlay and the FFmpeg render call the same renderFrame on the same Konva scene. What your user styles is what comes out.

No headless browser

Server renders run on skia-canvas piped into FFmpeg. No Chrome in your production pipeline.

26 style presets

Karaoke, Focus Box, Banger, Neon Pulse, Cinema and more. Each preset is a plain object you can clone and edit.

10 word animations

bounce, pop, scale, box, box-word, underline, slide-left, slide-up, slide-down or none.

Any word timings

toCaptions() reads a Deepgram response or a plain word array; the server also takes Whisper verbose_json.

Full typography

Google Fonts on demand, stroke, shadow, capitalization, active and past word colors, sentence-aware line breaks.

Put animated captions in your product this afternoon.

Rather not run render servers? captions.js Cloud is in early access.