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.
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
extraorcommentarywith 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
SxxExxnaming convention - Audit logging — every move/rename writes a
.auditentry 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
Getting started
Desktop app (Electron)
Prerequisites: Node.js 20+, npm, ffmpeg/ffprobe on PATH.
npm install
cp .env.example .env # add your TVDB_API_KEY
npm start
Rust core
cargo build --workspace
cargo test --workspace
Tests
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:
behind the scenes, deleted scenes, interviews, scenes, samples,
shorts, featurettes, clips, other, extras, trailers,
theme-music, backdrops.
Documentation
License
Languages
JavaScript
53.3%
Rust
41.4%
HTML
2.7%
Shell
1.2%
Python
0.7%
Other
0.7%