# MediaTracker Application Dockerisée de recensement de médiathèque. Scanne vos partages NAS en lecture seule, identifie automatiquement films et séries à partir des noms de fichiers, récupère les jaquettes via l'API publique IMDB, et expose une interface web pour rechercher votre catalogue — y compris en plusieurs langues. --- ## Fonctionnalités - **Scan automatique** : scan complet au premier démarrage, puis scan incrémental périodique (configurable) - **Détection films/séries** : parse-torrent-name reconnaît la grande majorité des conventions de nommage torrent - **Jaquettes automatiques** : récupérées via l'API de suggestion IMDB publique (sans clé API) - **Recherche multilingue** : cherchez en français ou en anglais — les titres sont croisés avec IMDB en temps réel - **Multi-NAS** : autant de sources que nécessaire, montées en lecture seule - **Affiches locales** : si un `poster.jpg` / `folder.jpg` existe à côté du fichier, il est utilisé en priorité - **Interface web** : thème sombre, cartes avec jaquette, modal de détail, panneau de scan avec historique --- ## Stack technique | Composant | Technologie | |------------|-------------------------------------| | Backend | Python 3.12 · FastAPI · SQLAlchemy | | Base de données | MariaDB 11 | | Planificateur | APScheduler | | Parser | parse-torrent-name (PTN) | | Métadonnées | IMDB suggestion API (public) | | Frontend | HTML/CSS/JS vanilla · Nginx | | Conteneurs | Docker Compose v2 | --- ## Prérequis - **Docker** ≥ 24 et **Docker Compose** ≥ v2 - **Python 3.x** sur l'hôte (pour `generate-compose.py`, stdlib uniquement) - Vos partages NAS montés sur le système hôte (voir ci-dessous) --- ## Monter un partage NAS (SMB/CIFS) Si votre NAS est accessible en SMB, installez `cifs-utils` puis montez le partage : ```bash sudo apt install cifs-utils # Debian/Ubuntu sudo mkdir -p /mnt/nas1 # Montage manuel (test) sudo mount -t cifs //192.168.1.100/Videotheque /mnt/nas1 \ -o username=VOTRE_USER,password=VOTRE_PASS,uid=$(id -u),gid=$(id -g),iocharset=utf8 # Montage permanent via /etc/fstab //192.168.1.100/Videotheque /mnt/nas1 cifs credentials=/etc/nas-creds,uid=1000,gid=1000,iocharset=utf8,_netdev 0 0 ``` `/etc/nas-creds` (permissions `600`) : ``` username=VOTRE_USER password=VOTRE_PASS ``` > MediaTracker ne monte rien lui-même et n'écrit jamais sur le NAS. --- ## Installation ### 1. Cloner le dépôt ```bash git clone https://github.com/votre-repo/mediatracker.git cd mediatracker ``` ### 2. Configurer l'environnement ```bash cp .env.example .env ``` Éditez `.env` et adaptez a minima : ```env DB_ROOT_PASSWORD=un_mot_de_passe_fort DB_PASSWORD=un_autre_mot_de_passe NAS_1=NAS Principal|/mnt/nas1 # NAS_2=Séries|/mnt/nas2 ``` ### 3. Générer le fichier Docker Compose override ```bash python3 generate-compose.py ``` Ce script lit `.env`, vérifie que les chemins existent, et génère `docker-compose.override.yml` avec les volumes en lecture seule. Relancez-le à chaque modification des entrées `NAS_*`. ### 4. Lancer l'application ```bash docker compose -f docker-compose.yml -f docker-compose.override.yml up -d --build ``` L'interface est disponible sur **http://localhost:8080** (ou le port défini par `APP_PORT`). Au premier démarrage, un scan complet est lancé automatiquement. --- ## Ajouter ou modifier un NAS 1. Éditez `.env` (ajoutez ou modifiez une entrée `NAS_X`) 2. Régénérez l'override : `python3 generate-compose.py` 3. Redémarrez le backend : ```bash docker compose -f docker-compose.yml -f docker-compose.override.yml up -d backend ``` --- ## Conventions de nommage supportées MediaTracker utilise [parse-torrent-name](https://github.com/platelminto/parse-torrent-name) pour analyser les noms de fichiers. ### Films ``` The.Dark.Knight.2008.1080p.BluRay.x264.mkv Inception (2010) 4K HDR.mkv Parasite.2019.FRENCH.1080p.WEB-DL.mp4 Dune Part Two (2024).mkv ``` ### Séries ``` Breaking.Bad.S01E01.1080p.mkv Game.of.Thrones.S08E06.The.Iron.Throne.720p.mkv /Stranger Things/Season 2/Stranger.Things.S02E04.mkv /The.Wire/Saison 3/S03E01.mkv ``` Les dossiers nommés `Season X`, `Saison X` ou `SXX` sont automatiquement détectés comme indicateurs de saison. --- ## Recherche multilingue La recherche fonctionne en français comme en anglais sans configuration supplémentaire. **Mécanisme :** lors d'une recherche, la requête est envoyée à l'API de suggestion IMDB (publique, multilingue). Les identifiants IMDB retournés sont croisés avec la colonne `imdb_id` de la base locale. Ainsi, chercher « chevalier noir » retrouve un film indexé sous son titre anglais « The Dark Knight » si son `imdb_id` est présent en base. Les `imdb_id` sont peuplés automatiquement lors du scan (phase de récupération des jaquettes). --- ## API Reference | Méthode | Endpoint | Description | |---------|--------------------------------------|------------------------------------| | GET | `/api/search?q=…&type=all\|movie\|series` | Recherche (titre + IMDB cross-ref) | | POST | `/api/scan/full` | Déclenche un scan complet | | POST | `/api/scan/incremental` | Déclenche un scan incrémental | | GET | `/api/scan/status/{id}` | Statut d'un scan | | GET | `/api/scan/history` | 20 derniers scans | | GET | `/api/stats` | Compteurs globaux | | GET | `/api/nas` | Liste des NAS et leur statut | | GET | `/api/health` | Healthcheck | | GET | `/api/local-poster?path=…` | Sert une jaquette locale depuis le NAS | --- ## Troubleshooting ### NAS inaccessible au démarrage Le backend démarre même si un NAS est inaccessible. Vérifiez les logs : ```bash docker compose logs backend | grep -i nas ``` Assurez-vous que le point de montage hôte existe **avant** de lancer `generate-compose.py`. ### Fichiers non reconnus Les fichiers que PTN ne parvient pas à analyser sont enregistrés dans la table `unmatched_files`. Consultez-les directement en base : ```sql SELECT file_path, reason FROM unmatched_files ORDER BY scanned_at DESC LIMIT 50; ``` Ou via les stats de l'interface (compteur « non reconnus »). ### Jaquettes manquantes après le scan Les jaquettes sont récupérées en parallèle après le scan de fichiers (10 workers). Si le réseau est lent ou IMDB indisponible, relancez un scan incrémental : ```bash curl -X POST http://localhost:8080/api/scan/incremental ``` ### Réinitialiser complètement la base de données ```bash docker compose down -v docker compose -f docker-compose.yml -f docker-compose.override.yml up -d --build ``` > Toutes les données sont supprimées. Un scan complet repart automatiquement. ### Voir les logs en temps réel ```bash docker compose logs -f backend ``` --- ## Licence MIT — voir [LICENSE](LICENSE). --- --- # MediaTracker — English Dockerized media library scanner. Scans your NAS shares in read-only mode, automatically identifies movies and TV series from filenames, fetches posters via the public IMDB API, and exposes a web UI to browse your catalogue — including multilingual search. --- ## Features - **Automatic scanning**: full scan on first start, then periodic incremental scans (configurable interval) - **Movie/series detection**: parse-torrent-name handles the vast majority of torrent naming conventions - **Automatic posters**: fetched via the public IMDB suggestion API (no API key required) - **Multilingual search**: search in French or English — titles are cross-referenced with IMDB at query time - **Multi-NAS**: any number of sources, all mounted read-only - **Local artwork**: if a `poster.jpg` / `folder.jpg` exists next to the video file, it is used first - **Web interface**: dark theme, poster cards, detail modal, scan panel with history --- ## Tech stack | Component | Technology | |-------------|-------------------------------------| | Backend | Python 3.12 · FastAPI · SQLAlchemy | | Database | MariaDB 11 | | Scheduler | APScheduler | | Parser | parse-torrent-name (PTN) | | Metadata | IMDB suggestion API (public) | | Frontend | Vanilla HTML/CSS/JS · Nginx | | Containers | Docker Compose v2 | --- ## Requirements - **Docker** ≥ 24 and **Docker Compose** ≥ v2 - **Python 3.x** on the host (for `generate-compose.py`, stdlib only) - NAS shares mounted on the host system (see below) --- ## Mounting a NAS share (SMB/CIFS) If your NAS is accessible via SMB, install `cifs-utils` and mount the share: ```bash sudo apt install cifs-utils # Debian/Ubuntu sudo mkdir -p /mnt/nas1 # Manual mount (testing) sudo mount -t cifs //192.168.1.100/Videos /mnt/nas1 \ -o username=YOUR_USER,password=YOUR_PASS,uid=$(id -u),gid=$(id -g),iocharset=utf8 # Permanent mount via /etc/fstab //192.168.1.100/Videos /mnt/nas1 cifs credentials=/etc/nas-creds,uid=1000,gid=1000,iocharset=utf8,_netdev 0 0 ``` `/etc/nas-creds` (permissions `600`): ``` username=YOUR_USER password=YOUR_PASS ``` > MediaTracker never mounts anything itself and never writes to the NAS. --- ## Installation ### 1. Clone the repository ```bash git clone https://github.com/your-repo/mediatracker.git cd mediatracker ``` ### 2. Configure the environment ```bash cp .env.example .env ``` Edit `.env` and set at minimum: ```env DB_ROOT_PASSWORD=a_strong_password DB_PASSWORD=another_strong_password NAS_1=Main NAS|/mnt/nas1 # NAS_2=4K Movies|/mnt/nas2 ``` ### 3. Generate the Docker Compose override ```bash python3 generate-compose.py ``` This script reads `.env`, checks that paths exist, and generates `docker-compose.override.yml` with read-only volumes. Re-run it whenever you change `NAS_*` entries. ### 4. Start the application ```bash docker compose -f docker-compose.yml -f docker-compose.override.yml up -d --build ``` The interface is available at **http://localhost:8080** (or the port set by `APP_PORT`). On first start, a full scan is triggered automatically. --- ## Adding or changing a NAS 1. Edit `.env` (add or update a `NAS_X` entry) 2. Regenerate the override: `python3 generate-compose.py` 3. Restart the backend: ```bash docker compose -f docker-compose.yml -f docker-compose.override.yml up -d backend ``` --- ## Supported naming conventions MediaTracker uses [parse-torrent-name](https://github.com/platelminto/parse-torrent-name) to parse filenames. ### Movies ``` The.Dark.Knight.2008.1080p.BluRay.x264.mkv Inception (2010) 4K HDR.mkv Parasite.2019.FRENCH.1080p.WEB-DL.mp4 Dune Part Two (2024).mkv ``` ### TV series ``` Breaking.Bad.S01E01.1080p.mkv Game.of.Thrones.S08E06.The.Iron.Throne.720p.mkv /Stranger Things/Season 2/Stranger.Things.S02E04.mkv /The.Wire/Season 3/S03E01.mkv ``` Directories named `Season X`, `Saison X`, or `SXX` are automatically detected as season indicators. --- ## Multilingual search Search works in any language without additional configuration. **How it works:** when a search query is submitted, it is sent to the IMDB suggestion API (public, multilingual). The returned IMDB IDs are cross-referenced against the `imdb_id` column in the local database. Searching "chevalier noir" (French for "dark knight") will therefore find a film indexed under its English title "The Dark Knight", provided its `imdb_id` is stored in the database. `imdb_id` values are populated automatically during the scan (poster-fetching phase). --- ## API Reference | Method | Endpoint | Description | |--------|---------------------------------------|--------------------------------------| | GET | `/api/search?q=…&type=all\|movie\|series` | Search (title + IMDB cross-ref) | | POST | `/api/scan/full` | Trigger a full scan | | POST | `/api/scan/incremental` | Trigger an incremental scan | | GET | `/api/scan/status/{id}` | Scan status | | GET | `/api/scan/history` | Last 20 scans | | GET | `/api/stats` | Global counters | | GET | `/api/nas` | NAS sources and their status | | GET | `/api/health` | Health check | | GET | `/api/local-poster?path=…` | Serve a local poster from the NAS | --- ## Troubleshooting ### NAS not accessible at startup The backend starts even if a NAS is unreachable. Check the logs: ```bash docker compose logs backend | grep -i nas ``` Make sure the host mount point exists **before** running `generate-compose.py`. ### Unrecognized files Files that PTN cannot parse are stored in the `unmatched_files` table. Query them directly: ```sql SELECT file_path, reason FROM unmatched_files ORDER BY scanned_at DESC LIMIT 50; ``` Or check the "unmatched" counter in the UI stats panel. ### Posters missing after scan Posters are fetched in parallel after the file walk (10 workers). If the network is slow or IMDB is unavailable, trigger an incremental scan to retry: ```bash curl -X POST http://localhost:8080/api/scan/incremental ``` ### Full database reset ```bash docker compose down -v docker compose -f docker-compose.yml -f docker-compose.override.yml up -d --build ``` > All data is deleted. A full scan will start automatically. ### Stream logs in real time ```bash docker compose logs -f backend ``` --- ## License MIT — see [LICENSE](LICENSE).