Skip to main content
MKVPriority Banner

Docker Release PyPI Release Python CI

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.

Features

  • 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)
  • Identifies forced subtitle tracks using dialogue-density heuristics without relying solely on track names
  • Suppresses default flags during native audio playback to prevent unnecessary subtitles for dialogue
  • 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 to handle specialized workflows

Docker Image

A Docker image is provided to simplify the installation process and enable quick deployment.

docker run --rm -v /path/to/media:/media ghcr.io/kennethsible/mkvpriority /media

Use a Custom Config

You 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/kennethsible/mkvpriority /media \
  --config /config/custom.toml

Use an Archive Database

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/kennethsible/mkvpriority /media \
  --archive /config/archive.db

TOML Configuration

All 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 (see here).

Override Config Rules

You can override config rules dynamically without modifying your TOML files using the --override argument. This is designed to address edge cases with non-standard or mislabeled metadata. CLI overrides use dot notation (section.key=value) and automatically parse values (numbers, booleans, strings, etc.)

docker run --rm -u ${PUID}:${PGID} \
  -v /path/to/media:/media \
  -v /path/to/mkvpriority/config:/config \
  ghcr.io/kennethsible/mkvpriority /media \
  --override 'subtitle_profiles.global.languages.mul=70' \
  --override 'subtitle_profiles.dialogue.filters.yellow=-10000'

Example: Subtitle Codecs

[subtitle_profiles.global.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)

Radarr/Sonarr Integration

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).

mkvpriority:
  image: ghcr.io/kennethsible/mkvpriority
  container_name: mkvpriority
  user: ${PUID}:${PGID}
  environment:
    WEBHOOK_PORT: "8080"
    MKVPRIORITY_ARGS: >
      --archive /config/archive.db
  volumes:
    - /path/to/media:/media
    - /path/to/mkvpriority/config:/config
  ports:
    - 8080:8080
  restart: unless-stopped

Use Multiple Configs

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/kennethsible/mkvpriority
  container_name: mkvpriority
  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
  ports:
    - 8080:8080
  restart: unless-stopped

Cron Scheduler

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/kennethsible/mkvpriority
  container_name: mkvpriority
  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-stopped

Extension Modules

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.

Example: Subtitle Extractor

You can use the subtitle_extractor extension to extract embedded subtitles flagged as default or forced. 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.

[subtitle_profiles.global]
convert_external_subtitles = true
Format:  {filename}.{language}.{default,forced}.{srt,ass}
Example: Princess Mononoke (1997).eng.default.ass

Example: Subtitle Converter

You can use the subtitle_converter extension to convert external subtitles between formats. Converting styled subtitles (.ass) to plain text (.srt) prevents server transcoding on devices with limited subtitle support. Conversely, converting plain text subtitles to stylized allows you to chain this module with the subtitle_restyler extension to apply advanced typography and consistent styling across your library.

[subtitle_profiles.global]
convert_target_format = "ass"
convert_remove_source = false

Example: Subtitle Restyler

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.5

Example: Multiplexer (Strip/Reorder Tracks)

You can use the multiplexer extension to strip tracks for unwanted languages and reorder tracks by priority scores. Since remuxing conflicts with the core "no-remux" design, these features are delegated to an extension module. To enable them, add the [multiplexer] section to your config file and include this extension in your arguments.

[multiplexer]
strip_tracks = true
reorder_tracks = true
remux_audio_profile = "default"
remux_subtitle_profile = "dialogue"
mkvmerge_arguments = []

Creating Extensions

You can easily write your own post-processing scripts to handle custom logic.

  1. 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 for pip)
    • /config/extensions (recommended for Docker)
  2. Import the Extension class and implement the process_file method:

    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
    
  3. Use -i/--include with the script name (without the .py extension):

    mkvpriority -i my_extension
    

CLI Usage

MKVToolNix must be installed on your system unless you are using the Docker image.

usage: mkvpriority [-h] [-c TOML_PATH[::TAG]] [-a DB_PATH] [-i MODULE_NAME] [-o KEY=VALUE] [-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
  -o, --override KEY=VALUE
                        override config settings
  -v, --verbose         inspect track metadata
  -x, --debug           print mkvtoolnix output
  -q, --quiet           suppress normal logging
  -p, --prune           prune database entries
  -n, --dry-run         simulate track changes
  -r, --restore         restore original flags

Python Package

To install the standalone CLI tool (without Docker), you can use pip:

pip install mkvpriority

To keep the CLI tool isolated from your environment, you can use uv:

uv tool install 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).

Release files for mkvpriority 2.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mkvpriority 2.1.0
File Size Uploaded
mkvpriority-2.1.0.tar.gz 100.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for mkvpriority 2.1.0
File Interpreter ABI Platform
mkvpriority-2.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 129.0 kB

Release files / mkvpriority-2.1.0.tar.gz

Download URL mkvpriority-2.1.0.tar.gz
Size 100.4 kB
Tags Source
SHA-256 checksum
How to use checksums
8c055f7c8e26fdb43971d6a9856252418594ab85ab4198826ed358bc9c53d0d2
BLAKE2b-256 checksum
How to use checksums
692edbf5ac9d0a4966a60201facf9c39718d8f89e21720b0d05b3dc9bebb7dcf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","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 / mkvpriority-2.1.0-py3-none-any.whl

Download URL mkvpriority-2.1.0-py3-none-any.whl
Size 28.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4cd9d326a6118425607846e5247a852ddf7bb7ffd167e70c0a100ea83724bd32
BLAKE2b-256 checksum
How to use checksums
144c1dad8c66c0ca7c7dad1d7b4480a415e334d7fba117ceb69cef254ee2b494
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","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 history Release notifications | RSS feed

2.2.0

2 release files

This release

2.1.0 This release

2 release files

2.0.0

2 release files

1.5.2

2 release files

1.5.1

2 release files

1.5.0

2 release 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