Skip to main content

Movie subtitles

CI Publish PyPI Python versions License: MIT Ruff

Command line tool that turns a video or audio file into a translated .srt file, and optionally into a dubbed video with a synthesised translated audio track.

Installation

Published on PyPI as movie-subtitles.

# Run without installing (recommended)
uvx movie-subtitles --input clip.mp4

# Install as a tool
uv tool install movie-subtitles

# Or with pip
pip install movie-subtitles

# Latest from git instead of the release on PyPI
uvx --from git+https://github.com/mathiasesn/movie-subtitles.git movie-subtitles --input clip.mp4

# Develop locally
git clone https://github.com/mathiasesn/movie-subtitles.git
cd movie-subtitles && uv sync && uv run movie-subtitles --help

Requires Python >= 3.10 and uv. ffmpeg must be on PATH for --dub; the plain .srt path and --managed do not need it.

Engines

The pipeline has three stages, each backed by a vendor you choose independently:

Flag Values
--asr-engine local (faster-whisper large-v3), elevenlabs (Scribe), openai (whisper-1)
--translation-engine local (MADLAD400), anthropic (Claude), openai (chat completions)
--tts-engine elevenlabs, openai (tts-1)

--engine is a shorthand that sets all three at once; per-stage flags always override it.

Invocation ASR Translation TTS
--engine local (default) faster-whisper MADLAD400 none
--engine openai OpenAI OpenAI OpenAI
--engine elevenlabs Scribe error ElevenLabs
--engine elevenlabs --translation-engine anthropic Scribe Claude ElevenLabs

--engine elevenlabs alone errors on purpose. ElevenLabs has no standalone text-translation endpoint — translation exists only bundled inside the Dubbing job (--managed) — so there is nothing honest for the shorthand to resolve the translation stage to. Pass --translation-engine {anthropic,openai,local} explicitly.

Engine values name vendors, not pipelines. An earlier version used --translation-engine elevenlabs; that value no longer exists, and its replacement is --translation-engine anthropic, since the call was always Claude.

Known limitation: --asr-engine openai

whisper-1's segment timestamps degrade to uniform 1.000s spans on music-heavy or dialogue-sparse audio (observed on a movie trailer), which corrupts both .srt cue timings and dub slots. Prefer --asr-engine elevenlabs on such material.

API keys

--engine local needs no keys and stays fully offline after the first model download. Everything else reads one or more of:

export ELEVENLABS_API_KEY="..."   # --asr-engine/--tts-engine elevenlabs, --managed
export ANTHROPIC_API_KEY="..."    # --translation-engine anthropic
export OPENAI_API_KEY="..."       # any stage set to openai

Or copy .env.example to .env and fill it in — .env is gitignored and loaded on startup, searching upward from the directory you run in. Exported variables take precedence. A missing key exits with a one-line error naming the variable, no traceback.

Usage

# Local, offline, .srt only
movie-subtitles --input clip.mp4

# ElevenLabs ASR + Claude translation, .srt only
movie-subtitles --input clip.mp4 --engine elevenlabs --translation-engine anthropic

# ...and dubbed into clip.dubbed.mp4 (needs ffmpeg)
movie-subtitles --input clip.mp4 --engine elevenlabs --translation-engine anthropic --dub

# OpenAI end to end, .srt only / dubbed
movie-subtitles --input clip.mp4 --engine openai
movie-subtitles --input clip.mp4 --engine openai --dub

# Mixed vendors — Scribe ASR, OpenAI translation and voice
movie-subtitles --input clip.mp4 --asr-engine elevenlabs --translation-engine openai --tts-engine openai --dub

# Managed ElevenLabs Dubbing job — no local ASR/MT/TTS code runs at all
movie-subtitles --input clip.mp4 --managed

Other flags: --audio-lang, --srt-lang, --whisper-model, --mt-model. Run movie-subtitles --help for the full list.

Dubbing notes

  • --dub replaces the original audio track, it does not mix with it. Only the synthesised track is mapped onto the source video; the original spoken audio is dropped.

  • --dub and --managed are mutually exclusive. --managed replaces the whole pipeline with a single hosted job.

  • --dub fails if TTS resolves to something unusable, e.g. plain --engine local --dub, since local has no TTS backend:

    [ERROR][cli] --dub requires a usable TTS engine, but it resolved to 'local'. Pass --tts-engine {elevenlabs,openai} explicitly.
    
  • --translation-engine local with --dub is allowed but warns. MADLAD400 ignores the length budget, so timing-drift fitting degrades to TTS-rate-only.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

movie_subtitles-0.1.0.tar.gz (190.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

movie_subtitles-0.1.0-py3-none-any.whl (25.8 kB view details)

Uploaded Python 3

File details

Details for the file movie_subtitles-0.1.0.tar.gz.

File metadata

  • Download URL: movie_subtitles-0.1.0.tar.gz
  • Upload date:
  • Size: 190.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for movie_subtitles-0.1.0.tar.gz
Algorithm Hash digest
SHA256 de1b65c41d767654409ac68b9b3cec0853c727ff06f682e0d81dbe96fc571a75
MD5 9947a75a10288fe4bbdd049b8bd368a0
BLAKE2b-256 434dc44c033b3befe47af38045766b766aaa705bbd365f9203674c88ce86e7dd

See more details on using hashes here.

Provenance

The following attestation bundles were made for movie_subtitles-0.1.0.tar.gz:

Publisher: publish.yml on mathiasesn/movie-subtitles

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file movie_subtitles-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: movie_subtitles-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 25.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for movie_subtitles-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 13b95281961fd6712ce1666ba8a8c211ff4e5af8bd845bc5ad7dbb84d5ab3d04
MD5 4e80529153e99e17a2275b2f0ef82c39
BLAKE2b-256 533f19c0d331b9b848385929c3afe00616e74622109bc2e6f874a8ce815a13f2

See more details on using hashes here.

Provenance

The following attestation bundles were made for movie_subtitles-0.1.0-py3-none-any.whl:

Publisher: publish.yml on mathiasesn/movie-subtitles

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

This release

0.1.0 This release

2 files

0.0.1

2 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