srt_gen is a cross-platform Python CLI that generates English .srt subtitle files from video or audio input.
It is built for local-first usage with Whisper and supports four local/cloud backend paths:
mlx-whisper(preferred on Apple Silicon)faster-whisper(cross-platform local backend)- OpenAI Whisper (PyTorch backend; supports
mps,cuda,cpu) - OpenAI audio translation API (optional cloud backend)
- Accepts media input (any format ffmpeg can decode).
- Extracts mono 16k audio from the source.
- Transcribes and translates speech to English.
- Splits text into readable subtitle cues.
- Writes a standards-compliant
.srtfile.
- Source language: any language (
--source-lang autoby default). - Output language: always English.
- Backends:
auto(default): picksmlxon Apple Silicon, otherwiselocalmlx:mlx-whisperbackend (Apple Silicon only)local:faster-whispertorch: OpenAI Whisper via PyTorch (mps/cuda/cpu)openai(optional): OpenAI audio translation API
- Python
3.10+ ffmpegandffprobeonPATH
./setup_env.sh .venvWhat this does:
- verifies
python3,ffmpeg, andffprobe - creates
.venv - installs project dependencies (
.[openai,dev]), plus Apple extras on Apple Silicon - prompts for install profile in interactive shells:
cpu,mlx, ortorch - verifies backend dependency consistency and auto-fixes common
torch/openai-whispermismatch - pre-downloads a default model on Apple Silicon (
mlx-community/whisper-large-v3-mlx)
Optional: preselect profile without prompt (useful for CI):
SRT_GEN_INSTALL_PROFILE=torch ./setup_env.sh .venvOptional custom pre-download:
# faster-whisper model
./setup_env.sh .venv large-v3 local
# mlx-whisper model
./setup_env.sh .venv mlx-community/whisper-large-v3-mlx mlxmacOS/Linux:
source .venv/bin/activateWindows PowerShell:
.venv\Scripts\Activate.ps1srt-gen /path/to/video.mp4If -o/--output is omitted, output defaults to the same base filename with .srt:
- input:
meeting.mp4 - output:
meeting.srt
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install --upgrade pip setuptools wheel
pip install -e .Optional OpenAI API support:
pip install -e ".[openai]"Apple Silicon optional extras:
pip install -e ".[apple]"Optional PyTorch Whisper backend (--backend torch):
pip install -e ".[torch]"srt-gen input.mp4srt-gen input.mp4 -o subtitles/output.srtsrt-gen input.mp4 --backend local --model mediumsrt-gen input.mp4 --backend mlx --model mlx-community/whisper-large-v3-mlxsrt-gen input.mp4 --backend torch --device mps --model large-v3srt-gen input.mp4 --source-lang jaexport OPENAI_API_KEY=your_key_here
srt-gen input.mp4 --backend openai --model whisper-1Or pass API key directly:
srt-gen input.mp4 --backend openai --api-key your_key_heresrt-gen input.mp4 --quietsrt-gen input [-o output.srt]
[--backend auto|local|mlx|torch|openai]
[--model MODEL]
[--source-lang LANG|auto]
[--api-key KEY]
[--ffmpeg-bin PATH]
[--max-line-chars N]
[--max-lines N]
[--max-cps N]
[--min-duration SECONDS]
[--max-duration SECONDS]
[--device auto|cpu|cuda|mps]
[--compute-type TYPE]
[--quiet]
input- path to source video/audio file
-o, --output- output
.srtpath - default: input path with
.srtextension
- output
--backendauto(default),local,mlx,torch, oropenai
--model- auto/mlx default:
mlx-community/whisper-large-v3-mlx(Apple Silicon) - local default:
large-v3(non-Apple, or when--backend local) - torch default:
large-v3 - openai default:
whisper-1
- auto/mlx default:
--source-lang- source language code (for example
ja,fr,es) orauto(default)
- source language code (for example
--api-key- OpenAI API key (alternative to
OPENAI_API_KEY)
- OpenAI API key (alternative to
--max-line-chars- target max characters per line (default:
42)
- target max characters per line (default:
--max-lines- max lines per cue (default:
2)
- max lines per cue (default:
--max-cps- target max reading speed in characters per second (default:
20.0)
- target max reading speed in characters per second (default:
--min-duration- minimum cue duration in seconds (default:
1.0)
- minimum cue duration in seconds (default:
--max-duration- maximum cue duration in seconds (default:
6.0)
- maximum cue duration in seconds (default:
--ffmpeg-bin- ffmpeg executable name/path (default:
ffmpeg)
- ffmpeg executable name/path (default:
--device- local
faster-whisperdevice:auto,cpu, orcuda(default:auto) - torch
openai-whisperdevice:auto,cpu,cuda, ormps
- local
--compute-type- local
faster-whispercompute type (default:auto)
- local
--quiet- disable progress/status messages
By default, the CLI prints status updates to stderr:
- audio extraction start/finish
- transcription start/finish
- periodic segment progress (local backend)
- cue generation and file write
This is intended to show activity during long files/model initialization.
- Local backend calls Whisper with
task="translate"(transcribe + translate to English in one pass). - MLX backend calls Whisper with
task="translate"(transcribe + translate to English in one pass). - Torch backend calls OpenAI Whisper with
task="translate"(transcribe + translate to English in one pass). - OpenAI backend uses the audio translation endpoint.
- There is no separate post-translation step.
- On Apple Silicon with
--backend auto, default model ismlx-community/whisper-large-v3-mlx. - On non-Apple systems (or
--backend local), default model islarge-v3. - On
--backend torch, default model islarge-v3and device can bempson Apple Silicon. - You can trade speed for accuracy with
--model mediumor smaller. - First use of a local model may take longer due to model download.
- If language auto-detection is wrong, pass
--source-langexplicitly (for exampleja,ko,fr). - MLX backend also accepts short aliases like
large-v3,medium,small, andturbo.
Use one of:
source .venv/bin/activate
srt-gen input.mp4or
.venv/bin/srt-gen input.mp4or
python -m srt_gen input.mp4Install ffmpeg/ffprobe and ensure they are discoverable:
ffmpeg -version
ffprobe -versionExpected on first run for a model: weights are downloaded/cached.
If you see loops like the the the the, it is usually a decoding issue from the speech model (not SRT formatting).
What helps:
- Keep
--source-langexplicit when auto-detection is unreliable. - Try a stronger model (
--model large-v3for local, ormlx-community/whisper-large-v3-mlxon Apple Silicon). - Try another backend (
--backend localvs--backend mlxvs--backend torch) for the same file. - Improve audio quality before transcription (reduce background noise/music where possible).
srt_gen also applies a conservative cleanup pass that removes obvious single-word loops (3+ repeated words in a row) from backend text.
Set key in environment or pass --api-key:
export OPENAI_API_KEY=your_key_hereTune:
--max-line-chars--max-lines--max-cps--min-duration--max-duration
srt_gen/
cli.py
media.py
segmentation.py
srt_writer.py
backends/
base.py
local_whisper.py
mlx_whisper.py
torch_whisper.py
openai_api.py
python -m compileall srt_gen
python -m srt_gen --help