SimpleSubGen
Generate and translate subtitles locally for a media library.
Media libraries often lack subtitles in the required languages. Selecting tracks, extracting audio and transcribing manually does not scale across an expanding library.
My contribution
How it worksDesigned and implemented the scanning, track selection, SQLite job state, worker orchestration, GPU-backed inference, optional translation and SRT output; published the application as a Docker image.
On startup, jobs left in processing return to pending so interrupted files can be queued again.
def recover_stale_jobs(self):
with self.session_factory() as session:
jobs = session.query(SubtitleJob).filter(SubtitleJob.status == PROCESSING).all()
for job in jobs:
job.status = PENDING
job.error = "Recovered after restart"
session.commit()How it works
A Python application, published as a Docker image, that scans media folders, ranks audio tracks, runs local transcription with faster-whisper and optionally translates subtitles with NLLB before writing SRT sidecar files.
- Media scannerFind video files and determine work to queue
- SQLite job queuePersist state and recover interrupted jobs
- FFprobe + FFmpegRank tracks and extract audio
- Whisper inferenceDetect language when needed and transcribe
- NLLB + SRT outputOptionally translate, then write sidecars
Engineering decisions
Audio selection before inference
Score tracks using language preferences, defaults, original-audio signals and codec information; penalize commentary and descriptive tracks.
Recoverable processing
Keep pending, processing, completed, failed and skipped states in SQLite; reset stale processing jobs after restarts.
Local model execution
Run transcription and conditional translation on a supported NVIDIA GPU without relying on a remote inference API.
Subtitle timings
Apply reading-speed and duration heuristics before writing timestamped SRT files beside the source media.