No description
  • Go 98.2%
  • Makefile 1.5%
  • Dockerfile 0.3%
Find a file
zemdregon a0fe5155cf
Some checks are pending
CI / lint (push) Waiting to run
CI / test (push) Waiting to run
CI / build (push) Waiting to run
CI / docker (push) Blocked by required conditions
fix: scanner settings and import behavior (vault-tested)
2026-08-17 09:35:01 -05:00
.github chore(deps): bump rardecode/v2 to v2.3.0 (#34) 2026-08-10 19:29:11 -05:00
cmd/module chore: refresh docs/CI and align module bootstrap 2026-07-22 19:09:49 -05:00
deploy chore: refresh docs/CI and align module bootstrap 2026-07-22 19:09:49 -05:00
internal fix: scanner settings and import behavior (vault-tested) 2026-08-17 09:35:01 -05:00
proto/scannerv1 feat: scanner proto and roots-aware import refinements. 2026-07-22 12:24:53 -05:00
test Initial commit: media-scanner module 2026-06-15 20:08:05 -05:00
.dockerignore Initial commit: media-scanner module 2026-06-15 20:08:05 -05:00
.env.example chore: refresh docs/CI and align module bootstrap 2026-07-22 19:09:49 -05:00
.gitignore Initial commit: media-scanner module 2026-06-15 20:08:05 -05:00
.golangci.yml Initial commit: media-scanner module 2026-06-15 20:08:05 -05:00
CHANGELOG.md Advertise settings capability (v0.1.9). 2026-08-10 04:48:07 -05:00
COMPATIBILITY.md Initial commit: media-scanner module 2026-06-15 20:08:05 -05:00
CONTRIBUTING.md chore: refresh docs/CI and align module bootstrap 2026-07-22 19:09:49 -05:00
Dockerfile Initial commit: media-scanner module 2026-06-15 20:08:05 -05:00
go.mod chore(deps): bump rardecode/v2 to v2.3.0 (#34) 2026-08-10 19:29:11 -05:00
go.sum chore(deps): bump rardecode/v2 to v2.3.0 (#34) 2026-08-10 19:29:11 -05:00
LICENSE Initial commit: media-scanner module 2026-06-15 20:08:05 -05:00
Makefile Initial commit: media-scanner module 2026-06-15 20:08:05 -05:00
muxcore.json Advertise settings capability (v0.1.9). 2026-08-10 04:48:07 -05:00
README.md chore: refresh docs/CI and align module bootstrap 2026-07-22 19:09:49 -05:00
ROADMAP.md feat: scanner proto and roots-aware import refinements. 2026-07-22 12:24:53 -05:00
SECURITY.md chore: refresh docs/CI and align module bootstrap 2026-07-22 19:09:49 -05:00

Media Scanner

CI Go Version License: GPL-3.0

Scans download directories, identifies media files via filename parsing, and imports them into an organized library structure.

A MuxCore sidecar module that watches download directories for new media files, parses their filenames to identify movies and TV shows, and organizes them into a clean library hierarchy. When connected to core, imports go through the storage API; otherwise files are hardlinked/copied/moved on the local filesystem.


How It Works

Download dir ──→ media-scanner ──→ Organized library
                   │
                   ├── Movies/Title (Year)/Title.Year.Quality.mkv
                   └── TV/Show Name/Season XX/Show.Name.SXXEYY.Quality.mkv

Key Features

  • Automatic scanning — fsnotify watches download directories (plus a 15m safety rescan)
  • Archive extract — ZIP/RAR archives are unpacked before import
  • Filename parsing — extracts title, year, season, episode, and quality from release names
  • Smart organization — Movies go to Movies/Title (Year)/, TV goes to TV/Title/Season XX/
  • Naming templates — when media.roots / media.rename are available, destination paths follow the roots naming template
  • Library root rescanScanLibraryRoots indexes media already under registered library roots (or SCANNER_LIBRARY_ROOT)
  • Deduplication — already-imported files are tracked in SQLite and skipped
  • Sample filtering — skips sample/trailer names and files below SCANNER_MIN_VIDEO_BYTES
  • Sidecar subtitles — imports matching subtitle files alongside video (registers with media.subtitles when available)
  • Watch directory management — add/remove watched paths at runtime via gRPC; optional SCANNER_DEFAULT_WATCH_DIR auto-registers on start
  • Import history — full audit trail of all imported files
  • Targeted importImportPath imports files under a single path (must be inside a watch dir). Register the downloader DOWNLOAD_DIR as a watch directory so automation can import completed downloads.

Configuration

Environment Variables

Variable Default Description
SCANNER_DB_PATH /var/lib/media-scanner/scanner.db SQLite database path
SCANNER_GRPC_ADDR :9470 gRPC listen address
SCANNER_LIBRARY_ROOT /data/media Root directory for organized media
SCANNER_DEFAULT_WATCH_DIR (empty) Auto-register this path as a watch dir on start
SCANNER_IMPORT_MODE hardlink Local import mode when core storage is unavailable: hardlink, copy, or move
SCANNER_SAMPLE_MAX_BYTES 209715200 (200 MiB) Max size for sample/trailer filename rejection
SCANNER_MIN_VIDEO_BYTES 5242880 (5 MiB) Reject videos smaller than this (0 disables)
SCANNER_SAFETY_RESCAN 15m Fallback full rescan interval (0 disables)
MUXCORE_GRPC_ADDR localhost:9090 Core mesh gRPC address
MUXCORE_INSECURE_DISABLE_TLS false Disable TLS for dev

Quick Start

# Build
make build

# Run against local core (dev mode)
export MUXCORE_INSECURE_DISABLE_TLS=true
./media-scanner --muxcore-mesh-addr localhost:9090

# Add a watch directory
grpcurl -d '{"path": "/downloads", "library_path": "/data/media"}' \
  :9470 muxcore.scanner.v1.ScannerService/AddWatchDir

# Trigger a scan
grpcurl :9470 muxcore.scanner.v1.ScannerService/Scan

# Rescan library roots in place
grpcurl :9470 muxcore.scanner.v1.ScannerService/ScanLibraryRoots

gRPC API

Scan, ScanLibraryRoots, ImportPath, AddWatchDir, RemoveWatchDir, ListWatchDirs, ListImported, GetStats


Development

make test     # run tests with race detection
make lint     # golangci-lint
make fmt      # format code
make proto    # regenerate protobuf code

License

GPL-3.0