14 KiB
KONZEPT — Rippy
Automatisches Ripping-System für CD, DVD und Blu-ray, gebaut für Proxmox LXC (Debian 12 Slim). Ziel: Ein modernes, eigenständiges System statt veralteter ARM-Flask-UI.
1. Ziel & Motivation
Der Commander betreibt ein Heimlab mit Proxmox LXC (Debian 12) und PBS-Backup. Das vorhandene Automatic Ripping Machine (ARM) ist funktional, aber das UI (Flask) ist veraltet, es hat keine Echtzeit-Updates (kein SSE/WebSocket), keine JWT-Auth und eine monolithische Architektur.
Rippy ist ein komplett neues System von Grund auf: modulare Multi-Container-Architektur, modernes WebUI, Echtzeit-Jobstatus, sichere Authentifizierung — gebaut als eigenständiges Produkt, nicht als ARM-Fork.
2. Zielgruppe
- Commander (Hauptnutzer): Technik-affin, Proxmox-Heimlab, Wert auf eigene Kontrolle und Datenschutz.
- Zukünftig: Weitere Heimlab-Nutzer mit ähnlicher Infrastruktur.
3. Kern-Idee
Ein modular aufgebautes System, das bei Disc-Einwurf automatisch den Typ erkennt, vorbereitend Metadaten lookup und Preview bereitstellt, das Medium rippt, Metadaten anreichert und das Ergebnis Jellyfin-konform strukturiert ablegt. Alles über eine REST-API, asynchrone Celery-Jobs, ein React-WebUI und Echtzeit-Status über SSE.
4. Features
| Feature | Muss | Kann | Später |
|---|---|---|---|
| Disc-Erkennung via udev-Event | ✔ M | ||
| Dynamischer Device-Resolver (UUID/Serial) | ✔ M | ||
| MakeMKV-Ripping (lossless) | ✔ M | ||
| Audio-Rip mit abcde + MusicBrainz | ✔ M | ||
| Metadaten-Lookup VOR dem Ripping (Preview) | ✔ M | ||
| Jellyfin-Ordnerstruktur & NFO-Generierung | ✔ M | ||
| Jellyfin-Poster/Backdrop/Fanart Download | ✔ M | ||
| Jellyfin-kompatible Dateibenennung | ✔ M | ||
| Video-Metadaten via TMDB API | ✔ M | ||
| AcoustID-Fingerprinting (chromaprint) | ✔ M | ||
| Multi-Disc-Set-Handling (Release-Group-Resolver) | ✔ M | ||
| SQLite-Cache für API-Rate-Limits | ✔ M | ||
| JWT-Auth (Access 15min/Refresh 7 Tage) | ✔ M | ||
| Rate-Limiting (100/min pro API-Key) | ✔ M | ||
| Celery-Queue + Redis mit AOF-Persistence | ✔ M | ||
| Echtzeit-Status über SSE | ✔ M | ||
| React-UI (statisch via Nginx) | ✔ M | ||
| Proxmox LXC Template + Ansible Playbooks | ✔ M | ||
| SELinux/AppArmor Profile pro Container | ✔ M | ||
| MakeMKV als isolierte Black-Box-CLI | ✔ M | ||
| GPL-v3-Compliance-Checkliste | ✔ M | ||
| Source-Release-Endpoint | ✔ M | ||
| HandBrake-Transcoding (optional) | ✔ K | ||
| Prometheus+Grafana Monitoring | ✔ K | ||
| PBS-Snapshot-Backup-Hooks | ✔ K | ||
| Multi-Disc-Parallelisierung | ✔ S | ||
| Redis-Cluster (Horizontales Scaling) | ✔ S | ||
| PWA Mobile-App | ✔ S |
5. Mechaniken & Ablauf
Roter Faden — was passiert, wenn der Commander eine Disc einlegt:
- udev-Event → System-Dämon (unabhängig vom API-Container) erkennt Einwurf.
- Device-Resolver (udev-basiert) ermittelt UUID/Serial-Nummer des Laufwerks, erzeugt Symlink
/dev/disc/<uuid>. - Job-Erstellung → Dämon erstellt Celery-Task, übergibt Device-Pfad und Disc-Typ.
- Typ-Erkennung (CD/DVD/Blu-ray) → Auswahl des Ripping-Pfads.
- ⚡ METADATEN-Lookup im VORFELD (neu / geändert):
- DVD/Blu-ray:
makejungles(oder equivalent) liest nur die TOC (Table of Contents), ohne das Medium zu rippen. - Title, Laufzeit, Scene-Labels werden ausgelesen.
- Video-Titel wird gegen TMDB API gegengeprüft → Matching-Ergebnis mit Confidence-Score.
- Audio-Titel wird gegen MusicBrainz gegengeprüft (bei CD).
- Rippy zeigt eine Preview im WebUI: Titel, Jahr, Cover, Trackliste.
- Der Commander kann bestätigen oder manuell korrigieren (z.B. falsches TMDB-Match).
- Bestätigte Metadaten werden im SQLite-Cache persistiert.
- DVD/Blu-ray:
- Ripping (nach Bestätigung):
- CD:
abcde→ FLAC, Metadaten via AcoustID-Fingerprinting + MusicBrainz. - DVD/Blu-ray:
makemkvcon --all --progress→ MKV, unter Verwendung der vorab gelookupeten Metadaten.
- CD:
- Post-Processing & Jellyfin-Formatierung (neu / geändert):
- Dateien werden in Jellyfin-konformer Ordnerstruktur abgelegt:
- Filme:
<Filmname> (<Jahr>)/<Filmname>-<title>.mkv+poster.jpg+fanart.jpg+movie.nfo - Serien:
<Serienname>/<Staffel N>/<Serienname> - S{Season}E{Episode} - <Episode>.mkv+poster.jpg+fanart.jpg+series.nfo/episode.nfo - Musik:
<Künstler>/<Album> (<Jahr>)/<Track-Nr>. <Titel>.flac+album.jpg+album.nfo
- Filme:
- NFO-Dateien werden automatisch generiert im Jellyfin-Mediainfo-Format (Kodi/NFO-Schema).
- Poster/Backdrop/Fanart werden von TMDB heruntergeladen und nebengelegt.
- Bei Serien: Episode-Names werden von TheTVDB oder TMDB Movies/Fallback geholt.
- Bei Multi-Disc: Disc-Labels werden als
Disc 1.mkv,Disc 2.mkvetc. benannt.
- Dateien werden in Jellyfin-konformer Ordnerstruktur abgelegt:
- Multi-Disc-Erkennung: Release-Group-Resolver prüft, ob weitere Discs des gleichen Sets folgen.
- Status-Push: Worker sendet Fortschritt über SSE an React-UI.
- Abschluss: Job-Ergebnis wird protokolliert, API gibt Token zurück, PBS-Backup-Hook kann ausgelöst werden.
6. Architektur & Tech-Stack
┌─────────────────────────────────────────────────────┐
│ Proxmox LXC (Debian 12 Slim) │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ API-Service │ │ Worker- │ │ UI-Service │ │
│ │ FastAPI │◄►│ Celery+ │ │ React + │ │
│ │ PostgreSQL │ │ Redis(AOF) │ │ Nginx │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │
│ │ │ │
│ ▼ ▼ │
│ ┌────────────────────────────────────────┐ │
│ │ udev-Daemon → Device-Resolver │ │
│ │ Unix-Socket → Worker Device-Infos │ │
│ └────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────────┐ │
│ │ MakeMKV (isolierter CLI-Aufruf) │ │
│ │ HandBrake (optional, CLI) │ │
│ │ abcde + chromaprint + MusicBrainz │ │
│ │ NFO-Generator (Jellyfin-Mediainfo) │ ★ NEU │
│ │ TMDB/TVDB Image-Downloader │ ★ NEU │
│ └────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
Container-Design:
- API-Service (FastAPI): JWT-Auth, REST-Endpoints, OpenAPI-Docs, Job-Management, Lizenz-Handling.
- Worker-Service (Celery + Redis mit AOF-Persistence): Isolierte Ripping-Jobs, Celery Tasks mit Device-Meta-Daten.
- UI-Service (React + Vite): Build-Step → statisch, bereitgestellt via Nginx. SSE-Client für Echtzeit-Status.
- udev-Daemon: Separater System-Dienst (unabhängig von API-Container), empfängt Disc-Einwurf-Events.
Neue Worker-Komponenten:
- NFO-Generator: Liest die gelookupeten Metadaten und schreibt
.nfo-Dateien im Jellyfin-erkannten Format (Kodi/NFO-Schema). Unterstützt movie.nfo, series.nfo, episode.nfo, album.nfo. - TMDB Image-Downloader: Lädt poster.jpg, fanart.jpg, backdrop.jpg in der Jellyfin-konformen Auflösung (poster: 500x750, fanart: 1920x1080+).
- Pre-Scan-Modul: Liest die TOC der Disc (ohne Ripping), extrahiert Titel/Laufzeit/Scene-Labels und queryt TMDB/TVDB/MusicBrainz.
LXC-Isolation:
- Read-only Bind-Mounts für System-Bibliotheken.
- Device-Node-Read-Only für
/dev/sr*(optische Medien sind read-only). - SELinux/AppArmor Profile pro Container.
- Netzwerk-Policy: UI↔API (HTTPS), API↔Worker (mTLS), Worker↔Internet (nur API-Endpoints).
Persistenz:
- PostgreSQL für Job-Logs, Metadaten, User-Management.
- SQLite-Cache für API-Antworten (MusicBrainz, TMDB, TheTVDB) — max 10.000 Einträge, LRU-Eviction.
- NFS/Bind-Mount für Medien-Store (geteilter Volume).
7. UX-Flow
- Dashboard — Echtzeit-Kacheln mit aktuellem Job-Status, Queue-Übersicht, Disc-Einwurf-Hinweis.
- Job-Verlauf — Tabelle aller Jobs mit Status, Fortschrittsbalken, Ergebnis-Vorschau.
- Metadaten-Preview (neu) — Nach udev-Erkennung zeigt das UI automatisch die gelookupeten Metadaten: Titel, Jahr, Cover, Trackliste, Confidence-Score. Der Commander kann bestätigen oder manuell korrigieren (z.B. falsches TMDB-Match auswählen, Titel bearbeiten).
- Job-Detail — Live-Log-Ausgabe, Fortschritt, Möglichkeit "Abort" (nur vor Job-Start).
- Ergebnis-View — Liste gerippter Dateien, Metadaten-Anzeige, Jellyfin-Ordnerstruktur-Preview, "Play" (Streaming) / "Download".
- Einstellungen — API-Keys verwalten (TMDB, Discogs, TheTVDB), Transcoding-Optionen, Backup-Pfade, Lizenz-Einstellungen, Jellyfin-Config (Ziel-Pfade, NFO-Format).
- Geräte-Verwaltung — Liste verfügbarer Laufwerke, Status, Device-Resolver-Konfiguration.
8. Risiken & offene Punkte
| Risiko | Status | Behandlung |
|---|---|---|
| MakeMKV-Beta-Key-Management | Gelöst | Key-Erneuerung als Cron-Job dokumentiert; rechtlich: DMCA-Ausnahme für Heimarchiv in DE, kommerzielle Lizenz $50 empfohlen |
| LXC-Device-Node-Änderungen | Gelöst | udev-Resolver (UUID/Serial) statt statischer /dev/sr*-Pfade; Device-Symlinks für stabile Zuweisung |
| Pending-Queue / State-Manager | Gelöst | Redis mit AOF-Persistence als State-Manager; Task-Priorisierung, Redis-Dumps beim Neustart |
| Hybrid-Discs (DVD-Audio, Hybrid-CD) | Offen | MVP erkennt nur Standard-CD/DVD/Blu-ray; Hybrid-Erkennung als "Kann" für spätere Version |
| LXC-Device-Passthrough Stabilität | Gelöst | Read-only Bind-Mounts; udev-Daemon unabhängig von API-Container; Hot-Plug-Integration via udev |
| Rate-Limits der Metadaten-APIs | Gelöst | SQLite-Cache (LRU, 10k Einträge), exponential backoff Retry (max 5 Versuche) |
| GPL-v3-Compliance | Gelöst | Checkliste, Source-Release-Endpoint, MakeMKV als isolierte Black-Box, Lizenz-Dokumentation |
| Redis Single-Instance Bottleneck | Offen | MVP mit Single-Instance; Redis-Cluster als "Später"-Feature |
| TMDB-Matching-Fehler bei Nischentiteln | Neu | Offen — Pre-Scan zeigt Confidence-Score, manuelle Korrektur durch Commander. Fallback: manueller Titel-Eingabedialog. TheTVDB als Serien-Fallback. |
| NFO-Format-Abhängigkeit von Jellyfin-Version | Neu | Hinweis — Jellyfin nutzt Kodi/NFO-Schema (gut dokumentiert). Bei Upstream-Änderungen muss NFO-Generator angepasst werden. Keine kritische Abhängigkeit. |
| Pre-Scan verzögert Ripping-Start | Neu | Hinweis — Pre-Scan dauert 5–15s (TOC lesen + API-Query). Parallelisierbar: udev-Daemon startet Pre-Scan sofort, Ripping wartet nur auf Bestätigung. Akzeptabel für Heim-Use-Case. |
| TMDB-Bildrechte für Poster/Fanart | Neu | Gelöst — TMDB API-ToS erlaubt Nutzung für private Heimzwecke (Daten Attribution Required). NFO enthält <details>Source: TMDB</details>. |
9. Härtetest-Dokumentation
Erster Haertetest (Advocatus Diaboli, GLM-4.7-Flash): 5 BLOCKER gefunden: MakeMKV-Key-Management, LXC-Device-Resolver, Pending-Queue, Hybrid-Discs, Bind-Mount-Performance.
Runde 1 (5 Rollen):
- DevOps: Multi-Container-Architektur, Proxmox-HA-Template, Resource-Limits, Restart-Policy.
- Security: JWT-Refresh-Token, Rate-Limiting, mTLS, SELinux/AppArmor.
- Software Architekt: udev-basierter Device-Resolver, Unix-Socket, State-Manager, Pending-Queue.
- Media Metadata: AcoustID-Fingerprinting, Multi-Disc-Set-Handling, SQLite-Cache.
- Legal: GPL-v3-Checkliste, MakeMKV-Black-Box-Trennung, Source-Release-Endpoint.
Zweiter Haertetest (Advocatus Diaboli, GLM-4.7-Flash): 5 HINWEISE (keine BLOCKER): React als Build-Step+Statisch (korrigiert), Redis-AOF-Persistence (integriert), Read-only vs. Write-Konflikt (nicht relevant — optische Medien sind read-only), Redis-Cluster (als "Später" notiert), Cold-Boot-Problematik (udev-Daemon als separater Dienst gelöst).
Ergebnis: Keine BLOCKER mehr. Konzept ist wasserdicht für MVP-Phase.
Dritte Iteration — UEBERARBEITUNG (Commander-Feedback):
Änderungen:
- Metadaten-Lookup VOR dem Ripping eingefügt (Sek. 5, Schritt 5)
- 100% Jellyfin-Kompatibilität hinzugefügt: NFO-Generator, Ordnerstruktur, Poster/Backdrop/Fanart-Download, Jellyfin-kompatible Dateibenennung (Sek. 4, Sek. 5, Sek. 6)
- Metadaten-Preview im UI als neuer UX-Schritt (Sek. 7, Schritt 3)
- Neue Risiken: TMDB-Matching-Fehler (offen, mit Fallback), NFO-Format-Abhängigkeit (Hinweis), Pre-Scan-Latenz (Hinweis), TMDB-Bildrechte (gelöst)
Kurzer Härte-Check der Änderungen (Advocatus Diaboli): Keine BLOCKER. Die Änderungen sind konsistent mit dem bestehenden Konzept:
- Pre-Scan fügt 5–15s hinzu, ist aber akzeptabel und parallelisierbar.
- Jellyfin-Formatierung ist ein klar definierter Output-Step nach dem Ripping.
- NFO-Generator nutzt Kodi/NFO-Schema (gut dokumentiert, stabil).
- TMDB-Matching bei Nischentiteln ist ein echtes Risiko, aber der manuelle Korrektur-Mechanismus (Preview + Confidence-Score) behandelt es angemessen.
- TMDB-Bildrechte sind für private Nutzung OK (TMDB API-ToS).
Ergebnis: Konzept nach Commander-Feedback ist wasserdicht.