Test
This commit is contained in:
30
README.md
30
README.md
@@ -2,13 +2,28 @@
|
||||
|
||||
Ripster ist eine lokale Web-Anwendung für halbautomatisches Disc-Ripping mit MakeMKV + HandBrake inklusive Metadaten-Auswahl, Titel-/Spurprüfung und Job-Historie.
|
||||
|
||||
---
|
||||
|
||||
> **Neu seit letztem Release**
|
||||
>
|
||||
> - **Cron-Job-System** – Skripte und Skript-Ketten zeitgesteuert ausführen; eigener Expression-Parser, Ausführungs-Logs, manuelle Auslösung, PushOver-Integration
|
||||
> - **DVD-Erkennung verbessert** – robuste Media-Profil-Erkennung (Blu-ray / DVD / CD) aus UDF/ISO9660-Dateisystemtyp, Laufwerk-Modell und Disc-Label
|
||||
> - **Pre-Encode-Ausführungen** – Skripte und Ketten können nun auch *vor* dem Encode-Schritt ausgeführt werden (zusätzlich zu Post-Encode)
|
||||
> - **Sortierbare Skripte & Ketten** – Reihenfolge über Drag & Drop festlegen; wird persistent in der Datenbank gespeichert
|
||||
> - **`rip_successful`-Flag in Jobs** – separates Feld zur Nachverfolgung ob der Rip-Schritt abgeschlossen wurde (unabhängig vom Encode-Status)
|
||||
|
||||
---
|
||||
|
||||
## Was Ripster kann
|
||||
|
||||
- Disc-Erkennung mit Pipeline-Status in Echtzeit (WebSocket)
|
||||
- Robuste Erkennung von Blu-ray, DVD und CD (UDF/ISO9660-Heuristik + Laufwerk-Modell)
|
||||
- Metadaten-Suche und Zuordnung über OMDb
|
||||
- MakeMKV-Analyse und Rip (MKV oder Backup-Modus)
|
||||
- HandBrake-Encode mit Preset + Extra-Args + Track-Override
|
||||
- Manuelle Playlist-/Titel-Auswahl bei komplexen Blu-rays
|
||||
- Pre- und Post-Encode-Skripte & Skript-Ketten (inkl. Drag-and-Drop-Sortierung)
|
||||
- Cron-Jobs: Skripte und Ketten zeitgesteuert ausführen (eigener Expression-Parser, Logs, PushOver)
|
||||
- Historie mit Re-Encode, Löschfunktionen und Detailansicht
|
||||
- Dateibasierte Logs (Backend + Job-Prozesslogs)
|
||||
|
||||
@@ -138,15 +153,30 @@ ripster/
|
||||
|
||||
## API-Überblick
|
||||
|
||||
**Pipeline**
|
||||
- `GET /api/pipeline/state`
|
||||
- `POST /api/pipeline/analyze`
|
||||
- `POST /api/pipeline/start/:jobId`
|
||||
- `POST /api/pipeline/confirm-encode/:jobId`
|
||||
|
||||
**History**
|
||||
- `GET /api/history`
|
||||
- `GET /api/history/:id`
|
||||
|
||||
**Settings**
|
||||
- `GET /api/settings`
|
||||
- `PUT /api/settings`
|
||||
|
||||
**Cron-Jobs** _(neu)_
|
||||
- `GET /api/crons`
|
||||
- `POST /api/crons`
|
||||
- `GET /api/crons/:id`
|
||||
- `PUT /api/crons/:id`
|
||||
- `DELETE /api/crons/:id`
|
||||
- `GET /api/crons/:id/logs`
|
||||
- `POST /api/crons/:id/run`
|
||||
- `POST /api/crons/validate-expression`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- WebSocket verbindet nicht:
|
||||
|
||||
@@ -81,15 +81,23 @@ else
|
||||
fi
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 3. Alte Installation entfernen
|
||||
# 3. Alle vorhandenen HandBrake-Installationen entfernen
|
||||
# --------------------------------------------------------------------------
|
||||
if command -v HandBrakeCLI &>/dev/null; then
|
||||
EXISTING=$(HandBrakeCLI --version 2>&1 | head -1)
|
||||
warn "Entferne vorhandenes HandBrakeCLI: ${EXISTING}"
|
||||
apt-get remove -y handbrake-cli 2>/dev/null || true
|
||||
snap remove handbrake-cli 2>/dev/null || true
|
||||
rm -f /usr/bin/HandBrakeCLI /usr/local/bin/HandBrakeCLI
|
||||
fi
|
||||
info "Entferne alle vorhandenen HandBrake-Installationen..."
|
||||
apt-get remove -y handbrake-cli handbrake 2>/dev/null || true
|
||||
snap remove handbrake-cli 2>/dev/null || true
|
||||
rm -f /usr/bin/HandBrakeCLI \
|
||||
/usr/local/bin/HandBrakeCLI \
|
||||
/snap/bin/handbrake-cli \
|
||||
/snap/bin/HandBrakeCLI
|
||||
while true; do
|
||||
FOUND=$(command -v HandBrakeCLI 2>/dev/null || true)
|
||||
[[ -z "$FOUND" ]] && break
|
||||
warn "Entferne: $FOUND"
|
||||
rm -f "$FOUND"
|
||||
done
|
||||
hash -r 2>/dev/null || true
|
||||
ok "Alte HandBrake-Installation(en) entfernt"
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# 4. Quellcode herunterladen
|
||||
|
||||
243
docs/api/crons.md
Normal file
243
docs/api/crons.md
Normal file
@@ -0,0 +1,243 @@
|
||||
# Cron API
|
||||
|
||||
Ripster enthält ein eingebautes Cron-System, mit dem **Skripte** und **Skript-Ketten** zeitgesteuert oder manuell ausgeführt werden können. Der Cron-Dienst benötigt keine externen Pakete – der Cron-Expression-Parser ist vollständig im Backend implementiert.
|
||||
|
||||
---
|
||||
|
||||
## Endpunkte
|
||||
|
||||
### `GET /api/crons`
|
||||
|
||||
Alle konfigurierten Cron-Jobs auflisten.
|
||||
|
||||
**Antwort:**
|
||||
|
||||
```json
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Nachtlauf Backup",
|
||||
"cronExpression": "0 2 * * *",
|
||||
"sourceType": "script",
|
||||
"sourceId": 3,
|
||||
"enabled": true,
|
||||
"pushoverEnabled": true,
|
||||
"lastRunAt": "2026-03-09T02:00:00.000Z",
|
||||
"lastRunStatus": "success",
|
||||
"nextRunAt": "2026-03-10T02:00:00.000Z",
|
||||
"createdAt": "2026-03-01T10:00:00.000Z",
|
||||
"updatedAt": "2026-03-09T02:00:00.000Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/crons`
|
||||
|
||||
Neuen Cron-Job anlegen.
|
||||
|
||||
**Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Nachtlauf Backup",
|
||||
"cronExpression": "0 2 * * *",
|
||||
"sourceType": "script",
|
||||
"sourceId": 3,
|
||||
"enabled": true,
|
||||
"pushoverEnabled": true
|
||||
}
|
||||
```
|
||||
|
||||
| Feld | Typ | Pflicht | Beschreibung |
|
||||
|------|-----|---------|-------------|
|
||||
| `name` | string | ✓ | Anzeigename |
|
||||
| `cronExpression` | string | ✓ | 5-Felder-Cron-Ausdruck (Minute Stunde Tag Monat Wochentag) |
|
||||
| `sourceType` | string | ✓ | `"script"` oder `"chain"` |
|
||||
| `sourceId` | number | ✓ | ID des Skripts bzw. der Kette |
|
||||
| `enabled` | boolean | – | Aktiviert (default: `true`) |
|
||||
| `pushoverEnabled` | boolean | – | PushOver-Benachrichtigung nach Ausführung (default: `true`) |
|
||||
|
||||
**Antwort:** `201 Created`
|
||||
|
||||
```json
|
||||
{ "job": { ... } }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `GET /api/crons/:id`
|
||||
|
||||
Einzelnen Cron-Job abrufen.
|
||||
|
||||
**Antwort:**
|
||||
|
||||
```json
|
||||
{ "job": { ... } }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `PUT /api/crons/:id`
|
||||
|
||||
Cron-Job aktualisieren. Body-Felder entsprechen `POST /api/crons`.
|
||||
|
||||
**Antwort:**
|
||||
|
||||
```json
|
||||
{ "job": { ... } }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `DELETE /api/crons/:id`
|
||||
|
||||
Cron-Job löschen.
|
||||
|
||||
**Antwort:**
|
||||
|
||||
```json
|
||||
{ "removed": { "id": 1 } }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `GET /api/crons/:id/logs`
|
||||
|
||||
Ausführungs-Logs eines Cron-Jobs abrufen.
|
||||
|
||||
**Query-Parameter:**
|
||||
|
||||
| Parameter | Typ | Default | Beschreibung |
|
||||
|-----------|-----|---------|-------------|
|
||||
| `limit` | number | 20 | Anzahl Einträge (max. 100) |
|
||||
|
||||
**Antwort:**
|
||||
|
||||
```json
|
||||
{
|
||||
"logs": [
|
||||
{
|
||||
"id": 42,
|
||||
"cronJobId": 1,
|
||||
"startedAt": "2026-03-09T02:00:01.000Z",
|
||||
"finishedAt": "2026-03-09T02:00:05.000Z",
|
||||
"status": "success",
|
||||
"exitCode": 0,
|
||||
"stdout": "Backup abgeschlossen.",
|
||||
"stderr": "",
|
||||
"triggeredBy": "cron"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
| Feld | Beschreibung |
|
||||
|------|-------------|
|
||||
| `status` | `"success"`, `"error"` oder `"running"` |
|
||||
| `triggeredBy` | `"cron"` (zeitgesteuert) oder `"manual"` (manuell ausgelöst) |
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/crons/:id/run`
|
||||
|
||||
Cron-Job sofort manuell auslösen (unabhängig vom Zeitplan).
|
||||
|
||||
**Antwort:**
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"exitCode": 0,
|
||||
"stdout": "...",
|
||||
"stderr": ""
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/crons/validate-expression`
|
||||
|
||||
Cron-Ausdruck validieren und nächsten Ausführungszeitpunkt berechnen.
|
||||
|
||||
**Body:**
|
||||
|
||||
```json
|
||||
{ "cronExpression": "*/15 * * * *" }
|
||||
```
|
||||
|
||||
**Antwort (gültig):**
|
||||
|
||||
```json
|
||||
{
|
||||
"valid": true,
|
||||
"nextRunAt": "2026-03-09T14:15:00.000Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Antwort (ungültig):**
|
||||
|
||||
```json
|
||||
{
|
||||
"valid": false,
|
||||
"error": "Cron-Ausdruck muss genau 5 Felder haben (Minute Stunde Tag Monat Wochentag).",
|
||||
"nextRunAt": null
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cron-Expression-Format
|
||||
|
||||
Ripster verwendet **5-Felder-Cron-Ausdrücke** (kein Sekunden-Feld):
|
||||
|
||||
```
|
||||
┌───────────── Minute (0-59)
|
||||
│ ┌────────── Stunde (0-23)
|
||||
│ │ ┌─────── Tag (1-31)
|
||||
│ │ │ ┌──── Monat (1-12)
|
||||
│ │ │ │ ┌─ Wochentag (0-7, 0 und 7 = Sonntag)
|
||||
│ │ │ │ │
|
||||
* * * * *
|
||||
```
|
||||
|
||||
### Beispiele
|
||||
|
||||
| Ausdruck | Beschreibung |
|
||||
|----------|-------------|
|
||||
| `0 2 * * *` | Täglich um 02:00 Uhr |
|
||||
| `*/15 * * * *` | Alle 15 Minuten |
|
||||
| `0 6 * * 1-5` | Montag–Freitag um 06:00 Uhr |
|
||||
| `30 23 * * 0` | Sonntags um 23:30 Uhr |
|
||||
| `0 0 1 * *` | Erster Tag des Monats um Mitternacht |
|
||||
|
||||
### Unterstützte Syntax
|
||||
|
||||
| Syntax | Bedeutung |
|
||||
|--------|----------|
|
||||
| `*` | Jeder Wert |
|
||||
| `*/n` | Jeder n-te Wert (Step) |
|
||||
| `a-b` | Bereich von a bis b |
|
||||
| `a,b,c` | Liste von Werten |
|
||||
| Kombinierbar | z. B. `1,5-10,*/3` |
|
||||
|
||||
---
|
||||
|
||||
## WebSocket-Event
|
||||
|
||||
Bei Änderungen an Cron-Jobs (Anlegen, Aktualisieren, Löschen) wird ein `CRON_JOBS_UPDATED`-Event gesendet:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "CRON_JOBS_UPDATED",
|
||||
"payload": {
|
||||
"action": "created",
|
||||
"id": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`action` ist `"created"`, `"updated"` oder `"deleted"`.
|
||||
@@ -42,6 +42,14 @@ Konfigurierbar über die Umgebungsvariable `PORT`.
|
||||
|
||||
[:octicons-arrow-right-24: History API](history.md)
|
||||
|
||||
- :material-clock-outline: **Cron API**
|
||||
|
||||
---
|
||||
|
||||
Cron-Jobs verwalten, manuell auslösen und Ausführungs-Logs abrufen.
|
||||
|
||||
[:octicons-arrow-right-24: Cron API](crons.md)
|
||||
|
||||
- :material-lightning-bolt: **WebSocket Events**
|
||||
|
||||
---
|
||||
|
||||
@@ -113,12 +113,19 @@ Disc erkannt.
|
||||
"payload": {
|
||||
"device": {
|
||||
"path": "/dev/sr0",
|
||||
"discLabel": "INCEPTION"
|
||||
"discLabel": "INCEPTION",
|
||||
"label": "INCEPTION",
|
||||
"model": "ASUS BW-16D1HT",
|
||||
"fstype": "udf",
|
||||
"mountpoint": null,
|
||||
"mediaProfile": "bluray"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`mediaProfile` ist `"bluray"`, `"dvd"`, `"other"` oder `null` (wenn nicht bestimmbar). Der Wert wird aus Dateisystemtyp (UDF/ISO9660), Laufwerk-Modell und Disc-Label abgeleitet.
|
||||
|
||||
### DISC_REMOVED
|
||||
|
||||
Disc entfernt.
|
||||
@@ -160,6 +167,22 @@ Fehler im Laufwerkserkennungsdienst.
|
||||
}
|
||||
```
|
||||
|
||||
### CRON_JOBS_UPDATED
|
||||
|
||||
Wird gesendet, wenn ein Cron-Job angelegt, aktualisiert oder gelöscht wurde.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "CRON_JOBS_UPDATED",
|
||||
"payload": {
|
||||
"action": "created",
|
||||
"id": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`action` ist `"created"`, `"updated"` oder `"deleted"`.
|
||||
|
||||
---
|
||||
|
||||
## Reconnect-Verhalten
|
||||
|
||||
@@ -7,11 +7,15 @@ Ripster verwendet **SQLite3** als Datenbank. Die Datenbankdatei liegt unter `bac
|
||||
## Schema-Übersicht
|
||||
|
||||
```sql
|
||||
-- Vier Haupt-Tabellen
|
||||
settings_schema -- Einstellungs-Definitionen
|
||||
settings_values -- Benutzer-Werte
|
||||
jobs -- Rip-Job-Datensätze
|
||||
pipeline_state -- Aktueller Pipeline-Zustand (Singleton)
|
||||
scripts -- Shell-Skripte für Pre-/Post-Encode-Ausführung
|
||||
script_chains -- Geordnete Ketten aus mehreren Skripten
|
||||
script_chain_steps -- Einzelschritte einer Skript-Kette
|
||||
cron_jobs -- Zeitgesteuerte Aufgaben (eigener Cron-Parser)
|
||||
cron_run_logs -- Ausführungs-Protokolle für Cron-Jobs
|
||||
```
|
||||
|
||||
---
|
||||
@@ -22,27 +26,31 @@ Die wichtigste Tabelle – speichert alle Ripping-Jobs.
|
||||
|
||||
```sql
|
||||
CREATE TABLE jobs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL,
|
||||
status TEXT NOT NULL, -- Aktueller Status
|
||||
title TEXT, -- Filmtitel (von OMDb)
|
||||
imdb_id TEXT, -- IMDb-ID
|
||||
omdb_year TEXT, -- Erscheinungsjahr
|
||||
omdb_type TEXT, -- movie/series
|
||||
omdb_poster TEXT, -- Poster-URL
|
||||
raw_path TEXT, -- Pfad zur Raw-MKV
|
||||
output_path TEXT, -- Pfad zur Ausgabedatei
|
||||
playlist TEXT, -- Gewählte Blu-ray Playlist
|
||||
makemkv_output TEXT, -- MakeMKV-Ausgabe (JSON)
|
||||
mediainfo_output TEXT, -- MediaInfo-Ausgabe (JSON)
|
||||
encode_plan TEXT, -- Encode-Plan (JSON)
|
||||
handbrake_log TEXT, -- HandBrake Log-Pfad
|
||||
error_message TEXT, -- Fehlermeldung bei ERROR
|
||||
error_details TEXT -- Detaillierte Fehler-Infos
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL,
|
||||
status TEXT NOT NULL, -- Aktueller Status
|
||||
title TEXT, -- Filmtitel (von OMDb)
|
||||
imdb_id TEXT, -- IMDb-ID
|
||||
omdb_year TEXT, -- Erscheinungsjahr
|
||||
omdb_type TEXT, -- movie/series
|
||||
omdb_poster TEXT, -- Poster-URL
|
||||
raw_path TEXT, -- Pfad zur Raw-MKV
|
||||
output_path TEXT, -- Pfad zur Ausgabedatei
|
||||
playlist TEXT, -- Gewählte Blu-ray Playlist
|
||||
rip_successful INTEGER NOT NULL DEFAULT 0, -- 1 wenn Rip abgeschlossen
|
||||
makemkv_output TEXT, -- MakeMKV-Ausgabe (JSON)
|
||||
mediainfo_output TEXT, -- MediaInfo-Ausgabe (JSON)
|
||||
encode_plan TEXT, -- Encode-Plan (JSON)
|
||||
handbrake_log TEXT, -- HandBrake Log-Pfad
|
||||
error_message TEXT, -- Fehlermeldung bei ERROR
|
||||
error_details TEXT -- Detaillierte Fehler-Infos
|
||||
);
|
||||
```
|
||||
|
||||
!!! info "rip_successful"
|
||||
Das Feld `rip_successful` wird auf `1` gesetzt, sobald MakeMKV den Rip-Schritt erfolgreich abgeschlossen hat – unabhängig davon, ob danach ein Encode-Fehler auftritt. Damit lässt sich in der History unterscheiden, ob eine Raw-Datei vorhanden ist.
|
||||
|
||||
### Job-Status-Werte
|
||||
|
||||
| Status | Beschreibung |
|
||||
@@ -111,6 +119,87 @@ CREATE TABLE settings_values (
|
||||
|
||||
---
|
||||
|
||||
## Tabelle: scripts
|
||||
|
||||
Verwaltet Shell-Skripte, die vor oder nach dem Encode-Schritt ausgeführt werden können.
|
||||
|
||||
```sql
|
||||
CREATE TABLE scripts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
script_body TEXT NOT NULL,
|
||||
order_index INTEGER NOT NULL DEFAULT 0, -- Sortierposition in der UI
|
||||
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
```
|
||||
|
||||
## Tabelle: script_chains
|
||||
|
||||
Geordnete Ketten, die mehrere Skripte sequenziell zusammenfassen.
|
||||
|
||||
```sql
|
||||
CREATE TABLE script_chains (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
order_index INTEGER NOT NULL DEFAULT 0, -- Sortierposition in der UI
|
||||
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE script_chain_steps (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
chain_id INTEGER NOT NULL REFERENCES script_chains(id) ON DELETE CASCADE,
|
||||
script_id INTEGER NOT NULL REFERENCES scripts(id) ON DELETE CASCADE,
|
||||
step_order INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
```
|
||||
|
||||
!!! info "Sortierung"
|
||||
`order_index` in `scripts` und `script_chains` wird über die API (`reorderScripts` / `reorderChains`) per Drag & Drop in der UI gesetzt und bleibt persistent gespeichert.
|
||||
|
||||
---
|
||||
|
||||
## Tabellen: cron_jobs & cron_run_logs
|
||||
|
||||
Speichern den Zeitplan und die Ausführungs-Historie des eingebauten Cron-Systems.
|
||||
|
||||
```sql
|
||||
CREATE TABLE cron_jobs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
cron_expression TEXT NOT NULL, -- 5-Felder-Ausdruck (min h d m wd)
|
||||
source_type TEXT NOT NULL, -- "script" oder "chain"
|
||||
source_id INTEGER NOT NULL, -- ID des Skripts/der Kette
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
pushover_enabled INTEGER NOT NULL DEFAULT 1,
|
||||
last_run_at TEXT,
|
||||
last_run_status TEXT, -- "success", "error", "running"
|
||||
next_run_at TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE cron_run_logs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
cron_job_id INTEGER NOT NULL REFERENCES cron_jobs(id) ON DELETE CASCADE,
|
||||
started_at TEXT NOT NULL,
|
||||
finished_at TEXT,
|
||||
status TEXT NOT NULL, -- "success", "error", "running"
|
||||
exit_code INTEGER,
|
||||
stdout TEXT,
|
||||
stderr TEXT,
|
||||
triggered_by TEXT NOT NULL DEFAULT 'cron', -- "cron" oder "manual"
|
||||
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
```
|
||||
|
||||
!!! info "Log-Rotation"
|
||||
Pro Cron-Job werden maximal **50 Log-Einträge** gespeichert; ältere Einträge werden automatisch gelöscht. Stdout/Stderr werden auf **100.000 Zeichen** begrenzt.
|
||||
|
||||
---
|
||||
|
||||
## Schema-Migrationen
|
||||
|
||||
`database.js` implementiert **automatische Migrationen**:
|
||||
@@ -126,7 +215,7 @@ Falls die Datenbankdatei korrupt ist:
|
||||
|
||||
```
|
||||
1. Korrupte Datei wird erkannt (Verbindungsfehler / Integritätsprüfung)
|
||||
2. Datei wird in /backend/data/quarantine/ verschoben
|
||||
2. Datei wird in backend/data/corrupt-backups/ verschoben
|
||||
3. Neue, leere Datenbank wird erstellt
|
||||
4. Schema wird neu initialisiert
|
||||
5. Log-Eintrag mit Warnung
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
# Post-Encode-Skripte
|
||||
# Encode-Skripte (Pre & Post)
|
||||
|
||||
Post-Encode-Skripte ermöglichen es, nach erfolgreichem Encoding automatisch beliebige Shell-Befehle oder Programme auszuführen – z. B. zum Verschieben von Dateien, Benachrichtigen externer Dienste oder Auslösen weiterer Verarbeitungsschritte.
|
||||
Ripster unterstützt **Pre-Encode-** und **Post-Encode-Ausführungen**: Beliebige Shell-Skripte oder Skript-Ketten können automatisch vor und/oder nach dem Encoding-Schritt laufen – z. B. zum Vorbereiten von Verzeichnissen, Verschieben von Dateien oder Benachrichtigen externer Dienste.
|
||||
|
||||
---
|
||||
|
||||
## Funktionsweise
|
||||
|
||||
Nach einem erfolgreich abgeschlossenen Encoding-Schritt führt Ripster die konfigurierten Skripte **sequenziell** in der festgelegten Reihenfolge aus:
|
||||
|
||||
```
|
||||
ENCODING abgeschlossen
|
||||
READY_TO_ENCODE
|
||||
↓
|
||||
Skript 1 ausführen ← Fehler? → Abbruch
|
||||
[Pre-Encode-Ausführungen] ← Fehler? → Abbruch
|
||||
Skript/Kette 1, 2, …
|
||||
↓
|
||||
Skript 2 ausführen ← Fehler? → Abbruch
|
||||
ENCODING
|
||||
↓
|
||||
...
|
||||
[Post-Encode-Ausführungen] ← Fehler? → Abbruch
|
||||
Skript/Kette 1, 2, …
|
||||
↓
|
||||
FINISHED
|
||||
```
|
||||
|
||||
!!! warning "Abbruch bei Fehler"
|
||||
Schlägt ein Skript fehl (Exit-Code ≠ 0), werden alle nachfolgenden Skripte **nicht mehr ausgeführt**.
|
||||
Der Job bleibt im Abschlusszustand `FINISHED`; der Fehler wird in Log/Status-Text und im `postEncodeScripts`-Summary festgehalten.
|
||||
Schlägt eine Ausführung fehl (Exit-Code ≠ 0), werden alle nachfolgenden Ausführungen der gleichen Phase **nicht mehr ausgeführt**.
|
||||
Der Job bleibt im Abschlusszustand `FINISHED`; der Fehler wird in Log/Status-Text und im Summary festgehalten.
|
||||
|
||||
---
|
||||
|
||||
## Skript-Verwaltung
|
||||
## Skript- und Ketten-Verwaltung
|
||||
|
||||
Skripte werden über die **Einstellungen-Seite** angelegt und verwaltet. Sie stehen danach in jedem Encode-Review zur Auswahl.
|
||||
Skripte und Skript-Ketten werden über die **Einstellungen-Seite** angelegt und verwaltet. Die Reihenfolge in der Liste kann per **Drag & Drop** geändert werden und bleibt persistent gespeichert.
|
||||
|
||||
### Skript anlegen
|
||||
|
||||
@@ -40,6 +40,10 @@ Navigiere zu **Einstellungen → Skripte** und klicke **"Neues Skript"**:
|
||||
| **Befehl** | Shell-Befehl oder Skriptpfad (z. B. `/home/michael/scripts/move-to-plex.sh`) |
|
||||
| **Beschreibung** | Optionale Erklärung |
|
||||
|
||||
### Skript-Ketten
|
||||
|
||||
Eine **Skript-Kette** fasst mehrere Skripte zu einer benannten Einheit zusammen, die als ganzes ausgewählt werden kann. Nützlich für wiederkehrende Kombinationen (z. B. „Move + Notify Plex + Webhook"). Ketten werden genauso wie einzelne Skripte im Review-Panel ausgewählt.
|
||||
|
||||
### Verfügbare Umgebungsvariablen
|
||||
|
||||
Jedes Skript wird mit folgenden Umgebungsvariablen aufgerufen:
|
||||
@@ -78,26 +82,35 @@ curl -s -X POST https://mein-webhook.example.com/ripster \
|
||||
|
||||
---
|
||||
|
||||
## Skript im Encode-Review auswählen
|
||||
## Im Encode-Review auswählen
|
||||
|
||||
Im `READY_TO_ENCODE`-Zustand zeigt das **MediaInfoReviewPanel** einen Skript-Abschnitt:
|
||||
Im `READY_TO_ENCODE`-Zustand zeigt das **MediaInfoReviewPanel** zwei Abschnitte:
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ Post-Encode-Skripte │
|
||||
│ Pre-Encode Ausführungen (optional) │
|
||||
├──────────────────────────────────────────────────────────┤
|
||||
│ Ausgewählte Skripte (Reihenfolge per Drag & Drop): │
|
||||
│ ≡ 1. Zu Plex verschieben [Entfernen]│
|
||||
│ ≡ 2. Webhook auslösen [Entfernen]│
|
||||
│ ≡ 1. Verzeichnis vorbereiten (Skript) [Entfernen]│
|
||||
├──────────────────────────────────────────────────────────┤
|
||||
│ Skript hinzufügen: [Zu Jellyfin verschieben ▾] [+ Hinzuf.]│
|
||||
│ Hinzufügen: [Skript/Kette auswählen ▾] [+ Hinzuf.]│
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ Post-Encode Ausführungen (optional) │
|
||||
├──────────────────────────────────────────────────────────┤
|
||||
│ ≡ 1. Zu Plex verschieben (Skript) [Entfernen]│
|
||||
│ ≡ 2. Notify-Kette (Kette) [Entfernen]│
|
||||
├──────────────────────────────────────────────────────────┤
|
||||
│ Hinzufügen: [Skript/Kette auswählen ▾] [+ Hinzuf.]│
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- **Reihenfolge** per Drag & Drop ändern
|
||||
- **Hinzufügen** aus der Dropdown-Liste aller konfigurierten Skripte
|
||||
- **Entfernen** einzelner Skripte aus der aktuellen Auswahl
|
||||
- Skripte können pro Job unterschiedlich gewählt werden
|
||||
- **Pre-Encode** und **Post-Encode** werden separat konfiguriert
|
||||
- Sowohl **einzelne Skripte** als auch **Skript-Ketten** können in beiden Phasen ausgewählt werden
|
||||
- **Reihenfolge** per Drag & Drop innerhalb jeder Phase ändern
|
||||
- **Hinzufügen** aus der Dropdown-Liste aller konfigurierten Skripte und Ketten
|
||||
- **Entfernen** einzelner Einträge
|
||||
- Auswahl kann pro Job frei variiert werden
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -183,6 +183,25 @@ install_makemkv() {
|
||||
warn "Beta-Key: https://www.makemkv.com/forum/viewtopic.php?t=1053"
|
||||
}
|
||||
|
||||
remove_all_handbrake() {
|
||||
info "Entferne alle vorhandenen HandBrake-Installationen..."
|
||||
apt-get remove -y handbrake-cli handbrake 2>/dev/null || true
|
||||
snap remove handbrake-cli 2>/dev/null || true
|
||||
rm -f /usr/bin/HandBrakeCLI \
|
||||
/usr/local/bin/HandBrakeCLI \
|
||||
/snap/bin/handbrake-cli \
|
||||
/snap/bin/HandBrakeCLI
|
||||
while true; do
|
||||
local found
|
||||
found=$(command -v HandBrakeCLI 2>/dev/null || true)
|
||||
[[ -z "$found" ]] && break
|
||||
warn "Entferne: $found"
|
||||
rm -f "$found"
|
||||
done
|
||||
hash -r 2>/dev/null || true
|
||||
ok "Alte HandBrake-Installation(en) entfernt"
|
||||
}
|
||||
|
||||
build_handbrake_nvdec() {
|
||||
header "HandBrake ${HANDBRAKE_VERSION} mit NVDEC aus Quellcode bauen"
|
||||
|
||||
@@ -191,6 +210,9 @@ build_handbrake_nvdec() {
|
||||
local src_url="https://github.com/HandBrake/HandBrake/releases/download/${HANDBRAKE_VERSION}/HandBrake-${HANDBRAKE_VERSION}-source.tar.bz2"
|
||||
local tarball="${tmp_dir}/handbrake-src.tar.bz2"
|
||||
|
||||
# Alte Installationen vollständig entfernen
|
||||
remove_all_handbrake
|
||||
|
||||
# Build-Abhängigkeiten
|
||||
info "Installiere Build-Abhängigkeiten..."
|
||||
apt-get install -y \
|
||||
@@ -220,14 +242,6 @@ build_handbrake_nvdec() {
|
||||
fi
|
||||
ok "Build-Abhängigkeiten installiert"
|
||||
|
||||
# Alte Installation entfernen
|
||||
if command_exists HandBrakeCLI; then
|
||||
warn "Entferne vorhandenes HandBrakeCLI..."
|
||||
apt-get remove -y handbrake-cli 2>/dev/null || true
|
||||
snap remove handbrake-cli 2>/dev/null || true
|
||||
rm -f /usr/bin/HandBrakeCLI /usr/local/bin/HandBrakeCLI
|
||||
fi
|
||||
|
||||
# Quellcode herunterladen
|
||||
info "Lade HandBrake ${HANDBRAKE_VERSION} herunter..."
|
||||
curl -fsSL "$src_url" -o "$tarball" 2>/dev/null || \
|
||||
|
||||
35
install.sh
35
install.sh
@@ -188,6 +188,29 @@ install_makemkv() {
|
||||
warn "Beta-Key: https://www.makemkv.com/forum/viewtopic.php?t=1053"
|
||||
}
|
||||
|
||||
remove_all_handbrake() {
|
||||
info "Entferne alle vorhandenen HandBrake-Installationen..."
|
||||
# apt
|
||||
apt-get remove -y handbrake-cli handbrake 2>/dev/null || true
|
||||
# snap
|
||||
snap remove handbrake-cli 2>/dev/null || true
|
||||
# bekannte Binär-Pfade
|
||||
rm -f /usr/bin/HandBrakeCLI \
|
||||
/usr/local/bin/HandBrakeCLI \
|
||||
/snap/bin/handbrake-cli \
|
||||
/snap/bin/HandBrakeCLI
|
||||
# alle weiteren Fundstellen über PATH
|
||||
while true; do
|
||||
local found
|
||||
found=$(command -v HandBrakeCLI 2>/dev/null || true)
|
||||
[[ -z "$found" ]] && break
|
||||
warn "Entferne: $found"
|
||||
rm -f "$found"
|
||||
done
|
||||
hash -r 2>/dev/null || true
|
||||
ok "Alte HandBrake-Installation(en) entfernt"
|
||||
}
|
||||
|
||||
build_handbrake_nvdec() {
|
||||
header "HandBrake ${HANDBRAKE_VERSION} mit NVDEC aus Quellcode bauen"
|
||||
|
||||
@@ -196,6 +219,9 @@ build_handbrake_nvdec() {
|
||||
local src_url="https://github.com/HandBrake/HandBrake/releases/download/${HANDBRAKE_VERSION}/HandBrake-${HANDBRAKE_VERSION}-source.tar.bz2"
|
||||
local tarball="${tmp_dir}/handbrake-src.tar.bz2"
|
||||
|
||||
# Alte Installationen vollständig entfernen
|
||||
remove_all_handbrake
|
||||
|
||||
# Build-Abhängigkeiten
|
||||
info "Installiere Build-Abhängigkeiten..."
|
||||
apt-get install -y \
|
||||
@@ -213,7 +239,6 @@ build_handbrake_nvdec() {
|
||||
if ! dpkg -l 2>/dev/null | grep -q '^ii.*nvidia-cuda-toolkit'; then
|
||||
apt-get install -y nvidia-cuda-toolkit >/dev/null 2>&1 || {
|
||||
warn "nvidia-cuda-toolkit nicht verfügbar – versuche Fallback-Header..."
|
||||
# Fallback: nur die minimalen Header aus dem NVIDIA-CUDA-Repo
|
||||
local cuda_keyring="/tmp/cuda-keyring.deb"
|
||||
local ubuntu_ver="${VERSION_ID//./}"
|
||||
curl -fsSL "https://developer.download.nvidia.com/compute/cuda/repos/ubuntu${ubuntu_ver}/x86_64/cuda-keyring_1.1-1_all.deb" \
|
||||
@@ -226,14 +251,6 @@ build_handbrake_nvdec() {
|
||||
fi
|
||||
ok "Build-Abhängigkeiten installiert"
|
||||
|
||||
# Alte Installation entfernen
|
||||
if command_exists HandBrakeCLI; then
|
||||
warn "Entferne vorhandenes HandBrakeCLI..."
|
||||
apt-get remove -y handbrake-cli 2>/dev/null || true
|
||||
snap remove handbrake-cli 2>/dev/null || true
|
||||
rm -f /usr/bin/HandBrakeCLI /usr/local/bin/HandBrakeCLI
|
||||
fi
|
||||
|
||||
# Quellcode herunterladen
|
||||
info "Lade HandBrake ${HANDBRAKE_VERSION} herunter..."
|
||||
curl -fsSL "$src_url" -o "$tarball" 2>/dev/null || \
|
||||
|
||||
@@ -62,12 +62,13 @@ nav:
|
||||
- Workflow & Zustände: pipeline/workflow.md
|
||||
- Encode-Planung & Track-Auswahl: pipeline/encoding.md
|
||||
- Playlist-Analyse: pipeline/playlist-analysis.md
|
||||
- Post-Encode-Skripte: pipeline/post-encode-scripts.md
|
||||
- Encode-Skripte (Pre & Post): pipeline/post-encode-scripts.md
|
||||
- API-Referenz:
|
||||
- api/index.md
|
||||
- Pipeline API: api/pipeline.md
|
||||
- Settings API: api/settings.md
|
||||
- History API: api/history.md
|
||||
- Cron API: api/crons.md
|
||||
- WebSocket Events: api/websocket.md
|
||||
- Konfiguration:
|
||||
- configuration/index.md
|
||||
|
||||
Reference in New Issue
Block a user