Hitonabi f74f4e54f6
Ampel / ampel (push) Successful in 32s
fix(api): Job-Meta (poster_path) an die Jobliste durchreichen
GET /jobs nutzt response_model=List[Job]; das Job-Model hatte kein meta-Feld,
also schnitt FastAPI die Disc-Metadaten (poster_path) weg -> Dashboard.tsx
bekam job.meta = undefined -> Filmstreifen-Platzhalter statt TMDB-Poster,
sowohl in der Jobliste als auch im aktiven Rip-Header (beide aus /jobs).

Additiv: meta: Optional[Dict] ins Job-Model + in _job_row_to_model parsen
(json.loads wie im Detail-Endpunkt, defensiv gegen kaputtes JSON). Keine
UI-Aenderung noetig -- posterUrl() rendert dann die vorhandenen Poster.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-25 00:03:41 +02:00

Rippy — die All-in-one Disc-Ripping-Maschine

Disc rein → automatisch erkannt (Titel, Poster, Metadaten) → verlustfrei gerippt (MakeMKV) → auf Arbeitsgröße komprimiert (HandBrake) → fertig abgelegt, wo DU willst (lokal, NAS, jede Freigabe). Modernes Web-UI, Echtzeit-Fortschritt, komplett in Docker, komplett lokal.

Schnellstart

Voraussetzungen: Docker + Docker Compose, ein optisches Laufwerk am Host.

git clone <repo-url> rippy && cd rippy
cp .env.example .env          # optional: API-Keys — geht auch später im UI
mkdir -p /srv/rippy/media     # Ablage-Basis (anpassbar in docker-compose.yml)
docker compose up -d --build

Dann http://<host> öffnen — der Einrichtungs-Assistent startet beim ersten Mal automatisch (API-Keys, Verarbeitung, erkannte Hardware).

Laufwerk anpassen

Der Worker braucht zwei Host-Geräteknoten: den CD-ROM-Knoten (meist /dev/sr0) und den passenden SCSI-Generic-Knoten (/dev/sgN) — MakeMKV spricht Laufwerke über die sg-Schicht an. Die sg-Nummer ist je Host anders (auf frischen Systemen oft /dev/sg0).

Ermitteln, welche Knoten dein Blu-ray/DVD-Laufwerk hat:

lsscsi -g          # zeigt Modell + zugehörigen /dev/sgN
# oder: ls -la /sys/class/scsi_generic/

Dann in der .env eintragen (Defaults passen für den Ursprungs-Host):

OPTICAL_SR=/dev/sr0    # CD-ROM-Knoten deines Laufwerks
OPTICAL_SG=/dev/sg0    # sg-Knoten deines Laufwerks

docker compose up -d nutzt diese Werte. (Für Feineinstellungen geht weiterhin eine docker-compose.override.yml mit eigenen devices:-Einträgen.)

Laufwerk in einer VM? Per USB-Passthrough anhand der Vendor-ID durchreichen (Proxmox: qm set <vmid> -usb0 host=xxxx:yyyy,usb3=1) — NICHT als emuliertes CD-ROM (media=cdrom), das kann keine SCSI-Kommandos.

Wie es funktioniert

  1. Disc-Wache (ioctl-Polling, kein udev-Gefrickel) erkennt Einlegen, identifiziert die Disc (Volume-Label → TMDB → OMDb-Fallback) und zeigt sie mit Poster auf dem Dashboard. Klick auf einen Job-Titel öffnet die Detail-Ansicht (Poster, Jahr, Beschreibung, Ablagepfad).
  2. Rip (MakeMKV, verlustfrei — der einzige Weg durch AACS): Ziel wählst du beim Start (Filme/Serien/Musik/eigener Pfad, inkl. Netzwerk-Ziele) — oder du stellst die Vollautomatik an (Einstellungen → Ripping) und der Rip startet ohne Nachfrage in den passenden Schnellwahl-Ordner. Optional nur Hauptfilm (längster Titel, Extras bleiben weg). Bereits gerippte Discs erkennt Rippy am Fingerabdruck und warnt. Vor dem Start prüft Rippy den freien Platz gegen die Disc-Größe. Alle Tonspuren und Untertitel bleiben erhalten (wichtig für Anime/O-Ton). Audio-CDs laufen über abcde → FLAC + MusicBrainz. Serien: Im Dialog „Serien" wählen → Serienname + Staffel angeben — Ablage wird <Serie>/Season NN, und die Episoden werden nach dem Rip per Laufzeitabgleich (TMDB) automatisch zu „Serie S01E02.mkv" benannt (nur bei eindeutiger Zuordnung — sonst bleiben die Namen, mit Log).
  3. Kompression (HandBrake, eigener Job auf eigener Queue): x265/x264, Preset im UI wählbar; Rohdatei wird erst nach Erfolg gelöscht („Original behalten" als Option). Fehlgeschlagene Kompressionen lassen sich ohne Neu-Rip neu anstoßen.
  4. Media-Server-Ablage: Unter Einstellungen → Ripping (oder im Einrichtungs-Assistenten) wählst du dein System — Jellyfin, Emby, Kodi, Plex oder keins. Fertige Rips heißen dann „Titel (Jahr)" statt Job-UUID; für Jellyfin/Emby/Kodi legt Rippy zusätzlich movie.nfo + poster.jpg dazu (Kodi-NFO-Schema, lesen alle drei nativ). Plex nutzt nur die Benennung. Jellyfin/Emby: Server-URL + API-Key eintragen, dann stößt Rippy nach jedem fertigen Rip sofort einen Bibliotheks-Scan an — Disc rein, Film erscheint im Server.
  5. 4K-UHD: braucht ein LibreDrive-fähiges Laufwerk (MakeMKV-Forum: „Ultimate UHD Drives Flashing Guide"). Normale BD/DVD gehen mit jedem Laufwerk. ⚠️ UHD-Rohdaten sind bis 100 GB groß — wenn die Platte der Rippy-Maschine dafür zu klein ist, lege das Arbeitsverzeichnis (Einstellungen → Verarbeitung) auf eine eingehängte Freigabe, z. B. /app/media/nas-arbeit. Rippy bricht sonst VOR dem Rip mit einer Klartext-Meldung ab statt nach 40 GB mit voller Platte.

Speicherziele (NAS, Freigaben)

Unter Einstellungen → Speicherziele hängst du NFS- oder SMB-Freigaben direkt aus dem UI ein — sie erscheinen sofort in der Ziel-Auswahl beim Rippen und werden beim Start automatisch wieder verbunden. Technik: der api-Container läuft mit CAP_SYS_ADMIN und einem rshared-Bind auf /srv/rippy/media, Mounts propagieren zu allen Containern. ⚠️ Zugangsdaten liegen unverschlüsselt in der lokalen Postgres-DB — bewusster Heimnetz-Kompromiss; lege fürs NAS einen eigenen, eingeschränkten Benutzer an.

Benachrichtigungen

Einstellungen → Benachrichtigungen: eine Webhook-URL eintragen, „Test senden" drücken, speichern — fertig. Rippy meldet Job-Ende (fertig, fehlgeschlagen, abgebrochen) und erkennt den Dienst an der URL selbst:

Dienst URL-Beispiel Format
Discord https://discord.com/api/webhooks/… {"content": …}
Slack https://hooks.slack.com/services/… {"text": …}
ntfy (Handy-Push) https://ntfy.sh/mein-geheimes-thema Roh-Text + Titel
Eigenes (HA, n8n, …) beliebige HTTPS-URL {"title","message","level"}

System, MakeMKV-Beta-Key & Updates

Einstellungen → System zeigt die Werkzeug-Versionen jedes Workers (MakeMKV, HandBrake), den Key-Status und den freien Speicherplatz. Der MakeMKV-Beta-Key (wechselt ~monatlich, Forum-Thread t=1053) wird hier im UI eingetragen und gilt ab dem nächsten Rip — ohne Rebuild, ohne Neustart; er schlägt den Key aus der .env.

Updates: „Auf Updates prüfen" vergleicht mit makemkv.com und den offiziellen HandBrake-Releases (12 h gecacht). MakeMKV-Update ohne Code-Änderung: MAKEMKV_VERSION=x.y.z in die .env, dann docker compose build worker && docker compose up -d worker — neue Versionen bringen auch die neueste Disc-Schlüssel-Datenbank mit. HandBrake kommt im Docker-Worker bewusst aus Debian (stabil, hinkt der offiziellen Version hinterher); der native Windows-Worker nutzt die aktuelle Version direkt.

Verarbeitung & Hardware

Einstellungen → Verarbeitung zeigt ehrlich an, welche Encoder deine Worker WIRKLICH haben (CPU x264/x265, VAAPI bei AMD/Intel-GPU, NVENC bei NVIDIA) — jeder Worker meldet seine Fähigkeiten selbst beim Start.

Optional: weitere Maschinen als Transcode-Worker

Die Kompression läuft als eigener Celery-Task auf der Queue transcode — JEDE Maschine im Netz kann sie übernehmen. Einstellungen → Worker zeigt für beide Varianten einen Copy-Paste-Befehl:

  • Linux (Docker): deploy/remote-transcode-worker.yml
  • Windows (nativ, ohne Docker): braucht nur Python 3.10+ — der Installer (install.ps1) kommt von der Rippy-Instanz selbst (/api/worker-setup/windows), lädt Worker-Code und HandBrakeCLI automatisch und erzeugt eine start-worker.bat (optional -Autostart).

Ohne Zusatz-Worker macht der eingebaute CPU-Worker alles selbst — Rippy bleibt All-in-one.

Umgebungsvariablen (.env)

Variable Pflicht Zweck
TMDB_API_KEY empfohlen Metadaten (deutsche Texte) — alternativ im UI/Wizard; beide Key-Arten gehen (v3-Schlüssel und v4-Token)
WORKER_NAME optional Anzeigename des eingebauten Workers (Standard: rippy-hauptworker)
OMDB_API_KEY optional zweite Metadaten-Quelle (Fallback)
THETVDB_API_KEY optional Serien-Fallback
MAKEMKV_APP_KEY optional MakeMKV-Beta-Key (Forum); DVDs gehen ohne — bequemer: im UI unter Einstellungen → System pflegen
MAKEMKV_URL_BASE optional alternative Download-Quelle für den Image-Build
OPTICAL_SR je Host Host-Pfad des CD-ROM-Knotens (Default /dev/sr0) — siehe „Laufwerk anpassen"
OPTICAL_SG je Host Host-Pfad des sg-Knotens des Laufwerks (Default /dev/sg1; oft /dev/sg0)
POSTGRES_PASSWORD optional DB-Passwort (Default rippy) — für exponierte Umgebungen ein starkes Passwort setzen

UI-Einstellungen (Wizard/Settings) überstimmen die Env-Variablen.

Rippy woanders bereitstellen

Rippy ist reines Docker Compose — es läuft auf jedem Linux-Host mit Docker, nicht nur auf der Original-VM. Es gibt (noch) keine fertigen Registry-Images; gebaut wird beim ersten up direkt aus dem Repo.

Voraussetzungen auf dem Ziel-Host:

  1. Linux (x86_64) mit Docker + Compose-Plugin.
  2. Ein optisches Laufwerk, das der Host sieht (ls /dev/sr* /dev/sg*). In einer VM: per USB-Passthrough (Vendor-ID) durchreichen, NICHT als emuliertes CD-ROM — siehe „Laufwerk anpassen" oben.
  3. Ablage-Basis anlegen: mkdir -p /srv/rippy/media (oder Pfad in docker-compose.yml anpassen). Der Bind nutzt shared/slave-Propagation (fürs In-UI-Einhängen von NAS-Freigaben). Auf den meisten systemd-Linux-Hosts ist / schon rshared, dann ist nichts zu tun. Bricht docker compose up mit „path … is mounted on / but it is not a shared mount" ab, einmalig:
    sudo mount --bind /srv/rippy/media /srv/rippy/media
    sudo mount --make-rshared /srv/rippy/media
    
    (reboot-fest als systemd-.mount-Unit persistieren.) Braucht einen klassischen Linux-Docker-Host mit SYS_ADMIN — nicht Docker-Desktop/rootless/Podman.

Dann wie im Schnellstart: klonen, .env füllen, docker compose up -d --build, http://<host> öffnen — der Einrichtungs-Assistent führt durch den Rest (API-Keys, Media-Server, Verarbeitung). Updates: git pull && docker compose up -d --build.

Nicht mitnehmen musst du: Gitea, Arcane, den CI-Runner — das ist die Entwicklungs-Infrastruktur DIESER Installation, nicht Teil von Rippy.

Härtung für fremde/exponierte Netze

Rippy ist bewusst Heimnetz-only: Es hat keine Authentifizierung, und Redis + PostgreSQL veröffentlichen Ports auf allen Interfaces (für Remote-Worker). Im vertrauten LAN ist das ein akzeptierter Kompromiss — exponiere Rippy niemals ungeschützt an ein unsicheres oder öffentliches Netz. Wer es weiter absichern will:

  • Zugriff kapseln: API (:8000) und UI hinter einen Reverse-Proxy mit Auth (Basic-/Forward-Auth) legen oder nur über VPN erreichbar machen; Port 8000 nicht auf 0.0.0.0 binden.
  • DB/Broker abschotten: POSTGRES_PASSWORD in der .env auf ein starkes Passwort setzen; die Ports 5432/6379 nur an ein internes/VPN-Interface binden (z. B. "10.0.0.5:5432:5432") statt an 0.0.0.0; Redis mit --requirepass <geheim> starten und das Passwort in REDIS_URL ergänzen.
  • CORS: main.py erlaubt aktuell * (nötig, weil UI und API getrennte Ports sind) — hinter einem Proxy auf die echte UI-Herkunft einschränken.
  • NAS-Zugangsdaten liegen bewusst im Klartext in der DB — ein weiterer Grund, den DB-Port nie offen ins unsichere Netz zu hängen.

Entwicklung

CI („Ampel") läuft bei jedem Push: Ruff, pytest, Vite-Build. Es gibt genau einen Branch, main (Single Source of Truth) — die Ampel prüft nur, deployt wird direkt aus main. Rot heißt: nicht deployen. Regeln für Beiträge: AGENTS.md · Konzept: KONZEPT.md · Fahrplan: ROADMAP.md

S
Description
Modernes automatisches CD/DVD/Blu-ray-Ripping-System mit WebUI und Proxmox-Integration
Readme 418 MiB
Languages
Python 63.7%
TypeScript 32.5%
Shell 2.5%
Dockerfile 1%
CSS 0.2%