# MovieMapper Desktop application for organizing and managing movie and TV show collections. Scan media directories, extract metadata with FFmpeg, tag files as extras or commentary, and move them into Jellyfin-compatible folder structures — with a full audit trail. [![CI](https://git.jarianc.com/jarianc/MovieMapper/actions/workflows/ci.yml/badge.svg)](https://git.jarianc.com/jarianc/MovieMapper/actions) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) ## Features - **Directory scanning** — non-recursive folder browsing with real-time progress - **Metadata extraction** — duration, video quality, and FPS via `ffprobe` - **File tagging** — mark files as `extra` or `commentary` with visual state - **Jellyfin-compatible moves** — tagged files move into spec-compliant folders (`extras/`, `commentary/`, `behind the scenes/`, ...) - **TheTVDB integration** — search shows, browse seasons/episodes, map episodes to `SxxExx` naming convention - **Audit logging** — every move/rename writes a `.audit` entry in the target directory; nothing happens silently - **Progress reporting** — IPC-driven progress updates during scans ## Architecture Three implementations share the same core concepts (scanner → metadata → tagging → mapping → audit): ``` ┌─────────────────────────────────────────────────────────────┐ │ MovieMapper │ ├──────────────┬──────────────────────────┬───────────────────┤ │ Electron │ Rust core (crate) │ iOS (Swift) │ │ desktop app │ movie_mapper │ companion client │ │ ├──────────────────────────┤ │ │ main.js │ model/ Show, Season, │ SharedModels/ │ │ renderer.js │ Episode │ Swift mirrors │ │ index.html │ service/ │ │ │ utils/ │ FileScanner │ build.sh │ │ │ MetadataExtractor │ archive.sh │ │ Electron │ TVDBClient │ Xcode project │ │ IPC bridge │ FileMapper │ │ │ │ TagManager │ │ │ │ AuditLogger │ │ └──────────────┴──────────────────────────┴───────────────────┘ ``` | Component | Stack | Role | |-----------|-------|------| | `main.js`, `renderer.js` | Electron (Node 20) | Desktop UI, IPC handlers, filesystem ops | | `utils/fileUtils.js` | Node + fluent-ffmpeg | Directory scanning, ffprobe metadata | | `Rust/` (crate `movie_mapper`) | Rust, tokio, reqwest | Reusable core: scanner, TVDB client, mapper, tags, audit | | `backend/` (crate) | Rust | Async backend integration layer | | `ui/` (crate) | Rust, Iced | Native Rust UI prototype | | `SharedModels/` | Swift | Data models for the iOS companion | ### Data flow ``` directory scan ──▶ ffprobe metadata ──▶ tag (extra/commentary) │ ▼ Jellyfin folder mapping │ ▼ .audit log entry per operation ``` ## Project structure ``` ├── main.js # Electron main process (IPC, file ops, TVDB) ├── renderer.js # Renderer process (UI state, events) ├── index.html # UI (dark theme) ├── preload.js # Context bridge ├── utils/fileUtils.js # Directory scan + ffprobe metadata ├── tests/ # vitest suite (118 tests) │ └── legacy/ # Earlier node:test integration tests ├── Rust/ # Rust core crate (movie_mapper) │ ├── src/service/ # Scanner, TVDB client, mapper, tags, audit │ ├── src/model/ # Show, Season, Episode, MediaFile │ └── tests/ # Unit, integration, e2e, benchmarks ├── backend/ # Rust backend integration crate ├── ui/ # Rust Iced UI prototype ├── SharedModels/ # Swift models (iOS companion) └── docs/ # Design docs, phase summaries, plans ``` ## Installation Installers are published on the [releases page](https://git.example.com/jarianc/MovieMapper/releases) (AppImage + .deb for Linux, .dmg for macOS, .exe for Windows). ### Linux — AppImage ```bash chmod +x MovieMapper-*.AppImage ./MovieMapper-*.AppImage ``` ### Linux — Debian/Ubuntu ```bash sudo dpkg -i MovieMapper_*_amd64.deb ``` ### Rust CLI ```bash cargo install --path Rust ``` Requires Rust and `ffmpeg`/`ffprobe` on PATH (used for metadata extraction). ## Getting started ### Desktop app (Electron) — from source Prerequisites: Node.js 20+, npm, `ffmpeg`/`ffprobe` on PATH. ```bash npm install cp .env.example .env # add your TVDB_API_KEY npm start ``` ### Building installers ```bash npm run dist # current platform npm run dist:linux # AppImage + deb npm run dist:mac # dmg (macOS only) npm run dist:win # nsis exe ``` ### Rust core ```bash cargo build --workspace cargo test --workspace ``` ### Rust CLI The `movie_mapper` binary exposes the core as a command-line tool for scripting and headless use: ```bash # List media files with metadata movie-mapper scan /path/to/season [--json] # Rename files to Jellyfin naming (Show S01E01 - Quality.ext) movie-mapper map /path/to/season --show "The Show" --season 1 [--episode-start 1] [--dry-run] # Tag / untag files (persisted to .moviemapper.json) movie-mapper tag /path/to/media "behind the scenes" movie-mapper untag /path/to/media "behind the scenes" # Move tagged files into the Jellyfin folder for that tag movie-mapper move /path/to/media "behind the scenes" [--dry-run] # TheTVDB (requires TVDB_API_KEY) movie-mapper tvdb search "Breaking Bad" movie-mapper tvdb show 81189 # Show the audit log for a directory movie-mapper audit /path/to/season ``` All destructive commands support `--dry-run` for a filesystem-safe preview. Every rename and move writes an entry to the directory's `.audit` log. Configuration is read from `~/.config/movemapper/config.toml`: ```toml tvdb_api_key = "your-api-key" media_dir = "/path/to/media" ``` Precedence for the API key: `--tvdb-key` flag > `TVDB_API_KEY` env var > config file. ### Tests ```bash npm test # vitest suite (JS) cargo test --workspace # Rust unit + integration ``` ## Configuration | Variable | Required | Description | |----------|----------|-------------| | `TVDB_API_KEY` | for TVDB search | TheTVDB v4 API token | ## Jellyfin folder compatibility Moves target the [Jellyfin extras folder specification](https://docs.jellyfin.org/): `behind the scenes`, `deleted scenes`, `interviews`, `scenes`, `samples`, `shorts`, `featurettes`, `clips`, `other`, `extras`, `trailers`, `theme-music`, `backdrops`. ## Documentation - [Project overview](docs/PROJECT_OVERVIEW.md) - [Feature matrix](docs/FEATURES.md) - [Rust implementation notes](docs/RUST_IMPLEMENTATION.md) - [Folder navigation design](docs/FOLDER_NAVIGATION_PLAN.md) - [iOS plan](docs/iOS_PLAN.md) ## License [MIT](LICENSE)