Skip to content

Repository files navigation

media-library-normalizer

English | Čeština

Normalize movie and TV series names for Jellyfin. Scans a media library, classifies files, validates parsed results, and looks up provider IDs from TMDb and TVDB.

Current status: This release is analysis-only. It scans, parses, validates, resolves basic provider matches, and writes review reports. Rename planning, dry-run execution, real filesystem changes, persistent approvals, and the interactive review UI are not implemented yet.

For the full project design, naming conventions, and implementation phases, see Project Description.

Requirements

  • Python 3.14 (>=3.14,<3.15)
  • uv for dependency management

Installation

git clone https://github.com/pokornyIt/media-library-normalizer.git
cd media-library-normalizer
uv sync

Quick Start

# Scan only — no API keys needed
uv run media-library-normalizer scan

# Full parse with provider lookup — requires API keys
export $(cat .env | grep -v '^#' | xargs)
uv run media-library-normalizer parse

The parse command:

  1. Scans the media library
  2. Classifies and normalizes filenames
  3. Validates parsed results
  4. Looks up provider IDs — first checks embedded IDs in folder names, then the local cache, then online APIs in this order: movie -> TMDb; tv_episode (series-level lookup) -> TMDb TV, then TVDB
  5. Writes data/workspace/reports/parse-review-report.json
  6. Writes data/workspace/reports/parse-review-report.html for human-friendly review triage
  7. Writes data/workspace/reports/unresolved-provider-report.json for items without a resolved ID
  8. Writes data/workspace/reports/unresolved-provider-report.html for human-friendly unresolved triage

Configuration

All settings are read from environment variables. Create a .env file in the project root:

# Paths
MLN_LIBRARY_PATH=./data/library
MLN_WORKSPACE_PATH=./data/workspace

# Logging
MLN_LOG_LEVEL=INFO
MLN_LOG_FORMAT=text

# Safety
MLN_DRY_RUN=true

# Provider API keys
MLN_TMDB_API_KEY=your-tmdb-api-key
MLN_TVDB_API_KEY=your-tvdb-api-key

# How often to log provider lookup progress (default: every 100 items)
MLN_PROVIDER_LOOKUP_PROGRESS_INTERVAL=100

Full environment variable reference

Variable Default Description
MLN_APP_NAME media-library-normalizer Application name used in logs
MLN_LIBRARY_PATH ./data/library Root path of the media library to scan
MLN_WORKSPACE_PATH ./data/workspace Root path for generated files
MLN_CACHE_PATH {workspace}/cache Provider ID cache directory
MLN_REPORTS_PATH {workspace}/reports Report output directory
MLN_MANIFESTS_PATH {workspace}/manifests Rename manifest directory
MLN_LOGS_PATH {workspace}/logs Log file directory
MLN_LOG_LEVEL INFO Logging level (DEBUG, INFO, WARNING, ERROR)
MLN_LOG_FORMAT text Log format (text or json)
MLN_DRY_RUN true Disable destructive operations by default
MLN_TMDB_API_KEY (none) TMDb API key for online movie lookup
MLN_TVDB_API_KEY (none) TVDB API key for online TV series lookup
MLN_PROVIDER_LOOKUP_PROGRESS_INTERVAL 100 Log progress every N items during provider lookup

TMDb API Key

  1. Register at themoviedb.org and create a free account.
  2. Go to Settings → API and copy your API Key (v3 auth).
  3. Set MLN_TMDB_API_KEY to that value.

TVDB API Key

TVDB API keys are project-based, not personal. You must register your application:

  1. Visit thetvdb.com/api-information and create an account.

  2. Click Sign Up to register a new project and fill in:

    • Company / Project Revenue: Less than $50k per year

    • Company or Project Name: media-library-normalizer

    • Description:

      Non-commercial open-source tool for normalizing and validating media library
      names for Jellyfin. Uses TVDB data for TV series metadata matching.
      Project: https://github.com/pokornyIt/media-library-normalizer
      
  3. Copy the API Key and set MLN_TVDB_API_KEY to that value.

TVDB's free tier requires attribution. Comply with their licensing terms.

Note: Without API keys, provider lookup uses only the local cache. Previously resolved items are still matched; new items are left unresolved.

CLI Commands

scan

Scans the media library and prints a summary.

uv run media-library-normalizer scan

Output:

Discovered 13342 media files.
- Filmy/Akcni/Avatar (2009) - CZ.mkv
...

parse

Scans, parses, validates, and performs provider ID lookup. This is the main analysis command.

export $(cat .env | grep -v '^#' | xargs)
uv run media-library-normalizer parse

# or with custom report path
uv run media-library-normalizer parse --output /path/to/custom-report.json

Output:

Parsed 13342 media files.
Validation summary: passed=13127, review_needed=215, failed=0
Provider lookup summary: resolved=12697 (cache=12695, online=0, embedded=2), unresolved=430
Review report written to: data/workspace/reports/parse-review-report.json
Review HTML report written to: data/workspace/reports/parse-review-report.html
Unresolved provider report written to: data/workspace/reports/unresolved-provider-report.json
Unresolved HTML report written to: data/workspace/reports/unresolved-provider-report.html

Provider ID resolution order:

  1. Embedded ID in folder name — e.g. [imdbid-tt1234567] or [tmdbid-12345]
  2. Local provider cache (data/workspace/cache/provider_ids.json)
  3. Online API (if API keys are configured), in this order: movie -> TMDb; tv_episode (series-level lookup) -> TMDb TV, then TVDB

report-scan

Scans and parses, then writes a full JSON report of all parsed items.

uv run media-library-normalizer report-scan
uv run media-library-normalizer report-scan --output /custom/path/report.json

Default output: data/workspace/reports/report-scan-results.json


bootstrap-providers

Initializes an empty provider cache file. Use this to reset cached provider matches.

uv run media-library-normalizer bootstrap-providers

Output:

Provider cache bootstrapped: data/workspace/cache/provider_ids.json

info

Displays current runtime settings.

uv run media-library-normalizer info

validate-path

Checks whether a given path exists on the filesystem. Useful for diagnosing path configuration.

uv run media-library-normalizer validate-path /path/to/check

Development

Stack

Tool Purpose
Python 3.14 (>=3.14,<3.15) Core language
uv Dependency and environment management
ruff Linting and formatting
pyright Static type checking
pytest Test framework

Common commands

# Run all tests
uv run pytest

# Run tests with coverage
uv run pytest --cov=src/media_library_normalizer --cov-report=term-missing

# Lint and format
uv run ruff check src/ tests/
uv run ruff format src/ tests/

# Type check
uv run pyright

About

Safely normalize media libraries with reviewable naming profiles. Jellyfin is supported first.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages