Nudebomb
Nudebomb recursively strips MKV (Matroska) files of unwanted audio and subtitle tracks, keeping only the languages you specify.
Installation
Requirements
- MKVToolNix — provides the
mkvmergebinary. Available via Homebrew, apt, or your favorite package manager.
Run nudebomb doctor to check that nudebomb can find mkvmerge and
reach the online lookup services.
Install
pip install nudebomb
Or with uv:
uv tool install nudebomb
Quick Start
Strip all non-English tracks from a directory tree:
nudebomb -rl eng /mnt/movies
Keep English and French, recurse, and use timestamps to skip already-processed files:
nudebomb -rtl eng,fra /mnt/movies
Dry run on a single file to preview what would be stripped:
nudebomb -dvvl eng movie.mkv
Stripping languages except eng, und.
Searching for MKV files to process:
Checking movie.mkv
audio: 1 eng
audio: 2 eng
audio: 3 eng
subtitles: 4 eng
subtitles: 5 eng
Already stripped movie.mkv
done.
Usage
nudebomb [options] path [path ...]
Paths can be individual MKV files or directories. Use -r to recurse into
directories.
Doctor
nudebomb doctor [options] [path ...]
Checks nudebomb's external dependencies and exits: whether mkvmerge runs and
which version it is, whether the TMDB and TVDB API keys are accepted, and
whether the lookup cache directory is writable. Then it lists the nudebomb and
Python versions, the config file it read, and the installed library versions.
It takes the same options as a run and resolves config the same way, so put
doctor in front of your usual command line to check exactly what that run
would use:
nudebomb doctor -rtl eng -m tv /mnt/tv
Paths are not walked. Instead, doctor reports what the next run would make of
each tree's timestamps file: how many entries it holds and when it was written,
or that the run will discard it because the config changed (and which options
changed), or that an interrupted run left a write-ahead log behind. The
comparison is against the command line as given, so leaving out -l reports
languages as changed. Per-directory .nudebomb.yaml overrides are not yet
applied to the other checks.
Doctor never writes files: -w, -W, and --write-config-file are ignored
with a warning. It exits 1 if any check fails and 0 otherwise, so
nudebomb doctor && nudebomb … works in scripts.
With -q, doctor prints only warnings and failures, and nothing at all when
everything is fine, which suits cron. As with any option, verbose: 0 in a
config file or NUDEBOMB_NUDEBOMB__VERBOSE=0 has the same effect, and -v
brings the full report back.
A directory named doctor in the current directory must be passed as
./doctor.
Configuration
Nudebomb is configured through four layers, each overriding the previous:
- User config file —
~/.config/nudebomb/config.yaml - Directory config files —
.nudebomb.yamlin a target directory (see Directory Config Files) - Environment variables
- Command-line arguments
Config File
nudebomb:
languages:
- eng
- und
recurse: true
timestamps: true
media_type: movie
tmdb_api_key: your-api-key-here
tvdb_api_key: your-api-key-here
All command-line options have config file equivalents.
Use -c INPUT to supply an input config file. It replaces your default user
config for that run (the packaged defaults still apply beneath it).
Nudebomb can also write your invoked options back out as config, then run normally:
-w/--write-configwrites them to your user config file, located automatically — no path needed.-c base.yaml -wderives your user config frombase.yamlplus the options you gave.-W/--write-dir-configwrites or updates a.nudebomb.yamlin each target directory (see Directory Config Files).--write-config-file PATHwrites to a specific file (advanced), merging-c INPUT(or the existingPATH) with your options.
Existing keys and comments are preserved. Run-mode flags (--dry-run and
verbosity) are not persisted, and files are written owner-readable only since
they may hold API keys. -W persists whatever you invoked, so omit API keys you
don't want stored in a media tree.
Environment Variables
Prefix with NUDEBOMB_NUDEBOMB__. List items are enumerated:
export NUDEBOMB_NUDEBOMB__RECURSE=True
export NUDEBOMB_NUDEBOMB__LANGUAGES__0=eng
export NUDEBOMB_NUDEBOMB__LANGUAGES__1=fra
export NUDEBOMB_NUDEBOMB__TMDB_API_KEY=your-api-key-here
Directory Config Files
Drop a .nudebomb.yaml in any target directory to override settings for that
directory and everything beneath it. Write one by hand, or run with
-W/--write-dir-config to save your invoked options into each target
directory. It uses the same nudebomb: format as the user config:
# /mnt/anime/.nudebomb.yaml
nudebomb:
sub_languages:
- jpn
title: false
media_type: tv
Discovery. For each MKV, nudebomb walks up the tree from the file's
directory to the path you named on the command line (never above it, exactly
like lang files), collecting every .nudebomb.yaml it
finds. A config outside the paths you pass never affects a run.
Layering. Directory configs sit above your user config but below environment
variables and command-line options, so -c/CLI/env always win. A deeper
directory's config overrides a shallower one. A .nudebomb.yaml may set any
config key. Keys that select which tracks to keep (languages, sub_languages,
subtitles, strip_und_language, und_language, title, mkvmerge_bin), the
lookup media_type, the traversal knobs (ignore, recurse, symlinks), and
timestamps take effect per directory — so, for example, a Movies/ folder can
set media_type: movie and enable timestamps for itself. Run-scope keys — API
keys, lookup_workers, cache_expiry_days, after, --dry-run, and verbosity
— are read once for the whole run, so setting them in a directory config has no
per-directory effect.
Unlike lang files, a directory config's languages replaces the inherited
value (so a subtree can narrow or change the keep-set); lang files still add on
top of whatever it resolves to.
Timestamps. When timestamps are on (globally with -t/--timestamps, or for
a directory via its config), editing, adding, or removing a .nudebomb.yaml
re-processes its directory tree on the next run, so a config change never leaves
stale files behind. Re-checking an already-stripped file is a fast no-op.
nudebomb doctor with your usual options and paths shows whether the
next run will keep or discard each tree's timestamps.
Lang Files (deprecated)
Deprecated. Lang files are superseded by Directory Config Files. Nudebomb now migrates them automatically: on each run it rewrites every lang file it walks into a
.nudebomb.yaml(creating one, or adding the languages to an existing one) and deletes the lang file. The migrated config records the directory's full effective keep-set, so results don't change. Dry runs (--dry-run) migrate nothing.
Lang files let you specify additional languages to keep on a per-directory basis. This is useful when your collection spans multiple languages — you want most content to keep English, but a specific show to also keep Japanese.
How They Work
Place a file named lang, langs, .lang, or .langs in any directory. The
file contains a comma-separated list of ISO 639 language codes:
jpn
Nudebomb walks up the directory tree from each MKV file, collecting languages
from every lang file it finds. The final set of languages to keep is the union
of --languages, all lang file languages from the current directory up to the
top-level path, and any online lookup results.
Example
/mnt/tv/
.lang # contains: eng
GI Robot/
Season 1/
episode.mkv # keeps: eng, und
Anime Show/
.lang # contains: jpn
Season 1/
episode.mkv # keeps: eng, jpn, und
Online Language Lookup
When no lang files contribute additional languages for a file, nudebomb can look up the original language of the media from online databases and add it to the languages to keep. This requires an API key.
TMDB (The Movie Database)
Works for both movies and TV series. Get an API key at themoviedb.org.
nudebomb -rl eng --tmdb-api-key YOUR_KEY --media-type movie /mnt/movies
TVDB (TheTVDB)
Specialized for TV series. Get an API key at
thetvdb.com. When both keys are
configured and --media-type tv is set, TVDB is tried first for TV content.
nudebomb -rl eng --tvdb-api-key YOUR_KEY --media-type tv /mnt/tv
Filename Parsing
Nudebomb parses media filenames to extract titles, years, and database IDs. For best results, use standard naming conventions:
- Movies:
Movie Title (2024).mkvorMovie.Title.2024.BluRay.mkv - TV:
Show Name S01E02.mkvorShow.Name.1x02.mkv
You can embed database IDs in curly braces for exact matching:
{tmdb-696}— TMDB ID{imdb-tt022345}— IMDB ID (looked up via TMDB){tvdb-5780}— TVDB ID
Example: {tvdb-1234} S01E01.mkv
Caching
Lookup results are cached in ~/.cache/nudebomb/ to avoid redundant API calls.
Cache entries with a found language expire after a year. Entries where no
language was found expire after --cache-expiry-days (default: 30) and are
re-queried.
Dot Color Key
When running at default verbosity, nudebomb prints single characters to indicate progress:
| Char | Meaning |
|---|---|
. |
MKV skipped (ignored, already stripped, or cache hit) |
. (green) |
Skipped because timestamp unchanged |
O |
Online lookup succeeded |
x |
Online lookup returned no result |
X |
Online lookup error or rate limited |
Use -vv for full text descriptions instead of dots.
Development
Source code is hosted at GitHub.
Inspiration
Nudebomb is a radical fork of mkvstrip. It adds recursion, lang files, timestamps, online language lookup, and more configuration options.
Metadata
Release files for nudebomb 1.8.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nudebomb-1.8.0.tar.gz | 5.4 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nudebomb-1.8.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 5.4 MB
Release files / nudebomb-1.8.0.tar.gz
| Download URL | nudebomb-1.8.0.tar.gz |
|---|---|
| Size | 5.4 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
633a67ff48cfe874e8bfc14835719b720611fd178967a4f0f385e4f6f6e85f36
|
|
BLAKE2b-256 checksum How to use checksums |
22a67401ff16939c8445bbcdc671996f6ed1f05aa8e177ade280aebe8b43b38e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / nudebomb-1.8.0-py3-none-any.whl
| Download URL | nudebomb-1.8.0-py3-none-any.whl |
|---|---|
| Size | 70.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a58b92afe75e8f5b8f6f3423a6412f296c411b66cc64a1a958d05e45fb61d76f
|
|
BLAKE2b-256 checksum How to use checksums |
1f2749cfbf016c8b4d8407ddee68dee542805283974488b51dcf9ab4b39de981
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|