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.1.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.1-py3-none-any.whl (25.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: movie_subtitles-0.1.1.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.1.tar.gz
Algorithm Hash digest
SHA256 a5343daf3e7196e55fc786529d987d86a3cd0e12d78102106c7abca72b77579b
MD5 153f6ae9ef77a930dc8aaa443162b77a
BLAKE2b-256 4fadb4f1fadcf6e4d3463e28d177a9b05d6551983a9b9bf5fbabd4d9da6c28c8

See more details on using hashes here.

Provenance

The following attestation bundles were made for movie_subtitles-0.1.1.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.1-py3-none-any.whl.

File metadata

  • Download URL: movie_subtitles-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 25.9 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 13029d1bca8b359dff8d1cbaa99cf7df5b0ee98bb7ec76b757c2a4f918f8d1be
MD5 2dfa5dd82f3c8365330350039013972b
BLAKE2b-256 0b8ba84b4324784cf612cc86f011827458d7d837ac05993af75e3e6579b16f63

See more details on using hashes here.

Provenance

The following attestation bundles were made for movie_subtitles-0.1.1-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

This release

0.1.1 This release

2 files

0.1.0

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