feat(install): ein Befehl statt Checkliste - install.sh nimmt die Handarbeit ab
Ampel / ampel (push) Successful in 28s
Ampel / ampel (push) Successful in 28s
Commander-Rueckmeldung: "Das Docker Deployment ist mir zu kompliziert." Zu
Recht - die Installation war eine Checkliste aus sechs Schritten, von denen
zwei nur mit Fachwissen zu schaffen waren.
## Neu: sudo ./install.sh
Nimmt genau die Schritte ab, an denen man scheitern konnte:
1. Prueft Voraussetzungen (Linux, Docker, Compose) und nennt bei jedem Mangel
den Installationsbefehl.
2. FINDET DAS LAUFWERK SELBST. Das war der schlimmste Punkt: MakeMKV braucht
ZWEI Geraeteknoten, und die sg-Nummer ist je Host anders. Das Skript gleicht
sie ueber die SCSI-Adresse in /sys ab statt zu raten. Auf der VM
gegengeprueft: sr0 -> 3:0:0:0, sg1 -> 3:0:0:0, also dasselbe Geraet -
korrekt als /dev/sr0 + /dev/sg1 erkannt.
3. Legt Ablage- und MakeMKV-Verzeichnis an.
4. Richtet die Mount-Propagation ein UND macht sie per systemd-.mount-Unit
neustart-fest. Vorher stand in der README nur "reboot-fest persistieren" -
ohne zu sagen wie; nach einem Reboot scheiterte das Einhaengen von
NAS-Freigaben aus dem UI stillschweigend.
5. Schreibt die .env, ueberschreibt aber NIE einen bestehenden Wert.
6. Baut und startet, und nennt bei Fehlschlag die drei haeufigsten Ursachen
mit Diagnosebefehl.
Wiederholbar (mehrfach ausfuehren aendert nichts kaputt) und damit auch der
Update-Weg: git pull && sudo ./install.sh
## Zwei Fallgruben, die beim Testen auffielen - beide meine eigenen
- --nur-pruefen verlangte root und brach ab. Ein Pruef-Modus, der nichts
aendert, darf daran nicht scheitern - sonst kann man vor der Installation
nicht nachsehen, ob alles passt. Behoben.
- .env.example hatte OPTICAL_SG=/dev/sg1 UNKOMMENTIERT vorbelegt. Damit haette
der Installer den erkannten Wert nicht eingetragen ("steht schon drin") und
auf jedem fremden Host still eine kaputte Konfiguration hinterlassen - genau
das, was er verhindern soll. Beide Geraetezeilen sind jetzt auskommentiert;
Compose hat ohnehin Vorgaben. Dazu eine Gegenprobe im Skript: zeigt ein
wirksamer Wert auf ein Geraet, das es hier nicht gibt (".env von einem
anderen Rechner"), wird das benannt statt kryptisch von Docker gemeldet.
## README neu aufgebaut
Vorher 293 Zeilen, in denen der Schnellstart zwischen lsscsi, sg-Knoten,
USB-Passthrough und mount --make-rshared begraben war. Jetzt: Installation in
zwei Zeilen oben, dann eine Tabelle "Wenn etwas nicht geht" mit den vier
Faellen, die praktisch alles abdecken. Alles Technische steht darunter in
aufklappbaren Abschnitten - inklusive der Handarbeits-Variante fuer die, die
sie wollen.
NEU und ausdruecklich gewuenscht: Abschnitt "Rippy schneller machen" mit dem
VM-CPU-Typ. Erklaert, warum Virtualisierer eine generische CPU ohne AVX2
geben, was das kostet (gemessene 28-55 h je 4K-Film), die genauen Schritte in
Proxmox (herunterfahren - Hardware/Processors/Type auf 'host' - starten, bzw.
qm set <vmid> --cpu host), warum ein Neustart von innen NICHT genuegt, und wie
man nachprueft: Rippy zeigt die Vektorbefehle seit v3.14 selbst an. Dazu der
Nachteil (keine Live-Migration auf andere CPUs) und die Alternative x86-64-v3
fuer Cluster.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,291 +2,374 @@
|
||||
|
||||
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.
|
||||
abgelegt, wo du willst (lokal, NAS, jede Freigabe). Modernes Web-UI, komplett
|
||||
in Docker, komplett lokal — keine Cloud, keine Telemetrie.
|
||||
|
||||
## Schnellstart
|
||||
---
|
||||
|
||||
Voraussetzungen: Docker + Docker Compose, ein optisches Laufwerk am Host.
|
||||
## Installation
|
||||
|
||||
Du brauchst: einen **Linux-Rechner mit Docker** und ein **optisches Laufwerk**.
|
||||
|
||||
```bash
|
||||
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)
|
||||
sudo ./install.sh
|
||||
```
|
||||
|
||||
Das war es. Am Ende steht die Adresse im Terminal — im Browser öffnen, der
|
||||
**Einrichtungs-Assistent** übernimmt den Rest.
|
||||
|
||||
Zuerst nur nachsehen, ob alles passt, ohne etwas zu ändern:
|
||||
|
||||
```bash
|
||||
./install.sh --nur-pruefen
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary><b>Was <code>install.sh</code> für dich macht</b> (aufklappen)</summary>
|
||||
|
||||
Es nimmt genau die Schritte ab, an denen man vorher scheitern konnte:
|
||||
|
||||
1. **Prüft die Voraussetzungen** — Linux, Docker, Compose. Fehlt etwas, steht
|
||||
der Installationsbefehl dabei.
|
||||
2. **Findet dein Laufwerk selbst.** MakeMKV braucht **zwei** Geräteknoten:
|
||||
`/dev/srN` und den passenden `/dev/sgM`. Welche sg-Nummer dazugehört, ist
|
||||
**je Rechner anders** — das Skript gleicht sie über die SCSI-Adresse ab
|
||||
statt zu raten. (Genau daran ging vorher die Handarbeit schief.)
|
||||
3. **Legt die Verzeichnisse an** (`/srv/rippy/media` für die Filme,
|
||||
`/srv/rippy/makemkv` für MakeMKVs Daten).
|
||||
4. **Richtet die Mount-Propagation ein** und macht sie neustart-fest — sonst
|
||||
funktioniert das Einhängen von NAS-Freigaben aus dem UI nach jedem Reboot
|
||||
nicht mehr.
|
||||
5. **Schreibt die `.env`** mit den gefundenen Werten. Bestehende Werte werden
|
||||
**nie** überschrieben.
|
||||
6. **Baut und startet** alles.
|
||||
|
||||
Das Skript ist **wiederholbar**: mehrmals ausführen ändert nichts kaputt. Es
|
||||
ist auch der Update-Weg — siehe unten.
|
||||
|
||||
</details>
|
||||
|
||||
### Aktualisieren
|
||||
|
||||
```bash
|
||||
git pull && sudo ./install.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Wenn etwas nicht geht
|
||||
|
||||
Die vier Fälle, die praktisch alles abdecken:
|
||||
|
||||
| Symptom | Ursache & Lösung |
|
||||
|---|---|
|
||||
| **„Kein optisches Laufwerk gefunden"** | In einer **VM**? Das Laufwerk muss per **USB-Passthrough** durchgereicht werden, nicht als emuliertes CD-ROM (`media=cdrom`) — das kann keine SCSI-Kommandos, MakeMKV sieht es nie. Proxmox: `qm set <vmid> -usb0 host=<hersteller>:<produkt>,usb3=1`. Auf echter Hardware: `ls /dev/sr*` prüfen. |
|
||||
| **Build bricht beim MakeMKV-Download ab** | Cloudflare drosselt manchmal. Tarballs von makemkv.com/download händisch nach `docker/worker/vendor/` legen, dann `sudo ./install.sh` erneut — der Build nimmt sie dann von dort. |
|
||||
| **Kompression läuft ewig** | Deine CPU kann kein AVX2. Rippy zeigt das jetzt selbst an (Einstellungen → System, „Vektorbefehle"). Siehe **[Rippy schneller machen](#rippy-schneller-machen)**. |
|
||||
| **4K-UHD: „The volume key is unknown"** | Erwartbar und **kein Fehler in Rippy**. Siehe **[4K-UHD](#4k-uhd)**. |
|
||||
|
||||
Logs ansehen: `docker compose logs -f` · Status: `docker compose ps`
|
||||
|
||||
---
|
||||
|
||||
## Rippy schneller machen
|
||||
|
||||
**Läuft Rippy in einer virtuellen Maschine, ist das hier der wirksamste
|
||||
Handgriff überhaupt** — und er kostet fünf Minuten.
|
||||
|
||||
Virtualisierer geben der VM standardmäßig eine **generische CPU** (bei
|
||||
Proxmox/KVM heißt sie `kvm64` bzw. `qemu64`). Die kann absichtlich nur alte
|
||||
Befehlssätze, damit sich eine VM zwischen verschiedenen Wirten verschieben
|
||||
lässt. Der Preis: **kein AVX2** — und genau davon lebt der Video-Encoder x265.
|
||||
|
||||
Was das ausmacht, ist auf der Rippy-Maschine gemessen worden: ein 4K-Film in
|
||||
H.265 brauchte **28 bis 55 Stunden**, bei voll ausgelasteten Kernen. Mit AVX2
|
||||
sind typisch **2- bis 4-mal schneller** drin.
|
||||
|
||||
**So stellst du es um (Proxmox):**
|
||||
|
||||
1. VM **herunterfahren.** Ein Neustart von innen genügt nicht — Proxmox
|
||||
übernimmt Hardware-Änderungen nur bei einem echten Stopp.
|
||||
2. Im Web-UI: VM auswählen → **Hardware** → **Processors** → Doppelklick →
|
||||
**Type** auf **`host`** stellen → OK.
|
||||
Oder auf der Proxmox-Konsole:
|
||||
```bash
|
||||
qm set <vmid> --cpu host
|
||||
```
|
||||
3. VM **starten.**
|
||||
|
||||
**Nachprüfen — Rippy sagt es dir selbst:** Einstellungen → System, Zeile
|
||||
„Vektorbefehle" beim Worker. Steht dort jetzt `avx2` oder `avx512f` statt
|
||||
`sse4_2`, hat es geklappt und die amberfarbene Warnung verschwindet.
|
||||
Auf der Kommandozeile: `grep -o avx2 /proc/cpuinfo | head -1`.
|
||||
|
||||
<details>
|
||||
<summary>Nachteile von <code>host</code> — der Vollständigkeit halber</summary>
|
||||
|
||||
Die VM sieht dann die echte CPU. Dadurch lässt sie sich nicht mehr auf einen
|
||||
Wirt mit anderem Prozessor **live** verschieben. In einem Heim-Cluster mit
|
||||
einem einzigen Wirt ist das ohne Bedeutung. Wer mehrere Wirte hat und
|
||||
Live-Migration nutzt, wählt statt `host` das neueste Modell, das **alle**
|
||||
Wirte beherrschen (z. B. `x86-64-v3` — das enthält AVX2).
|
||||
|
||||
</details>
|
||||
|
||||
**Kein AVX2 möglich?** Dann zwei Auswege, beide im UI:
|
||||
- **4K nicht komprimieren** (Einstellungen → Verarbeitung → Preset für 4K-UHD →
|
||||
„Nicht komprimieren"). Die verlustfreie Datei bleibt stehen: beste Qualität,
|
||||
20–100 GB je Film. Der Einrichtungs-Assistent wählt das bei schwacher CPU
|
||||
von selbst.
|
||||
- **Andere Maschine komprimieren lassen** — siehe
|
||||
[Weitere Maschinen als Worker](#weitere-maschinen-als-worker).
|
||||
|
||||
---
|
||||
|
||||
## Der Alltag
|
||||
|
||||
### Rippen
|
||||
|
||||
Disc einlegen. Rippy erkennt sie, zeigt Titel und Poster, du wählst das Ziel —
|
||||
oder du stellst die **Vollautomatik** an (Einstellungen → Ripping) und es
|
||||
läuft ohne Nachfrage los.
|
||||
|
||||
- **Alle Tonspuren und Untertitel bleiben erhalten** (wichtig für Anime/O-Ton).
|
||||
- **Nur Hauptfilm** auf Wunsch — der längste Titel, Extras bleiben weg.
|
||||
- **Serien:** Serienname + Staffel angeben → Ablage `<Serie>/Season NN`, und
|
||||
die Episoden werden per Laufzeitabgleich (TMDB) zu „Serie S01E02.mkv"
|
||||
benannt. Nur bei eindeutiger Zuordnung, sonst bleiben die Namen — mit Log.
|
||||
- **Audio-CDs** laufen über abcde zu FLAC mit MusicBrainz-Tags.
|
||||
- Schon gerippte Discs erkennt Rippy am Fingerabdruck und warnt.
|
||||
- Vor dem Start wird der freie Platz gegen die Disc-Größe geprüft.
|
||||
|
||||
### Kompression
|
||||
|
||||
Ein **eigenes Preset je Disc-Typ** (Einstellungen → Verarbeitung) — Rippy
|
||||
erkennt den Typ selbst. Das ist wichtig, weil ein 1080p-Preset eine 4K-UHD
|
||||
stillschweigend herunterrechnet und eine DVD sinnlos hochskaliert.
|
||||
|
||||
Jeder Typ kann auch auf **„Nicht komprimieren"** stehen: dann bleibt der
|
||||
verlustfreie Rip liegen. Sinnvoll für 4K, wenn die Ablage groß genug ist.
|
||||
|
||||
Die Rohdatei wird erst nach erfolgreicher Kompression gelöscht („Original
|
||||
behalten" als Option). Fehlgeschlagene Kompressionen lassen sich ohne
|
||||
Neu-Rip erneut anstoßen.
|
||||
|
||||
### Ablage & Media-Server
|
||||
|
||||
Einstellungen → Ripping: dein System wählen (Jellyfin, Emby, Kodi, Plex oder
|
||||
keins). Fertige Rips heißen dann „Titel (Jahr)"; für Jellyfin/Emby/Kodi legt
|
||||
Rippy zusätzlich `movie.nfo` + `poster.jpg` dazu. Bei **Jellyfin/Emby** mit
|
||||
Server-URL + API-Key stößt Rippy nach jedem Rip sofort einen
|
||||
Bibliotheks-Scan an — Disc rein, Film erscheint im Server.
|
||||
|
||||
**NAS-Freigaben** hängst du unter Einstellungen → Speicherziele direkt aus dem
|
||||
UI ein (NFS/SMB). Sie erscheinen sofort in der Ziel-Auswahl und werden beim
|
||||
Start automatisch wieder verbunden.
|
||||
⚠️ Zugangsdaten liegen unverschlüsselt in der lokalen Datenbank — 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. Rippy erkennt den Dienst an der URL selbst:
|
||||
|
||||
| Dienst | URL-Beispiel |
|
||||
|---|---|
|
||||
| Discord | `https://discord.com/api/webhooks/…` |
|
||||
| Slack | `https://hooks.slack.com/services/…` |
|
||||
| ntfy (Handy-Push) | `https://ntfy.sh/mein-geheimes-thema` |
|
||||
| Eigenes (Home Assistant, n8n, …) | beliebige HTTPS-URL |
|
||||
|
||||
---
|
||||
|
||||
## 4K-UHD
|
||||
|
||||
4K braucht **zwei** Dinge, die normale BD/DVD nicht brauchen: ein
|
||||
**LibreDrive-fähiges Laufwerk** (MakeMKV-Forum: „Ultimate UHD Drives Flashing
|
||||
Guide") **und** den **Schlüssel dieser Pressung**.
|
||||
|
||||
**Der Schlüssel ist die eigentliche Hürde — aus einem überraschenden Grund.**
|
||||
Am 25.07.2026 auf beiden Maschinen gemessen (Akira UHD, MKB v76, Pressung
|
||||
Dezember 2020): Laufwerk und MakeMKV waren in Ordnung — „Using LibreDrive mode
|
||||
(v06.3)", die Disc wurde gelesen — und trotzdem kam „The volume key is unknown
|
||||
for this disc".
|
||||
|
||||
> **`makemkvcon` unter Linux holt Disc-Schlüssel nie aus dem Netz.
|
||||
> Die Windows-Version tut es.**
|
||||
|
||||
Gemessen: Linux baute in keinem einzigen Lauf eine Verbindung nach draußen auf
|
||||
— geprüft mit leerem und gefülltem Schlüsselspeicher, mit und ohne `--noscan`,
|
||||
mit `dev:` und `disc:`, und mit erzwungener frischer Prüfung. Dieselbe Disc am
|
||||
selben Laufwerk unter Windows: „Lade aktuelle HK …", Verbindung zum
|
||||
Schlüssel-Server, Disc geht auf. **Ein MakeMKV-Update ändert daran nichts, und
|
||||
es ist kein Fehler in Rippy.**
|
||||
|
||||
**Der Weg drumherum** (Einstellungen → System):
|
||||
|
||||
1. MakeMKV auf einem **Windows-PC** installieren (gleicher Beta-Key).
|
||||
2. Laufwerk anstecken, Disc **einmal öffnen** — dabei lädt MakeMKV die
|
||||
Schlüssel nach.
|
||||
3. In MakeMKV unter *Preferences → General* das „MakeMKV data directory"
|
||||
nachschlagen und die Datei **`_private_data.tar`** daraus bei Rippy
|
||||
hochladen.
|
||||
|
||||
Rippy zeigt an, **wie viele Disc-Schlüssel** dieser Worker kennt. Steht dort 0,
|
||||
scheitert jede unbekannte UHD. Für neue Discs den Schritt gelegentlich
|
||||
wiederholen. Rippy prüft die Datei und lehnt sie ab, wenn kein einziger
|
||||
Schlüssel drinsteckt — sonst ändert sich nichts und niemand versteht, warum.
|
||||
|
||||
**Kennt MakeMKV die Pressung selbst nicht**, bleibt die **`KEYDB.cfg`** als
|
||||
Notnagel (gleicher Tab). Und: **AACS-Dumps herunterladen** — den Dump legt
|
||||
MakeMKV bei jeder unbekannten Disc selbst ab, und genau den braucht man, wenn
|
||||
man im MakeMKV-Forum um den Schlüssel für eine neue Pressung bittet.
|
||||
|
||||
> ⚠️ **Rippy liefert keine Disc-Schlüssel mit, lädt keine herunter und
|
||||
> verteilt keine.** Rippy hält nur den Platz für eine Datei bereit, die du
|
||||
> selbst mitbringst, und zeigt ehrlich an, was dort liegt. Der
|
||||
> MakeMKV-**Beta-Key** ist die Lizenz für die *Software* — zwei völlig
|
||||
> verschiedene Dinge.
|
||||
|
||||
⚠️ UHD-Rohdaten sind bis 100 GB groß. Ist die Platte zu klein, lege das
|
||||
**Arbeitsverzeichnis** (Einstellungen → Verarbeitung) auf eine eingehängte
|
||||
Freigabe. Rippy bricht sonst **vor** dem Rip mit Klartext ab statt nach 40 GB
|
||||
mit voller Platte.
|
||||
|
||||
---
|
||||
|
||||
## Weitere Maschinen als Worker
|
||||
|
||||
Die Kompression läuft als eigener Task auf der Queue `transcode` — **jede**
|
||||
Maschine im Netz kann sie übernehmen. Einstellungen → Worker zeigt für beide
|
||||
Varianten einen Copy-Paste-Befehl:
|
||||
|
||||
- **Windows (nativ, ohne Docker)** — braucht nur Python. Der Installer kommt
|
||||
als fertige `.exe` von Rippy selbst; Worker-Code und HandBrake holt er zur
|
||||
Laufzeit.
|
||||
- **Linux (Docker)** — `deploy/remote-transcode-worker.yml`.
|
||||
|
||||
Rippy zeigt für jeden Worker an, **was er wirklich kann**: Encoder, Kernzahl,
|
||||
Vektorbefehle. Für einen **GPU-Worker** wichtig: das Bild braucht ein
|
||||
HandBrake mit `nvenc_*` bzw. `qsv_*` — die Anzeige nennt HandBrakes
|
||||
ungefilterte Auskunft, damit du das nachprüfen kannst. Das mitgelieferte
|
||||
Linux-Worker-Bild hat **keinen** Hardware-Encoder.
|
||||
|
||||
Ohne Zusatz-Worker macht der eingebaute CPU-Worker alles selbst — Rippy bleibt
|
||||
All-in-one.
|
||||
|
||||
---
|
||||
|
||||
## Für Fortgeschrittene
|
||||
|
||||
<details>
|
||||
<summary><b>Umgebungsvariablen (.env)</b></summary>
|
||||
|
||||
`install.sh` füllt die hostabhängigen Werte selbst. Alles hier ist optional —
|
||||
UI-Einstellungen überstimmen die Env-Variablen.
|
||||
|
||||
| Variable | Zweck |
|
||||
|---|---|
|
||||
| `TMDB_API_KEY` | Metadaten (deutsche Texte). Bequemer im Assistenten — beide Key-Arten gehen (v3-Schlüssel und v4-Token) |
|
||||
| `OMDB_API_KEY` | zweite Metadaten-Quelle (Fallback) |
|
||||
| `THETVDB_API_KEY` | Serien-Fallback |
|
||||
| `WORKER_NAME` | Anzeigename des eingebauten Workers (Standard `rippy-hauptworker`) |
|
||||
| `MAKEMKV_APP_KEY` | MakeMKV-Beta-Key. Bequemer im UI unter Einstellungen → System — gilt ab dem nächsten Rip, ohne Rebuild |
|
||||
| `MAKEMKV_VERSION` | MakeMKV-Version für den Image-Build |
|
||||
| `MAKEMKV_URL_BASE` | alternative Download-Quelle für den Build |
|
||||
| `MAKEMKV_DATA_HOST` | Host-Verzeichnis für MakeMKVs Daten (Standard `/srv/rippy/makemkv`) — Schlüsselspeicher, `KEYDB.cfg`, AACS-Dumps. Persistent, überlebt jeden Rebuild |
|
||||
| `OPTICAL_SR` / `OPTICAL_SG` | Geräteknoten des Laufwerks. **Findet `install.sh` selbst** |
|
||||
| `POSTGRES_PASSWORD` | DB-Passwort (Standard `rippy`) |
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Installation ohne install.sh (von Hand)</b></summary>
|
||||
|
||||
Falls du jeden Schritt selbst machen willst:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
mkdir -p /srv/rippy/media /srv/rippy/makemkv
|
||||
|
||||
# Laufwerksknoten ermitteln — die sg-Nummer ist je Host anders!
|
||||
lsscsi -g # zeigt Modell + zugehoerigen /dev/sgN
|
||||
# in die .env: OPTICAL_SR=/dev/sr0 und OPTICAL_SG=/dev/sgN
|
||||
|
||||
# Nur falls 'docker compose up' meldet:
|
||||
# "path ... is mounted on / but it is not a shared mount"
|
||||
mount --bind /srv/rippy/media /srv/rippy/media
|
||||
mount --make-rshared /srv/rippy/media # neustart-fest als systemd-.mount-Unit
|
||||
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
Dann `http://<host>` öffnen — der **Einrichtungs-Assistent** startet beim
|
||||
ersten Mal automatisch (API-Keys, Verarbeitung, erkannte Hardware).
|
||||
Braucht klassisches Linux-Docker mit `SYS_ADMIN` — nicht Docker Desktop,
|
||||
rootless oder Podman. Die Mount-Propagation ist nur für das Einhängen von
|
||||
NAS-Freigaben **aus dem UI** nötig; Freigaben auf dem Host einhängen geht immer.
|
||||
|
||||
### Laufwerk anpassen
|
||||
</details>
|
||||
|
||||
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`).
|
||||
<details>
|
||||
<summary><b>Wie es intern funktioniert</b></summary>
|
||||
|
||||
Ermitteln, welche Knoten dein Blu-ray/DVD-Laufwerk hat:
|
||||
```bash
|
||||
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):
|
||||
```bash
|
||||
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.)
|
||||
1. **Disc-Wache** — ioctl-Polling, kein udev. Im Container läuft kein udevd,
|
||||
die udev-Datenbank ist leer; `udevadm info` liefert dort prinzipbedingt
|
||||
nichts.
|
||||
2. **Rip** — MakeMKV, verlustfrei. Der einzige Weg durch AACS: HandBrake kann
|
||||
verschlüsselte Discs nicht lesen, deshalb sind es zwingend zwei Stufen.
|
||||
3. **Kompression** — HandBrake als eigener Celery-Task auf eigener Queue,
|
||||
deshalb an andere Maschinen routbar.
|
||||
4. **Metadaten** — Volume-Label → TMDB → OMDb → MyAnimeList, mit
|
||||
Ähnlichkeits-Bewertung und Korrektur-Popup an der Disc-Karte.
|
||||
|
||||
**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.
|
||||
</details>
|
||||
|
||||
## Wie es funktioniert
|
||||
<details>
|
||||
<summary><b>Härtung für exponierte Netze</b></summary>
|
||||
|
||||
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,
|
||||
**je Disc-Typ ein eigenes Preset** (Einstellungen → Verarbeitung) —
|
||||
Rippy kennt den Typ und wählt selbst. Wichtig, weil ein 1080p-Preset
|
||||
eine 4K-UHD stillschweigend herunterrechnet und ein 1080p-Preset eine
|
||||
DVD sinnlos hochskaliert. Sind die drei Felder nie gespeichert worden,
|
||||
gilt weiter das alte allgemeine Preset — Bestandsinstallationen ändern
|
||||
ihr Verhalten also nicht von selbst.
|
||||
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 **zwei** Dinge — ein LibreDrive-fähiges Laufwerk
|
||||
(MakeMKV-Forum: „Ultimate UHD Drives Flashing Guide") **und** einen
|
||||
passenden Disc-Schlüssel. Normale BD/DVD gehen mit jedem Laufwerk und
|
||||
ohne Schlüssel-Datei.
|
||||
**Der Schlüssel ist heute die eigentliche Hürde — und zwar aus einem
|
||||
überraschenden Grund.** Am 25.07.2026 auf beiden Maschinen gemessen
|
||||
(Akira UHD, MKB v76, Pressung Dezember 2020): Laufwerk und MakeMKV
|
||||
waren in Ordnung — „Using LibreDrive mode (v06.3)", die Disc wurde
|
||||
gelesen — und trotzdem kam „The volume key is unknown for this disc".
|
||||
Die Ursache:
|
||||
**`makemkvcon` unter Linux holt Disc-Schlüssel nie aus dem Netz. Die
|
||||
Windows-Version tut es.**
|
||||
Gemessen: Linux baute in keinem einzigen Lauf eine Verbindung nach
|
||||
draußen auf — geprüft mit leerem und mit gefülltem Schlüsselspeicher,
|
||||
mit und ohne `--noscan`, mit `dev:` und `disc:`, und mit erzwungener
|
||||
frischer Prüfung. Dieselbe Disc am selben Laufwerk unter Windows: „Lade
|
||||
aktuelle HK …", Verbindung zum Schlüssel-Server, Disc geht auf.
|
||||
Ein MakeMKV-Update ändert daran nichts, und es ist kein Fehler in
|
||||
Rippy.
|
||||
**Der Weg drumherum:** MakeMKV einmal auf einem Windows-PC die Disc
|
||||
öffnen lassen und die dabei gefüllte Datei `_private_data.tar` bei
|
||||
Rippy unter **Einstellungen → System** hochladen (siehe unten). Für
|
||||
Pressungen, die auch MakeMKV nicht kennt, bleibt die **`KEYDB.cfg`**
|
||||
als Notnagel.
|
||||
⚠️ **Rippy liefert keine Schlüssel mit, lädt keine herunter und
|
||||
verteilt keine.** Rippy stellt nur den Platz für eine Datei bereit, die
|
||||
du selbst mitbringst, und zeigt dir ehrlich an, was dort liegt.
|
||||
⚠️ 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.
|
||||
Rippy ist bewusst **Heimnetz-only**: keine Authentifizierung, und Redis +
|
||||
PostgreSQL veröffentlichen Ports für Remote-Worker. Im vertrauten LAN ein
|
||||
akzeptierter Kompromiss — **exponiere Rippy niemals ungeschützt an ein
|
||||
öffentliches Netz.**
|
||||
|
||||
## 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, Disc-Schlüssel & 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`.
|
||||
|
||||
**Disc-Schlüssel für 4K-UHD** — im selben Tab, nur für UHD nötig. Der
|
||||
Hauptweg zuerst:
|
||||
|
||||
- **Schlüsselspeicher (`_private_data.tar`)**: Rippy zeigt, **wie viele
|
||||
Disc-Schlüssel** dieser Worker kennt. Steht dort 0, scheitert jede
|
||||
unbekannte UHD-Disc.
|
||||
**So füllst du ihn:** MakeMKV auf einem Windows-PC installieren
|
||||
(gleicher Beta-Key), Laufwerk anstecken, Disc einmal öffnen — dabei lädt
|
||||
MakeMKV die Schlüssel nach. Dann in MakeMKV unter *Preferences →
|
||||
General* das „MakeMKV data directory" nachschlagen und die Datei
|
||||
`_private_data.tar` daraus hier hochladen. Wirkt ab dem nächsten Rip;
|
||||
für neue Discs gelegentlich wiederholen.
|
||||
Rippy prüft die Datei und lehnt sie ab, wenn kein einziger Schlüssel
|
||||
drinsteckt — sonst ändert sich nichts und niemand versteht, warum.
|
||||
- **`KEYDB.cfg`** (Notnagel): nur nötig, wenn eine Pressung auch mit
|
||||
gefülltem Speicher nicht aufgeht, MakeMKV sie also selbst nicht kennt.
|
||||
Hochladen, Status und Entfernen genau wie oben.
|
||||
- **AACS-Dumps herunterladen**: MakeMKV legt bei jeder unbekannten Disc
|
||||
selbst einen Dump ab. Genau den braucht man, wenn man im MakeMKV-Forum
|
||||
um den Schlüssel für eine neue Pressung bittet — hier holst du ihn dir
|
||||
aus dem Container, ohne SSH.
|
||||
|
||||
Der Beta-Key ist die **Lizenz für die Software**, der Schlüsselspeicher
|
||||
und die `KEYDB.cfg` sind **Disc-Schlüssel** — zwei völlig verschiedene
|
||||
Dinge. **Rippy liefert und lädt keine Disc-Schlüssel**, es hält nur ein
|
||||
persistentes Verzeichnis dafür bereit (`MAKEMKV_DATA_HOST`, siehe Tabelle
|
||||
unten) — rebuild-fest, damit deine Dateien einen
|
||||
`docker compose build` überleben. Der Schlüsselspeicher ist der
|
||||
Zwischenspeicher **deiner eigenen** MakeMKV-Installation.
|
||||
|
||||
**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`.
|
||||
⚠️ **Richtigstellung (25.07.2026):** Hier stand früher, neue MakeMKV-
|
||||
Versionen brächten „auch die neueste Disc-Schlüssel-Datenbank mit". Das
|
||||
ist widerlegt — MakeMKV liefert überhaupt keine Disc-Schlüssel mit, es
|
||||
holt sie zur Laufzeit. Und die Linux-Version holt sie nie. Ein Update
|
||||
lohnt für Programmfehler und neue Laufwerke, hilft aber NICHT gegen „The
|
||||
volume key is unknown". Dafür brauchst du den Schlüsselspeicher (siehe
|
||||
oben).
|
||||
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 |
|
||||
| `MAKEMKV_DATA_HOST` | optional | Host-Verzeichnis für MakeMKVs Daten (Default `/srv/rippy/makemkv`) — hier liegen dein Schlüsselspeicher `_private_data.tar`, eine etwaige `KEYDB.cfg` und die AACS-Dumps; persistent, überlebt jeden Rebuild |
|
||||
| `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:
|
||||
```bash
|
||||
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.
|
||||
4. MakeMKV-Datenverzeichnis anlegen: `mkdir -p /srv/rippy/makemkv` (oder
|
||||
eigenen Pfad über `MAKEMKV_DATA_HOST` in der `.env`). Dort liegen
|
||||
MakeMKVs Programmzustand, die AACS-Dumps und — falls du 4K-UHD rippst —
|
||||
dein Schlüsselspeicher (`_private_data.tar`) sowie eine etwaige
|
||||
`KEYDB.cfg`. Das Verzeichnis gehört dem Host, damit ein
|
||||
`docker compose build` deine Dateien nicht wegwirft.
|
||||
|
||||
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
|
||||
- **Zugriff kapseln:** UI und API (`:8000`) hinter einen Reverse-Proxy mit Auth
|
||||
oder nur über VPN erreichbar machen.
|
||||
- **DB/Broker abschotten:** starkes `POSTGRES_PASSWORD`; die Ports
|
||||
`5432`/`6379` nur an ein internes/VPN-Interface binden statt an `0.0.0.0`;
|
||||
Redis mit `--requirepass` starten und das Passwort in `REDIS_URL` ergänzen.
|
||||
- **CORS:** `main.py` erlaubt `*` (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.
|
||||
- **NAS-Zugangsdaten** liegen im Klartext in der DB — ein weiterer Grund, den
|
||||
DB-Port nie offen ins unsichere Netz zu hängen.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Updates der Werkzeuge</b></summary>
|
||||
|
||||
„Auf Updates prüfen" (Einstellungen → System) vergleicht mit makemkv.com und
|
||||
den offiziellen HandBrake-Releases, 12 h gecacht.
|
||||
|
||||
**MakeMKV** aktualisieren: `MAKEMKV_VERSION=x.y.z` in die `.env`, dann
|
||||
`sudo ./install.sh`. Der Beta-Key wechselt etwa monatlich (Forum-Thread
|
||||
t=1053) und wird im UI gepflegt — ohne Rebuild.
|
||||
|
||||
**HandBrake** kommt im Docker-Worker bewusst aus Debian (stabil, hinkt der
|
||||
offiziellen Version hinterher); der native Windows-Worker nutzt die aktuelle.
|
||||
|
||||
⚠️ Ein MakeMKV-Update hilft **nicht** gegen „The volume key is unknown" —
|
||||
MakeMKV liefert überhaupt keine Disc-Schlüssel mit, es holt sie zur Laufzeit,
|
||||
und die Linux-Version holt sie nie. Siehe [4K-UHD](#4k-uhd).
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
## 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.
|
||||
einen Branch, `main` — die Ampel prüft nur, deployt wird direkt aus `main`.
|
||||
Rot heißt: nicht deployen.
|
||||
|
||||
Regeln für Beiträge: [AGENTS.md](AGENTS.md) · Konzept: [KONZEPT.md](KONZEPT.md) ·
|
||||
Fahrplan: [ROADMAP.md](ROADMAP.md)
|
||||
Fahrplan: [ROADMAP.md](ROADMAP.md) · Stand: [SAVEPOINT.md](SAVEPOINT.md)
|
||||
|
||||
Reference in New Issue
Block a user