Media Organizer
A fast, lightweight CLI tool to automatically organize TV show episodes, clean and synchronize subtitles, and remux lossless MKV containers for media servers.
Table of Contents
- About The Project
- Built With
- Getting Started
- Usage & Examples
- Roadmap
- Contributing
- License
- Acknowledgements
About The Project
Managing downloaded TV shows for home media servers (like Plex, Jellyfin, or Emby) often involves repetitive and frustrating manual cleanup:
- Video files and parent folders come with messy release names (e.g.
Show.Name.S01E01.1080p.WEB-DL.DDP5.1.Atmos.H.264-FLUX). - Subtitles have broken character encodings (corrupted music symbols like
J“instead of♪). - Multiple subtitle tracks are unclassified or loose in separate folders.
- Missing official episode titles.
The Problem
Media servers rely on clean naming conventions (like Show Name Season 01/Show Name - S01E01 - Title.mkv) to match metadata reliably. Fixing dozens of episodes and subtitles manually takes unnecessary time.
The Solution
Media Organizer automates this entire pipeline in a single command:
- Identifies Shows & Seasons: Handles full titles, common acronyms (
GOT,HOTD,BCS,BB,TWD, etc.), and multi-part episodes (S01E01-E02). - Fetches Official Metadata: Queries TVmaze API for official episode titles.
- Repairs Subtitles: Auto-detects text encodings (UTF-8, UTF-16, CP1252, ISO-8859-1) and fixes corrupted musical note characters in-place.
- Classifies Tracks: Sorts subtitles into
English,English [SDH], andEnglish [Forced]with proper default/forced stream dispositions. - Downloads Missing Subtitles: Matches release groups against the SubDL database to guarantee audio-subtitle synchronization.
- Lossless Remuxing: Uses FFmpeg stream copying to package video, audio, and subtitles into clean MKVs in seconds without quality loss or re-encoding.
- Release Log: Preserves original release tags in
release_info.txtso you never lose source details.
Built With
- Python (>= 3.10)
- uv - Fast package and dependency management
- Typer - Type-driven CLI framework
- Rich - Terminal tables, status panels, and dashboard UI
- HTTPX - HTTP client for API metadata and subtitle downloads
- FFmpeg - Stream copy and container remuxing
Getting Started
Prerequisites
- Python 3.10+: Ensure Python is installed on your system.
- FFmpeg: Must be installed and accessible in your system
PATH(or standard Windows install paths). - uv: Recommended for running and installing Python packages.
# Windows (PowerShell) powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" # macOS / Linux curl -LsSf https://astral.sh/uv/install.sh | sh
Installation
Option A: Install from PyPI (Global CLI tool)
pip install media-organizer-cli
Option B: Clone & Run Locally
-
Clone the repository:
git clone https://github.com/Abdullah-AboOun/media-organizer.git cd media-organizer
-
Install dependencies with uv:
uv sync -
(Optional) Install locally as a tool:
uv tool install .
Usage & Examples
1. Safe Dry-Run Simulation
Preview planned file and folder changes without writing or modifying anything:
uv run media-organizer -i "D:/Downloads/HOTD.S01.1080p" -r -n
2. Rename Files & Season Folders
Renames video files, subtitle files, and the parent folder to standard Media Server format (House of the Dragon Season 01):
uv run media-organizer -i "D:/Downloads/HOTD.S01.1080p" -r
3. Lossless MKV Remuxing
Merges video and loose .srt files into self-contained .mkv files with proper subtitle tags (default mode):
uv run media-organizer -i "D:/Downloads/House.of.the.Dragon.S01" -m
4. Auto-Download Subtitles & Cleanup Sources
Downloads matching subtitles from SubDL if missing, embeds them into MKV files, and cleans up raw source files:
uv run media-organizer -i "D:/Downloads/Breaking.Bad.S01" -m -D -d
5. Subtitle Inspection & Repair
Inspects loose .srt files and embedded subtitle tracks in existing .mkv files, repairing character artifacts in-place:
uv run media-organizer -i "D:/Media/TV Shows/Breaking Bad Season 01" -c
6. Recursive Batch Processing
Recursively organizes multiple shows and seasons in a folder up to 2 directory levels deep:
uv run media-organizer -i "D:/Downloads/Unsorted" -R --depth 2 -m -k
CLI Flags Reference
| Option | Flag | Description | Default |
|---|---|---|---|
--input <path> |
-i |
Input folder containing episodes | . |
--output <path> |
-o |
Output directory destination | Parent folder |
--remux |
-m |
Remux video + subtitles into lossless MKV | True (default mode) |
--rename-only |
-r |
Rename files and folder without remuxing | False |
--clean-subs |
-c |
In-place subtitle inspection and repair | False |
--download-subs |
-D |
Auto-download missing subtitles via SubDL | False |
--lang <code> |
Language for downloaded subtitles | en |
|
--delete-source |
-d |
Delete source files after successful remux | False |
--skip-existing |
-k |
Skip episodes already present in destination | False |
--dry-run |
-n |
Preview planned actions without modifying disk | False |
--recursive |
-R |
Recursively scan subdirectories for seasons | False |
--depth <num> |
Maximum directory depth for recursion | 2 |
|
--show <name> |
-s |
Manually specify / override show name | Auto-detected |
--season <num> |
Manually specify / override season number | Auto-detected | |
--in-place |
Keep original folder name unchanged | False |
|
--no-log |
Disable writing release_info.txt |
False |
|
--verbose |
-v |
Show all files in status tables | False |
Roadmap
- Lossless MKV Remuxing & stream tagging
- Subtitle character encoding detection & music note repair
- SubDL API subtitle auto-fetching with release match scoring
- TVmaze API official episode title fetching
- Rich terminal UI and execution summary dashboard
- Movie file renaming & remuxing support
- Anime episode numbering & release tag parser support
Contributing
Contributions, issues, and feature requests are welcome!
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature) - Format and lint your changes (
uv run ruff check .anduv run ruff format .) - Run tests (
uv run pytest) - Commit your Changes (
git commit -m 'Add some AmazingFeature') - Push to the Branch (
git push origin feature/AmazingFeature) - Open a Pull Request
License
Distributed under the MIT License. See LICENSE for more information.
Acknowledgements
- TVmaze API - Free, public TV metadata database
- SubDL - Subtitle database API
- FFmpeg - Cross-platform multimedia framework
- Chingu - Community and documentation guides
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file media_organizer_cli-0.1.0.tar.gz.
File metadata
- Download URL: media_organizer_cli-0.1.0.tar.gz
- Upload date:
- Size: 34.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3cdacbe2bb1e5517d360065e45a3849f2c8755b6ac1f1db617a2de97ea6704fd
|
|
| MD5 |
394b3f6cc4c63d29cac90910d52cfd8d
|
|
| BLAKE2b-256 |
4167dc9ebc41bd69d134e0048e59713024b456728ea1e779269ac078aefdd270
|
Provenance
The following attestation bundles were made for media_organizer_cli-0.1.0.tar.gz:
Publisher:
publish.yml on Abdullah-AboOun/media-organizer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
media_organizer_cli-0.1.0.tar.gz -
Subject digest:
3cdacbe2bb1e5517d360065e45a3849f2c8755b6ac1f1db617a2de97ea6704fd - Sigstore transparency entry: 2521295207
- Sigstore integration time:
-
Permalink:
Abdullah-AboOun/media-organizer@aef04875052458e3f4cc60587923961c97eb8b20 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Abdullah-AboOun
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@aef04875052458e3f4cc60587923961c97eb8b20 -
Trigger Event:
release
-
Statement type:
File details
Details for the file media_organizer_cli-0.1.0-py3-none-any.whl.
File metadata
- Download URL: media_organizer_cli-0.1.0-py3-none-any.whl
- Upload date:
- Size: 25.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
faa6f80ebf6c922860d4ece1e99073a80885bdb0bcb840c9c8b7c4a306c90087
|
|
| MD5 |
23743bd13683f8b77fc144a661325e80
|
|
| BLAKE2b-256 |
f422b36df72530609998b17c312fbf9cbc4d920e96bcdfe8e8a06f9aee16f0d3
|
Provenance
The following attestation bundles were made for media_organizer_cli-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on Abdullah-AboOun/media-organizer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
media_organizer_cli-0.1.0-py3-none-any.whl -
Subject digest:
faa6f80ebf6c922860d4ece1e99073a80885bdb0bcb840c9c8b7c4a306c90087 - Sigstore transparency entry: 2521296165
- Sigstore integration time:
-
Permalink:
Abdullah-AboOun/media-organizer@aef04875052458e3f4cc60587923961c97eb8b20 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Abdullah-AboOun
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@aef04875052458e3f4cc60587923961c97eb8b20 -
Trigger Event:
release
-
Statement type: