Sign inSign up

maskin25/captions.js-render

By maskin25

•Updated 10 days ago

captions.js (captionsjs) — burn animated word-level captions/subtitles into video with FFmpeg

Image
Integration & delivery
0

648

maskin25/captions.js-render repository overview

⁠@captionsjs/server

Burn captions.js⁠ animated word-level captions into a video file. It runs the same renderFrame as the browser overlay, drawn with skia-canvas and piped into FFmpeg. No headless browser.

⁠CLI

npx captions.js burn talk.mp4 words.json --preset Karaoke
# → talk.captions.mp4

words.json is any of:

[{ "word": "Hello", "start": 0.12, "end": 0.48 }, ...]   // plain word timings
{ "segments": [{ "words": [...] }] }                     // OpenAI Whisper verbose_json
{ "results": { "channels": [...] } }                     // Deepgram response
Option
-p, --preset <name>Style preset, case-insensitive (default Karaoke). npx captions.js presets lists them.
-o, --output <file>Output path (default <video>.captions.mp4).
--fps <n>Overlay frame rate (default: source fps, max 60).
--fonts-dir <dir>Folder with TTFs in Google Fonts layout (Family_Name/FamilyName-Bold.ttf).
--crf <n>x264 quality (default 20).

Requires ffmpeg and ffprobe on PATH (or FFMPEG_PATH / FFPROBE_PATH). Preset fonts are downloaded from Google Fonts on first use and cached in ~/.cache/captionsjs/fonts (override with CAPTIONSJS_CACHE_DIR).

⁠Node API

import { burnCaptions } from "@captionsjs/server";

const { output } = await burnCaptions({
  video: "talk.mp4",
  captions: "words.json", // path, URL, JSON string or parsed array
  preset: "Focus Box",
  onProgress: ({ frame, totalFrames }) => console.log(frame / totalFrames),
});

Font size follows the browser overlay rule (videoHeight / 480), so what you tune in the preview is what you get in the file. Pass scale to override.

⁠Docker

Multi-arch image (linux/amd64, linux/arm64) with FFmpeg and all preset fonts baked in — works offline.

# CLI: mount a folder, burn, done
docker run --rm -v "$PWD:/data" maskin25/captions.js-render \
  burn /data/talk.mp4 /data/words.json --preset Karaoke -o /data/out.mp4

# HTTP service on :4000 (GET /health, POST /burnCaptions)
docker run -p 4000:4000 maskin25/captions.js-render

The HTTP endpoint currently takes the Pub/Sub push envelope used by Shorty.plus ({ message: { data: base64({ preset, video_uri, captions_uri, output_uri }) } }). A simpler upload-and-download API is planned.

MIT © maskin25

Tag summary

Content type

Image

Digest

sha256:1da507879…

Size

285.1 MB

Last updated

10 days ago

docker pull maskin25/captions.js-render