Skip to main content

wordcaps

Word-by-word karaoke captions for any video, made on your machine.

wordcaps transcribes a video with Whisper, lines every word up with the actual voice, and burns animated captions into the video: the word being spoken lights up as it is said. It works offline, costs nothing per minute, and gives you an editable file in between, so you can fix a typo and re-render in seconds.

Three caption styles on the same clip: reel, box and pop

It was built for vertical Reels, Shorts and TikToks, and works on any video: landscape interviews, courses, square posts.

CI PyPI Python License: MIT

Why another captioning tool

Most auto-captioning is either a paid cloud service or a script that trusts Whisper's timestamps. Those timestamps are good at which words were said and noticeably worse at when: on a clip that opens with a second of silence, the first words routinely show up early. On a fast-cut vertical video that is the difference between captions that feel glued to the voice and captions that feel off.

wordcaps treats timing as the core problem:

  • Silence-aware transcription. It finds speech in the loudness envelope first and hands Whisper only the stretches with voice, each starting 0.15 s before the first sound, so leading silence can't drag the words early.
  • Envelope snapping. Word edges that fall in silence are moved onto the real speech onset or offset.
  • A coverage check on the output. After rendering, wordcaps re-reads the audio of the finished file and tells you if any moment of speech has no caption on screen. It exits non-zero, so it also works in scripts.

How it works in detail: docs/how-it-works.md.

Install

You need Python 3.11+ and ffmpeg. For speech-to-text, pick one backend:

# macOS: whisper.cpp is fast on Apple Silicon
brew install ffmpeg whisper-cpp
pipx install wordcaps
wordcaps models download base
# Linux / Windows: faster-whisper, a pure pip install
pipx install "wordcaps[faster-whisper]"

Then check that everything is in place:

wordcaps doctor

Quick start

wordcaps burn talk.mp4 --lang en

This writes talk.captioned.mp4, plus talk.captioned.json with every word and its timing. Whisper will get a few words wrong: open the JSON, fix them, and render again without transcribing:

wordcaps burn talk.mp4 --captions talk.captioned.json

The captions file keeps one caption per line, so it stays easy to edit:

{
  "wordcaps": 1,
  "language": "en",
  "cues": [
    {"words": [["HI", 1.15, 1.23], ["EVERYONE", 1.23, 2.25]]},
    {"words": [["TODAY", 2.25, 2.43], ["I", 2.43, 2.51], ["WANT", 2.51, 2.74]]}
  ]
}

Each word is [text, start, end] in seconds. Add "lines": [0, 2] to a cue to force a line break before its third word.

Styles

wordcaps styles
Style For Look
reel (default) Reels, Shorts, TikTok Bold caps, the spoken word turns yellow
box Vertical The spoken word sits on a colored box, with a small pop
pop Vertical Two words at a time, the spoken word grows and turns green
ocean Vertical Compact two-line captions with a blue highlight
landscape 16:9 video Sentence case, lower third, longer lines, punctuation kept
minimal Anything No outline, soft shadow, subtle highlight

Sizes and positions are fractions of the frame, so every style works at any resolution. Tweak any option from the command line:

wordcaps burn talk.mp4 --style box --set highlight=#FF4D8D --set max_words=2

Or keep your brand in a TOML file that starts from a preset (example):

extends = "reel"
highlight = "#FF4D8D"
highlight_mode = "box"
emphasis = ["FREE", "TODAY"]   # these words get a box and a bouncy pop
wordcaps burn talk.mp4 --style brand.toml
wordcaps styles --show reel    # every option, with its current value

An emphasis word popping in a colored box

Iterate on a style without rendering the whole video:

wordcaps preview talk.mp4 talk.captioned.json --at 3.2 -o frame.png

Using it with a video editor

Keep editing in Premiere, Final Cut, DaVinci or CapCut and let wordcaps do only the captions:

# captions only, transparent background, ProRes 4444
wordcaps burn talk.mp4 --overlay-only -o captions.mov

# or standard subtitle files
wordcaps export talk.captioned.json -o talk.srt
wordcaps export talk.captioned.json -o talk.ass --size 1080x1920

The .ass export reproduces the word-by-word highlight (one event per word); the box and pop animations exist only in burned-in video.

All commands

Command What it does
wordcaps burn VIDEO Transcribe (or read --captions) and burn captions in
wordcaps transcribe VIDEO Only write the editable captions file
wordcaps preview VIDEO CAPTIONS --at T Render one frame, to check a style
wordcaps export CAPTIONS -o file.srt Convert to SRT, VTT or ASS
wordcaps verify VIDEO CAPTIONS Report speech with no caption on screen
wordcaps sheet VIDEO Contact sheet of evenly spaced frames
wordcaps styles List presets, --show NAME for all options
wordcaps models list / download NAME Manage whisper.cpp models
wordcaps doctor Check ffmpeg, backends, models and fonts

Useful flags: --lang (default auto-detect), --model (base, small, large-v3-turbo, or a path to a .bin), --backend, --threshold (speech level in dBFS, or auto for noisy recordings), --crf for output quality.

Choosing a model

Model Download Notes
base 142 MB Fast, fine for clear English
small 466 MB Good default for other languages
large-v3-turbo 1.6 GB Best accuracy, still quick on Apple Silicon

Models are stored in ~/.cache/wordcaps/models (override with WORDCAPS_MODELS). Downloads resume if the connection drops.

Limitations

  • HDR sources are captioned but not tone mapped: export SDR first if colors look washed out.
  • One speaker style per video: there is no per-speaker color yet.
  • The loudness-based checks assume speech is louder than the background. With loud music under the voice, try --threshold auto or a higher value.

Roadmap

  • Per-speaker colors (diarization)
  • Automatic emphasis on keywords
  • Emoji and title overlays
  • A Python API reference

Ideas and pull requests are welcome, see CONTRIBUTING.md.

Credits

License

MIT, see LICENSE. The bundled Montserrat fonts are under the SIL Open Font License.

Metadata

Release files for wordcaps 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for wordcaps 0.1.0
File Size Uploaded
wordcaps-0.1.0.tar.gz 1.8 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for wordcaps 0.1.0
File Interpreter ABI Platform
wordcaps-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 2.2 MB

Release files / wordcaps-0.1.0.tar.gz

Download URL wordcaps-0.1.0.tar.gz
Size 1.8 MB
Tags Source
SHA-256 checksum
How to use checksums
8388da2bd5f1ba6abd6b03dc7c99db6ab4ec70338b75b081ace95b59c87321a8
BLAKE2b-256 checksum
How to use checksums
a2ca4c43e5af5ee898cf9da96350ef36e862373e88a2d5a0236ab6837aeeb191
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / wordcaps-0.1.0-py3-none-any.whl

Download URL wordcaps-0.1.0-py3-none-any.whl
Size 420.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
44b2691e3e891107262c4d8f34a5352607c6b5af1ef6470576aa48fac0e1f226
BLAKE2b-256 checksum
How to use checksums
7104ea681fbd1a30d343420a963162785edd096caa791a8e19304ada08ebf479
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page