Metadata-Version: 2.5
Name: media-organizer-cli
Version: 0.1.0
Summary: Universal TV Show Episode Renamer & Lossless MKV Remuxer
Author-email: Abdullah AbuOun <abdullah.h.oun@gmail.com>
License-File: LICENSE
Requires-Python: >=3.10
Requires-Dist: httpx>=0.28.1
Requires-Dist: rich>=15.0.0
Requires-Dist: typer>=0.27.1
Description-Content-Type: text/markdown

# Media Organizer

[![CI](https://github.com/Abdullah-AboOun/media-organizer/actions/workflows/ci.yml/badge.svg)](https://github.com/Abdullah-AboOun/media-organizer/actions/workflows/ci.yml)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/)
[![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

> 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](#about-the-project)
  - [The Problem](#the-problem)
  - [The Solution](#the-solution)
- [Built With](#built-with)
- [Getting Started](#getting-started)
  - [Prerequisites](#prerequisites)
  - [Installation](#installation)
- [Usage & Examples](#usage--examples)
  - [1. Safe Dry-Run Simulation](#1-safe-dry-run-simulation)
  - [2. Rename Files & Season Folders](#2-rename-files--season-folders)
  - [3. Lossless MKV Remuxing](#3-lossless-mkv-remuxing)
  - [4. Auto-Download Subtitles & Cleanup Sources](#4-auto-download-subtitles--cleanup-sources)
  - [5. Subtitle Inspection & Repair](#5-subtitle-inspection--repair)
  - [6. Recursive Batch Processing](#6-recursive-batch-processing)
  - [CLI Flags Reference](#cli-flags-reference)
- [Roadmap](#roadmap)
- [Contributing](#contributing)
- [License](#license)
- [Acknowledgements](#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:
1. **Identifies Shows & Seasons**: Handles full titles, common acronyms (`GOT`, `HOTD`, `BCS`, `BB`, `TWD`, etc.), and multi-part episodes (`S01E01-E02`).
2. **Fetches Official Metadata**: Queries TVmaze API for official episode titles.
3. **Repairs Subtitles**: Auto-detects text encodings (UTF-8, UTF-16, CP1252, ISO-8859-1) and fixes corrupted musical note characters in-place.
4. **Classifies Tracks**: Sorts subtitles into `English`, `English [SDH]`, and `English [Forced]` with proper default/forced stream dispositions.
5. **Downloads Missing Subtitles**: Matches release groups against the SubDL database to guarantee audio-subtitle synchronization.
6. **Lossless Remuxing**: Uses FFmpeg stream copying to package video, audio, and subtitles into clean MKVs in seconds without quality loss or re-encoding.
7. **Release Log**: Preserves original release tags in `release_info.txt` so you never lose source details.

---

## Built With

- [Python](https://www.python.org/) (>= 3.10)
- [uv](https://docs.astral.sh/uv/) - Fast package and dependency management
- [Typer](https://typer.tiangolo.com/) - Type-driven CLI framework
- [Rich](https://rich.readthedocs.io/) - Terminal tables, status panels, and dashboard UI
- [HTTPX](https://www.python-httpx.org/) - HTTP client for API metadata and subtitle downloads
- [FFmpeg](https://ffmpeg.org/) - Stream copy and container remuxing

---

## Getting Started

### Prerequisites

1. **Python 3.10+**: Ensure Python is installed on your system.
2. **FFmpeg**: Must be installed and accessible in your system `PATH` (or standard Windows install paths).
3. **uv**: Recommended for running and installing Python packages.
   ```bash
   # 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)
```bash
pip install media-organizer-cli
```

#### Option B: Clone & Run Locally
1. Clone the repository:
   ```bash
   git clone https://github.com/Abdullah-AboOun/media-organizer.git
   cd media-organizer
   ```

2. Install dependencies with uv:
   ```bash
   uv sync
   ```

3. (Optional) Install locally as a tool:
   ```bash
   uv tool install .
   ```

---

## Usage & Examples

### 1. Safe Dry-Run Simulation
Preview planned file and folder changes without writing or modifying anything:
```bash
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`):
```bash
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):
```bash
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:
```bash
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:
```bash
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:
```bash
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

- [x] Lossless MKV Remuxing & stream tagging
- [x] Subtitle character encoding detection & music note repair
- [x] SubDL API subtitle auto-fetching with release match scoring
- [x] TVmaze API official episode title fetching
- [x] 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!

1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
3. Format and lint your changes (`uv run ruff check .` and `uv run ruff format .`)
4. Run tests (`uv run pytest`)
5. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
6. Push to the Branch (`git push origin feature/AmazingFeature`)
7. Open a Pull Request

---

## License

Distributed under the MIT License. See `LICENSE` for more information.

---

## Acknowledgements

- [TVmaze API](https://www.tvmaze.com/api) - Free, public TV metadata database
- [SubDL](https://subdl.com/) - Subtitle database API
- [FFmpeg](https://ffmpeg.org/) - Cross-platform multimedia framework
- [Chingu](https://medium.com/chingu) - Community and documentation guides
