Reel 01Go CLIffmpeg + Deepgramsrt · vtt · txt · json

Cut subtitles
straight from the file.

subkit extracts the audio, transcribes it, shapes the words into cues and renders every format you asked for — from one command, with every stage cached so the next run is instant.

00:00:12:04 CUE 001 / 614 SUBKIT

Nobody tells you that the hard part of subtitling isn't the words. It's deciding where to cut them. Ninguém nos diz que a parte difícil das legendas não são as palavras. --language pt-PT 42 characters a line. 17 a second. Two lines, never three. --subtitle-algorithm netflix

Get started subkit subtitle movie.mp4

Needs ffmpeg on your PATH and a DEEPGRAM_API_KEY. Full setup →

What comes out

Four artefacts,
one transcription.

Ask for as many outputs as you like in a single command. They are all rendered from the same cached transcript, so extra formats cost nothing but the write.

movie.srt
1
00:00:12,040 --> 00:00:15,900
Nobody tells you that the hard part
of subtitling isn't the words.

2
00:00:16,400 --> 00:00:18,880
It's deciding where to cut them.

The pipeline

Five stages.
Each one an artefact.

Every stage writes a cached artefact keyed by the source media hash, the step options, the pipeline version and — for audio — the ffmpeg build. Stop at any one of them, or run the lot.

InputMedia file
Stage 1 · extract-audioNormalized audio
Stage 2 · transcribeTranscript
Stage 3 · cuesCues
Stage 4 · rendersrt · vtt · txt · json

Provider-neutral transcript

Words carry text, punctuation, start and end, confidence, speaker, channel and language. Segments carry type and word ranges. Deepgram today, without a schema that assumes it.

Whole seasons at a time

Pass files or globs. Four run concurrently by default, a live terminal view tracks each one, and failures are collected into a summary instead of killing the queue.

Audio stays temporary

Normalized audio is run-local by default because it grows fast. Pass --cache-audio when you want it kept and reused between runs.

Progress that adapts

An interactive Bubble Tea view in a terminal, plain log lines when output is redirected. Force either with --progress tui or --progress plain.

Cue shaping

The hard part
isn't the words.

Transcription gives you tokens and timestamps. Deciding where a cue starts, where a line breaks and how long it stays on screen is a different problem — and subkit ships two answers to it. Same audio, same transcript, below:

--subtitle-algorithm deepgram Default
1
00:00:12,040 --> 00:00:14,180
[speaker 0]
Nobody tells you that the hard part of

2
00:00:14,180 --> 00:00:17,640
subtitling isn't the words. It's deciding where to

3
00:00:17,640 --> 00:00:18,880
cut them.
8 words per cueexact word timingspeaker labelssplits on speaker change
--subtitle-algorithm netflix Style guide
1
00:00:12,040 --> 00:00:15,900
Nobody tells you that the hard part
of subtitling isn't the words.

2
00:00:16,400 --> 00:00:18,880
It's deciding where to cut them.
42 chars / line2 lines max17 chars / second5⁄6s – 7ssentence-first

deepgram is a faithful port of deepgram-go-captions — fixed-size chunks, timing taken straight from the first and last word. netflix follows the Timed Text Style Guide: it never spans a speaker change or a long silence, packs whole sentences while they fit, splits oversized ones at the best linguistic break, and favours bottom-heavy line breaks. Read the full comparison →

Caching

Run it twice.
Pay once.

Cache keys hash the source media, the step options, the pipeline version and the ffmpeg version string. Change a subtitle flag and only the cue and render stages rebuild — the transcription is reused. Delete an output file and it comes straight back from the render cache.

subkit subtitle movie.mp4 --rerun transcribe  # one stage
subkit subtitle movie.mp4 --rerun audio,cues  # several
subkit subtitle movie.mp4 --refresh            # rebuild all
subkit subtitle movie.mp4 --no-cache           # touch nothing
First run31.4s
ffmpeg extract · Deepgram call · cue build · render
Same command again0.08s
Every artefact restored from cache. No provider call, no second bill.

Distribution

Install it

A single static binary, built for amd64 and arm64 on all three platforms. No runtime to install beyond ffmpeg.

Windowsx64 · arm64
winget install AndreSantos.Subkit

Or run the .msi installer from the releases page.

macOSarm64 · x64
subkit_darwin_arm64.dmg

Disk images and .zip archives on the releases page.

Linuxamd64 · arm64
curl -sSL …/subkit_linux_amd64.tar.gz | tar xz

Move the subkit binary anywhere on your PATH.

Go1.26+
go install github.com/andrerfcsantos/subkit-codex/cmd/subkit@latest

Builds from source, everywhere Go runs.

Prerequisites: ffmpeg on your PATH and a DEEPGRAM_API_KEY environment variable. Per-platform notes, verification and shell setup are in the install guide.

Now go read
the flags.