MKVPriority assigns configurable priority scores to audio and subtitle tracks, similar to custom formats in Radarr/Sonarr. MKV flags, such as default and forced, are automatically set for the highest-priority tracks (e.g., 5.1 surround and ASS subtitles), while lower-priority tracks (e.g., stereo audio and PGS subtitles) are deprioritized.
This repository is a fork of kennethsible/mkvpriority that keeps the upstream track-priority behavior and adds optional remux-focused workflows.
Important
MKVPriority modifies track flags in place using mkvpropedit by default (no remuxing), allowing media players to automatically select the best audio and subtitle tracks according to your preferences. Remuxing can optionally be enabled in the config to disable track compression or reorder tracks.
- Assigns configurable priority scores to audio and subtitle tracks (similar to custom formats in Radarr/Sonarr)
- Automatically sets default/forced flags for the highest priority tracks (e.g., Japanese audio and ASS subtitles)
- Deprioritizes unwanted audio and subtitle tracks (e.g., English dubs, commentary tracks, signs/songs)
- Optionally remuxes changed files with
mkvmerge --compression -1:noneto disable track compression - Optionally remuxes files to place video tracks first, then audio/subtitle tracks by score
- Periodically scans your media library using a cron schedule and processes new MKV files with a database
- Integrates with Radarr and Sonarr using a custom script to process new MKV files as they are imported
- Supports extension modules for optional, user-defined post-processors, allowing for edge-case handling
A Docker image is provided to simplify the installation process and enable quick deployment.
docker run --rm -v /path/to/media:/media ghcr.io/nothing2obvi/mkvpriority-remux /mediaYou can specify your own preferences by creating a custom TOML config that defines track filters by name and assigns scores by property. To override the default config, use a bind mount:
docker run --rm -u ${PUID}:${PGID} \
-v /path/to/media:/media \
-v /path/to/mkvpriority/config:/config \
ghcr.io/nothing2obvi/mkvpriority-remux /media \
--config /config/custom.tomlImportant
Before starting the Docker container, you should pre-create the config folder on the host. Otherwise, Docker will create the folder as the root user, causing Python to raise a PermissionError.
You can periodically process your media library using a cron job and an archive database. To keep track of processed files, create an archive.db file and use a bind mount:
docker run --rm -u ${PUID}:${PGID} \
-v /path/to/media:/media \
-v /path/to/mkvpriority/config:/config \
ghcr.io/nothing2obvi/mkvpriority-remux /media \
--archive /config/archive.dbAll behavior is configured through TOML files, which assign priority scores to track properties, such as languages and codecs, and define custom filters for track names, such as "signs" and "songs." To get started, check the example TOML file that has been provided for anime (see here).
You can enable optional remux steps that run after audio and subtitle flags are changed:
remux_disable_compression = true
remux_reorder_tracks = trueWhen remux_disable_compression is enabled, MKVPriority rewrites the MKV with mkvmerge --compression -1:none after track flags are changed. This disables Matroska track compression, which can improve compatibility with clients that do not handle compressed tracks well.
When remux_reorder_tracks is enabled, MKVPriority changes the track order according to calculated scores: video tracks stay first, audio tracks are ordered from highest score to lowest score, and subtitle tracks are ordered from highest score to lowest score. If the current track order already matches that score order, MKVPriority skips the reorder remux.
If both options are enabled and both operations are needed, MKVPriority performs one shared mkvmerge remux instead of rewriting the file twice. The remux is written to a temporary file in the same directory, then replaces the original MKV only after mkvmerge succeeds. These remux steps do not run during --restore, and they are logged through the mkvmerge logger. In --dry-run mode, MKVPriority logs the command it would run without remuxing the file.
Important
These options rewrite and replace the MKV file, so they break hardlinks and require enough free disk space for a temporary copy of the file.
[subtitle_codecs]
"S_TEXT/ASS" = 30 # Stylized (Advanced SubStationAlpha)
"S_TEXT/SSA" = 30 # Legacy Stylized (SubStationAlpha)
"S_TEXT/UTF8" = 20 # Plain Text (SubRip/SRT)
"S_TEXT/WEBVTT" = 20 # Web-Based Video Text (Used in Streaming)
"S_HDMV/PGS" = 10 # Image-Based (Used in Blu-rays)
S_VOBSUB = 10 # Legacy Image-Based (Used in DVDs)You can process new MKV files as they are imported into Radarr/Sonarr by adding the custom script mkvpriority.sh and selecting 'On File Import' and 'On File Upgrade'. In order for Radarr/Sonarr to recognize the custom script, it must be visible inside the container. When using Radarr/Sonarr, you can assign scores to the original audio language (org).
Note
To add a custom script to Radarr/Sonarr, go to Settings > Connect > Add Connection > Custom Script.
mkvpriority:
image: ghcr.io/nothing2obvi/mkvpriority-remux
container_name: mkvpriority-remux
user: ${PUID}:${PGID}
environment:
WEBHOOK_PORT: '8080'
MKVPRIORITY_ARGS: >
--archive /config/archive.db
volumes:
- /path/to/media:/media
- /path/to/mkvpriority/config:/config
restart: unless-stoppedImportant
If you are not using "mkvpriority" as the name of your container, you will need to update it in the custom script. Also, verify that the mount point for your media directory in MKVPriority is the same as the one used by Radarr/Sonarr.
MKVPriority supports multiple, tag-based configs that can be customized to match the tagging system used in Radarr/Sonarr. For example, you can create a separate config for anime by adding an anime tag in Radarr/Sonarr either manually or via auto-tagging. Then, append the ::anime tag to the config path in the MKVPriority arguments.
mkvpriority:
image: ghcr.io/nothing2obvi/mkvpriority-remux
container_name: mkvpriority-remux
user: ${PUID}:${PGID}
environment:
WEBHOOK_PORT: '8080'
MKVPRIORITY_ARGS: >
--config /config/anime.toml::anime
--archive /config/archive.db
volumes:
- /path/to/media:/media
- /path/to/mkvpriority/config:/config
restart: unless-stoppedImportant
In Radarr/Sonarr, a given movie or show can have multiple tags. However, MKVPriority only uses the first tag in alphabetical order. Therefore, you may need to create new tags specifically for MKVPriority.
You can use the built-in cron scheduler to periodically scan your media library and process MKV files. When paired with an archive database, MKVPriority will only process new files with each scan.
mkvpriority:
image: ghcr.io/nothing2obvi/mkvpriority-remux
container_name: mkvpriority-remux
user: ${PUID}:${PGID}
environment:
TZ: "America/New_York"
CRON_SCHEDULE: "0 0 * * *"
CRON_TARGET_PATHS: /media
MKVPRIORITY_ARGS: >
--archive /config/archive.db
volumes:
- /path/to/media:/media
- /path/to/mkvpriority/config:/config
restart: unless-stoppedNote
MKVPriority supports non-standard macros for cron expressions, such as @daily and @hourly.
MKVPriority supports user-defined extension modules for optional post-processing. This feature is designed to handle complex library edge cases, integrate your workflow with external tools, and provide an open-ended automation framework, such as automatically extracting embedded subtitles or dynamically restyling subtitle fonts.
You can use the subtitle_extractor extension to extract embedded subtitles with the highest priority score. This may result in smoother playback if your media player doesn't support certain subtitle formats. For example, if the player needs to transcode or burn in embedded subtitles, it must first demux and process the entire MKV container. To use this feature, add extract_embedded_subtitles = true to the top level of your config file and include this extension in your arguments.
Naming Format: {basename}.{language}.{default,forced}.{srt,ass}
Note
To avoid changing internal track flags and only use external subtitles, use the subtitle extractor with the --dry-run argument since subtitle extraction still runs during a dry run, which only prevents changes to the MKV container.
You can use the subtitle_restyler extension to restyle external subtitles by defining style overrides in your config file. Since this extension operates on external subtitles, it can be seamlessly chained with the subtitle extractor. To ensure this extension only restyles dialogue subtitles, it filters out styles that exceed calibrated thresholds for spatial, karaoke, and drawing tags. A complete list of restylable attributes can be found in the extension's Python script on GitHub.
[subtitle_styles]
Fontsize = 72
Bold = -1
Outline = 3.6
Shadow = 1.5You can use the multiplexer extension to strip tracks for unwanted languages and reorder tracks by priority scores. To enable it, add the [multiplexer] section to your config file and include this extension in your arguments.
[multiplexer]
strip_tracks = true
reorder_tracks = trueYou can easily write your own post-processing scripts to handle custom logic.
-
Create a Python script (e.g.,
my_extension.py) inside any of the following:- current working directory (recommend for local development)
~/.config/mkvpriority/extensions(recommended forpip)/config/extensions(recommended for Docker)
-
Import the
Extensionclass and implement theprocess_filemethod:class Extension(ABC): def __init__(self, extension_name: str | None = None): name = extension_name or self.__class__.__name__ self.extension_logger = logging.getLogger(name) @abstractmethod def process_file( self, file_path: Path, video_tracks: list[Track], audio_tracks: list[Track], subtitle_tracks: list[Track], config: Config, dry_run: bool = False, ) -> None: raise NotImplementedError
-
Use
-i/--includewith the script name (without the.pyextension):mkvpriority -i my_extension
Note
Check the extensions folder in the GitHub repository for example scripts. In addition to the subtitle extractor, there's also a subtitle restyler that lets you define style overrides in your config file, and there's a multiplexer that lets you strip tracks for languages not included in your config file (as well as reorder tracks by priority scores).
mkvtoolnix must be installed on your system for mkvpropedit (unless you are using the Docker image).
usage: mkvpriority [-h] [-c TOML_PATH[::TAG]] [-a DB_PATH] [-i MODULE_NAME] [-v] [-x] [-q] [-p] [-n] [-r] [INPUT_PATH[::TAG] ...]
positional arguments:
INPUT_PATH[::TAG] files or directories
options:
-c, --config TOML_PATH[::TAG]
-a, --archive DB_PATH
-i, --include MODULE_NAME
include extension module
-v, --verbose inspect track metadata
-x, --debug show mkvtoolnix output
-q, --quiet suppress logging output
-p, --prune prune database entries
-n, --dry-run simulate track changes
-r, --restore restore original tracks
To install the standalone CLI tool (without Docker), you can use pip:
pip install mkvpriorityTo keep the CLI tool isolated from your environment, you can use uv:
uv tool install mkvpriorityNote
If you have uv installed, you can also run MKVPriority without installing using uvx mkvpriority.
MKVPriority avoids remuxing by using mkvpropedit, but this still affects hardlinks since the metadata is modified. To avoid breaking hardlinks, use the subtitle extractor with the --dry-run argument (see here).