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.
|
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
|
## Was Ripster kann
|
||||||
|
|
||||||
- Disc-Erkennung mit Pipeline-Status in Echtzeit (WebSocket)
|
- 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
|
- Metadaten-Suche und Zuordnung über OMDb
|
||||||
- MakeMKV-Analyse und Rip (MKV oder Backup-Modus)
|
- MakeMKV-Analyse und Rip (MKV oder Backup-Modus)
|
||||||
- HandBrake-Encode mit Preset + Extra-Args + Track-Override
|
- HandBrake-Encode mit Preset + Extra-Args + Track-Override
|
||||||
- Manuelle Playlist-/Titel-Auswahl bei komplexen Blu-rays
|
- 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
|
- Historie mit Re-Encode, Löschfunktionen und Detailansicht
|
||||||
- Dateibasierte Logs (Backend + Job-Prozesslogs)
|
- Dateibasierte Logs (Backend + Job-Prozesslogs)
|
||||||
|
|
||||||
@@ -138,15 +153,30 @@ ripster/
|
|||||||
|
|
||||||
## API-Überblick
|
## API-Überblick
|
||||||
|
|
||||||
|
**Pipeline**
|
||||||
- `GET /api/pipeline/state`
|
- `GET /api/pipeline/state`
|
||||||
- `POST /api/pipeline/analyze`
|
- `POST /api/pipeline/analyze`
|
||||||
- `POST /api/pipeline/start/:jobId`
|
- `POST /api/pipeline/start/:jobId`
|
||||||
- `POST /api/pipeline/confirm-encode/:jobId`
|
- `POST /api/pipeline/confirm-encode/:jobId`
|
||||||
|
|
||||||
|
**History**
|
||||||
- `GET /api/history`
|
- `GET /api/history`
|
||||||
- `GET /api/history/:id`
|
- `GET /api/history/:id`
|
||||||
|
|
||||||
|
**Settings**
|
||||||
- `GET /api/settings`
|
- `GET /api/settings`
|
||||||
- `PUT /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
|
## Troubleshooting
|
||||||
|
|
||||||
- WebSocket verbindet nicht:
|
- WebSocket verbindet nicht:
|
||||||
|
|||||||
@@ -81,15 +81,23 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
# 3. Alte Installation entfernen
|
# 3. Alle vorhandenen HandBrake-Installationen entfernen
|
||||||
# --------------------------------------------------------------------------
|
# --------------------------------------------------------------------------
|
||||||
if command -v HandBrakeCLI &>/dev/null; then
|
info "Entferne alle vorhandenen HandBrake-Installationen..."
|
||||||
EXISTING=$(HandBrakeCLI --version 2>&1 | head -1)
|
apt-get remove -y handbrake-cli handbrake 2>/dev/null || true
|
||||||
warn "Entferne vorhandenes HandBrakeCLI: ${EXISTING}"
|
snap remove handbrake-cli 2>/dev/null || true
|
||||||
apt-get remove -y handbrake-cli 2>/dev/null || true
|
rm -f /usr/bin/HandBrakeCLI \
|
||||||
snap remove handbrake-cli 2>/dev/null || true
|
/usr/local/bin/HandBrakeCLI \
|
||||||
rm -f /usr/bin/HandBrakeCLI /usr/local/bin/HandBrakeCLI
|
/snap/bin/handbrake-cli \
|
||||||
fi
|
/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
|
# 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)
|
[: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**
|
- :material-lightning-bolt: **WebSocket Events**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -113,12 +113,19 @@ Disc erkannt.
|
|||||||
"payload": {
|
"payload": {
|
||||||
"device": {
|
"device": {
|
||||||
"path": "/dev/sr0",
|
"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_REMOVED
|
||||||
|
|
||||||
Disc entfernt.
|
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
|
## Reconnect-Verhalten
|
||||||
|
|||||||
@@ -7,11 +7,15 @@ Ripster verwendet **SQLite3** als Datenbank. Die Datenbankdatei liegt unter `bac
|
|||||||
## Schema-Übersicht
|
## Schema-Übersicht
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
-- Vier Haupt-Tabellen
|
|
||||||
settings_schema -- Einstellungs-Definitionen
|
settings_schema -- Einstellungs-Definitionen
|
||||||
settings_values -- Benutzer-Werte
|
settings_values -- Benutzer-Werte
|
||||||
jobs -- Rip-Job-Datensätze
|
jobs -- Rip-Job-Datensätze
|
||||||
pipeline_state -- Aktueller Pipeline-Zustand (Singleton)
|
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
|
```sql
|
||||||
CREATE TABLE jobs (
|
CREATE TABLE jobs (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
created_at TEXT NOT NULL,
|
created_at TEXT NOT NULL,
|
||||||
updated_at TEXT NOT NULL,
|
updated_at TEXT NOT NULL,
|
||||||
status TEXT NOT NULL, -- Aktueller Status
|
status TEXT NOT NULL, -- Aktueller Status
|
||||||
title TEXT, -- Filmtitel (von OMDb)
|
title TEXT, -- Filmtitel (von OMDb)
|
||||||
imdb_id TEXT, -- IMDb-ID
|
imdb_id TEXT, -- IMDb-ID
|
||||||
omdb_year TEXT, -- Erscheinungsjahr
|
omdb_year TEXT, -- Erscheinungsjahr
|
||||||
omdb_type TEXT, -- movie/series
|
omdb_type TEXT, -- movie/series
|
||||||
omdb_poster TEXT, -- Poster-URL
|
omdb_poster TEXT, -- Poster-URL
|
||||||
raw_path TEXT, -- Pfad zur Raw-MKV
|
raw_path TEXT, -- Pfad zur Raw-MKV
|
||||||
output_path TEXT, -- Pfad zur Ausgabedatei
|
output_path TEXT, -- Pfad zur Ausgabedatei
|
||||||
playlist TEXT, -- Gewählte Blu-ray Playlist
|
playlist TEXT, -- Gewählte Blu-ray Playlist
|
||||||
makemkv_output TEXT, -- MakeMKV-Ausgabe (JSON)
|
rip_successful INTEGER NOT NULL DEFAULT 0, -- 1 wenn Rip abgeschlossen
|
||||||
mediainfo_output TEXT, -- MediaInfo-Ausgabe (JSON)
|
makemkv_output TEXT, -- MakeMKV-Ausgabe (JSON)
|
||||||
encode_plan TEXT, -- Encode-Plan (JSON)
|
mediainfo_output TEXT, -- MediaInfo-Ausgabe (JSON)
|
||||||
handbrake_log TEXT, -- HandBrake Log-Pfad
|
encode_plan TEXT, -- Encode-Plan (JSON)
|
||||||
error_message TEXT, -- Fehlermeldung bei ERROR
|
handbrake_log TEXT, -- HandBrake Log-Pfad
|
||||||
error_details TEXT -- Detaillierte Fehler-Infos
|
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
|
### Job-Status-Werte
|
||||||
|
|
||||||
| Status | Beschreibung |
|
| 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
|
## Schema-Migrationen
|
||||||
|
|
||||||
`database.js` implementiert **automatische Migrationen**:
|
`database.js` implementiert **automatische Migrationen**:
|
||||||
@@ -126,7 +215,7 @@ Falls die Datenbankdatei korrupt ist:
|
|||||||
|
|
||||||
```
|
```
|
||||||
1. Korrupte Datei wird erkannt (Verbindungsfehler / Integritätsprüfung)
|
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
|
3. Neue, leere Datenbank wird erstellt
|
||||||
4. Schema wird neu initialisiert
|
4. Schema wird neu initialisiert
|
||||||
5. Log-Eintrag mit Warnung
|
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
|
## 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
|
FINISHED
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! warning "Abbruch bei Fehler"
|
!!! warning "Abbruch bei Fehler"
|
||||||
Schlägt ein Skript fehl (Exit-Code ≠ 0), werden alle nachfolgenden Skripte **nicht mehr ausgeführt**.
|
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 `postEncodeScripts`-Summary festgehalten.
|
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
|
### 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`) |
|
| **Befehl** | Shell-Befehl oder Skriptpfad (z. B. `/home/michael/scripts/move-to-plex.sh`) |
|
||||||
| **Beschreibung** | Optionale Erklärung |
|
| **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
|
### Verfügbare Umgebungsvariablen
|
||||||
|
|
||||||
Jedes Skript wird mit folgenden Umgebungsvariablen aufgerufen:
|
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. Verzeichnis vorbereiten (Skript) [Entfernen]│
|
||||||
│ ≡ 1. Zu Plex verschieben [Entfernen]│
|
|
||||||
│ ≡ 2. Webhook auslösen [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
|
- **Pre-Encode** und **Post-Encode** werden separat konfiguriert
|
||||||
- **Hinzufügen** aus der Dropdown-Liste aller konfigurierten Skripte
|
- Sowohl **einzelne Skripte** als auch **Skript-Ketten** können in beiden Phasen ausgewählt werden
|
||||||
- **Entfernen** einzelner Skripte aus der aktuellen Auswahl
|
- **Reihenfolge** per Drag & Drop innerhalb jeder Phase ändern
|
||||||
- Skripte können pro Job unterschiedlich gewählt werden
|
- **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"
|
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() {
|
build_handbrake_nvdec() {
|
||||||
header "HandBrake ${HANDBRAKE_VERSION} mit NVDEC aus Quellcode bauen"
|
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 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"
|
local tarball="${tmp_dir}/handbrake-src.tar.bz2"
|
||||||
|
|
||||||
|
# Alte Installationen vollständig entfernen
|
||||||
|
remove_all_handbrake
|
||||||
|
|
||||||
# Build-Abhängigkeiten
|
# Build-Abhängigkeiten
|
||||||
info "Installiere Build-Abhängigkeiten..."
|
info "Installiere Build-Abhängigkeiten..."
|
||||||
apt-get install -y \
|
apt-get install -y \
|
||||||
@@ -220,14 +242,6 @@ build_handbrake_nvdec() {
|
|||||||
fi
|
fi
|
||||||
ok "Build-Abhängigkeiten installiert"
|
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
|
# Quellcode herunterladen
|
||||||
info "Lade HandBrake ${HANDBRAKE_VERSION} herunter..."
|
info "Lade HandBrake ${HANDBRAKE_VERSION} herunter..."
|
||||||
curl -fsSL "$src_url" -o "$tarball" 2>/dev/null || \
|
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"
|
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() {
|
build_handbrake_nvdec() {
|
||||||
header "HandBrake ${HANDBRAKE_VERSION} mit NVDEC aus Quellcode bauen"
|
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 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"
|
local tarball="${tmp_dir}/handbrake-src.tar.bz2"
|
||||||
|
|
||||||
|
# Alte Installationen vollständig entfernen
|
||||||
|
remove_all_handbrake
|
||||||
|
|
||||||
# Build-Abhängigkeiten
|
# Build-Abhängigkeiten
|
||||||
info "Installiere Build-Abhängigkeiten..."
|
info "Installiere Build-Abhängigkeiten..."
|
||||||
apt-get install -y \
|
apt-get install -y \
|
||||||
@@ -213,7 +239,6 @@ build_handbrake_nvdec() {
|
|||||||
if ! dpkg -l 2>/dev/null | grep -q '^ii.*nvidia-cuda-toolkit'; then
|
if ! dpkg -l 2>/dev/null | grep -q '^ii.*nvidia-cuda-toolkit'; then
|
||||||
apt-get install -y nvidia-cuda-toolkit >/dev/null 2>&1 || {
|
apt-get install -y nvidia-cuda-toolkit >/dev/null 2>&1 || {
|
||||||
warn "nvidia-cuda-toolkit nicht verfügbar – versuche Fallback-Header..."
|
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 cuda_keyring="/tmp/cuda-keyring.deb"
|
||||||
local ubuntu_ver="${VERSION_ID//./}"
|
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" \
|
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
|
fi
|
||||||
ok "Build-Abhängigkeiten installiert"
|
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
|
# Quellcode herunterladen
|
||||||
info "Lade HandBrake ${HANDBRAKE_VERSION} herunter..."
|
info "Lade HandBrake ${HANDBRAKE_VERSION} herunter..."
|
||||||
curl -fsSL "$src_url" -o "$tarball" 2>/dev/null || \
|
curl -fsSL "$src_url" -o "$tarball" 2>/dev/null || \
|
||||||
|
|||||||
@@ -62,12 +62,13 @@ nav:
|
|||||||
- Workflow & Zustände: pipeline/workflow.md
|
- Workflow & Zustände: pipeline/workflow.md
|
||||||
- Encode-Planung & Track-Auswahl: pipeline/encoding.md
|
- Encode-Planung & Track-Auswahl: pipeline/encoding.md
|
||||||
- Playlist-Analyse: pipeline/playlist-analysis.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-Referenz:
|
||||||
- api/index.md
|
- api/index.md
|
||||||
- Pipeline API: api/pipeline.md
|
- Pipeline API: api/pipeline.md
|
||||||
- Settings API: api/settings.md
|
- Settings API: api/settings.md
|
||||||
- History API: api/history.md
|
- History API: api/history.md
|
||||||
|
- Cron API: api/crons.md
|
||||||
- WebSocket Events: api/websocket.md
|
- WebSocket Events: api/websocket.md
|
||||||
- Konfiguration:
|
- Konfiguration:
|
||||||
- configuration/index.md
|
- configuration/index.md
|
||||||
|
|||||||
Reference in New Issue
Block a user