1.0.0 release snapshot
This commit is contained in:
@@ -0,0 +1,290 @@
|
||||
# Converter API
|
||||
|
||||
Endpunkte für den Datei-Converter: Datei-Explorer, Upload, Job-Verwaltung.
|
||||
|
||||
Basis-Pfad: `/api/converter`
|
||||
|
||||
---
|
||||
|
||||
## Scan & Explorer
|
||||
|
||||
### `GET /api/converter/tree`
|
||||
|
||||
Vollständiger Verzeichnisbaum des `converter_raw_dir` (FS-basiert, keine DB).
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"tree": [
|
||||
{
|
||||
"name": "filme",
|
||||
"relPath": "filme",
|
||||
"isDir": true,
|
||||
"children": [
|
||||
{
|
||||
"name": "film.mkv",
|
||||
"relPath": "filme/film.mkv",
|
||||
"isDir": false,
|
||||
"size": 10485760
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `GET /api/converter/browse?parent=relPath`
|
||||
|
||||
DB-basierter Datei-Explorer. Gibt Einträge für einen Unterordner zurück.
|
||||
|
||||
**Query-Parameter:**
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
|---|---|---|
|
||||
| `parent` | string | Relativer Pfad zum Unterordner (leer = Root) |
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"id": 1,
|
||||
"rel_path": "filme/film.mkv",
|
||||
"is_dir": false,
|
||||
"size": 10485760,
|
||||
"job_id": null
|
||||
}
|
||||
],
|
||||
"rawDir": "/data/output/converter-raw"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/converter/scan`
|
||||
|
||||
Manuellen Scan des `converter_raw_dir` auslösen. Aktualisiert `converter_scan_entries` in der DB.
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{ "result": { "added": 3, "removed": 1 } }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Jobs erstellen
|
||||
|
||||
### `POST /api/converter/jobs/from-selection`
|
||||
|
||||
Jobs aus im Datei-Explorer ausgewählten Dateien erstellen.
|
||||
|
||||
**Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"relPaths": ["filme/film.mkv", "musik/track.flac"],
|
||||
"audioMode": "individual"
|
||||
}
|
||||
```
|
||||
|
||||
| Feld | Typ | Beschreibung |
|
||||
|---|---|---|
|
||||
| `relPaths` | string[] | Relative Pfade der ausgewählten Dateien |
|
||||
| `audioMode` | string | `individual` (ein Job pro Datei) oder `shared` (ein gemeinsamer Job) |
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{ "jobs": [{ "id": 42, "status": "READY_TO_START" }] }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/converter/create-jobs`
|
||||
|
||||
Jobs aus DB-Scan-Einträgen erstellen.
|
||||
|
||||
**Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"entries": [
|
||||
{ "relPath": "filme/film.mkv", "converterMediaType": "video" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/converter/upload`
|
||||
|
||||
Dateien hochladen (Multipart, max. 50 Dateien).
|
||||
|
||||
**Form-Felder:**
|
||||
|
||||
| Feld | Typ | Beschreibung |
|
||||
|---|---|---|
|
||||
| `files` | File[] | Hochzuladende Dateien |
|
||||
| `folderName` | string | (Optional) Ziel-Unterordner |
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"folders": [{ "folderRelPath": "upload-2026-03-30", "fileCount": 2 }]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Job-Verwaltung
|
||||
|
||||
### `GET /api/converter/jobs`
|
||||
|
||||
Alle Converter-Jobs zurückgeben.
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{ "jobs": [{ "id": 42, "status": "READY_TO_START", "title": "film.mkv" }] }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `GET /api/converter/jobs/:jobId`
|
||||
|
||||
Einzelnen Converter-Job abrufen.
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/converter/jobs/:jobId/config`
|
||||
|
||||
Konfigurationsentwurf für einen Job speichern (persistiert in `encode_plan_json`).
|
||||
|
||||
**Body:** Partielles Konfig-Objekt (Ausgabeformat, Presets, Metadaten, Track-Auswahl).
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/converter/jobs/:jobId/assign-files`
|
||||
|
||||
Dateien einem bestehenden (noch nicht gestarteten) Job hinzufügen.
|
||||
|
||||
**Body:**
|
||||
|
||||
```json
|
||||
{ "relPaths": ["musik/track2.flac"] }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/converter/jobs/:jobId/remove-file`
|
||||
|
||||
Datei aus einem Job entfernen (per relativer Pfad).
|
||||
|
||||
**Body:**
|
||||
|
||||
```json
|
||||
{ "relPath": "musik/track2.flac" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/converter/jobs/:jobId/remove-input`
|
||||
|
||||
Datei aus einem Job entfernen (per absolutem Eingabepfad).
|
||||
|
||||
**Body:**
|
||||
|
||||
```json
|
||||
{ "inputPath": "/data/output/converter-raw/musik/track2.flac" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/converter/jobs/:jobId/start`
|
||||
|
||||
Job mit finaler Konfiguration starten.
|
||||
|
||||
**Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"converterMediaType": "video",
|
||||
"outputFormat": "mkv",
|
||||
"userPreset": "H.264 MKV 1080p30",
|
||||
"trackSelection": {},
|
||||
"handBrakeTitleId": 1,
|
||||
"audioFormatOptions": {}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/converter/jobs/:jobId/cancel`
|
||||
|
||||
Laufenden Job abbrechen.
|
||||
|
||||
---
|
||||
|
||||
### `DELETE /api/converter/jobs/:jobId`
|
||||
|
||||
Job aus der DB löschen.
|
||||
|
||||
---
|
||||
|
||||
## Datei-Operationen
|
||||
|
||||
Alle Datei-Operationen arbeiten direkt auf dem Dateisystem (ohne DB-Aktualisierung). Ein anschließender Scan-Aufruf synchronisiert die DB.
|
||||
|
||||
### `DELETE /api/converter/files`
|
||||
|
||||
Datei oder Ordner löschen.
|
||||
|
||||
**Body:**
|
||||
|
||||
```json
|
||||
{ "relPath": "filme/film.mkv" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/converter/files/rename`
|
||||
|
||||
Datei oder Ordner umbenennen.
|
||||
|
||||
**Body:**
|
||||
|
||||
```json
|
||||
{ "relPath": "filme/film.mkv", "newName": "film-neu.mkv" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/converter/files/move`
|
||||
|
||||
Datei oder Ordner verschieben.
|
||||
|
||||
**Body:**
|
||||
|
||||
```json
|
||||
{ "relPath": "filme/film.mkv", "targetParentRelPath": "archiv" }
|
||||
```
|
||||
|
||||
`targetParentRelPath = ""` verschiebt in das Root-Verzeichnis.
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/converter/files/folder`
|
||||
|
||||
Neuen Ordner anlegen.
|
||||
|
||||
**Body:**
|
||||
|
||||
```json
|
||||
{ "parentRelPath": "filme", "name": "neu" }
|
||||
```
|
||||
@@ -0,0 +1,182 @@
|
||||
# Cron API
|
||||
|
||||
Ripster enthält ein eingebautes Cron-System für Skripte und Skript-Ketten (`sourceType: script|chain`).
|
||||
|
||||
---
|
||||
|
||||
## GET /api/crons
|
||||
|
||||
Listet alle Cron-Jobs.
|
||||
|
||||
```json
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Nachtlauf Backup",
|
||||
"cronExpression": "0 2 * * *",
|
||||
"sourceType": "script",
|
||||
"sourceId": 3,
|
||||
"sourceName": "Backup-Skript",
|
||||
"enabled": true,
|
||||
"pushoverEnabled": true,
|
||||
"lastRunAt": "2026-03-10T02:00:00.000Z",
|
||||
"lastRunStatus": "success",
|
||||
"nextRunAt": "2026-03-11T02:00:00.000Z",
|
||||
"createdAt": "2026-03-01T10:00:00.000Z",
|
||||
"updatedAt": "2026-03-10T02:00:05.000Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /api/crons
|
||||
|
||||
Erstellt Cron-Job.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Nachtlauf Backup",
|
||||
"cronExpression": "0 2 * * *",
|
||||
"sourceType": "script",
|
||||
"sourceId": 3,
|
||||
"enabled": true,
|
||||
"pushoverEnabled": true
|
||||
}
|
||||
```
|
||||
|
||||
Response: `201` mit `{ "job": { ... } }`
|
||||
|
||||
---
|
||||
|
||||
## GET /api/crons/:id
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{ "job": { "id": 1, "name": "..." } }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## PUT /api/crons/:id
|
||||
|
||||
Aktualisiert Cron-Job. Felder wie bei `POST`.
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{ "job": { ... } }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## DELETE /api/crons/:id
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{ "removed": { "id": 1, "name": "Nachtlauf Backup" } }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## GET /api/crons/:id/logs
|
||||
|
||||
Liefert Ausführungs-Logs.
|
||||
|
||||
**Query-Parameter:**
|
||||
|
||||
| Parameter | Typ | Default | Beschreibung |
|
||||
|-----------|-----|---------|-------------|
|
||||
| `limit` | number | `20` | Anzahl Einträge, max. `100` |
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"logs": [
|
||||
{
|
||||
"id": 42,
|
||||
"cronJobId": 1,
|
||||
"startedAt": "2026-03-10T02:00:01.000Z",
|
||||
"finishedAt": "2026-03-10T02:00:05.000Z",
|
||||
"status": "success",
|
||||
"output": "Backup abgeschlossen.",
|
||||
"errorMessage": null
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`status`: `running` | `success` | `error`
|
||||
|
||||
---
|
||||
|
||||
## POST /api/crons/:id/run
|
||||
|
||||
Triggert Job manuell (asynchron).
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{ "triggered": true, "cronJobId": 1 }
|
||||
```
|
||||
|
||||
Wenn Job bereits läuft: `409`.
|
||||
|
||||
---
|
||||
|
||||
## POST /api/crons/validate-expression
|
||||
|
||||
Validiert 5-Felder-Cron-Ausdruck und berechnet nächsten Lauf.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{ "cronExpression": "*/15 * * * *" }
|
||||
```
|
||||
|
||||
**Gültige Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"valid": true,
|
||||
"nextRunAt": "2026-03-10T14:15:00.000Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Ungültige Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"valid": false,
|
||||
"error": "Cron-Ausdruck muss genau 5 Felder haben (Minute Stunde Tag Monat Wochentag).",
|
||||
"nextRunAt": null
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cron-Format
|
||||
|
||||
Ripster unterstützt 5 Felder:
|
||||
|
||||
```text
|
||||
Minute Stunde Tag Monat Wochentag
|
||||
```
|
||||
|
||||
Beispiele:
|
||||
|
||||
- `0 2 * * *` täglich 02:00
|
||||
- `*/15 * * * *` alle 15 Minuten
|
||||
- `0 6 * * 1-5` Mo-Fr 06:00
|
||||
|
||||
---
|
||||
|
||||
## WebSocket-Events zu Cron
|
||||
|
||||
- `CRON_JOBS_UPDATED` bei Create/Update/Delete
|
||||
- `CRON_JOB_UPDATED` bei Laufzeitstatus (`running` -> `success|error`)
|
||||
@@ -0,0 +1,143 @@
|
||||
# Downloads API
|
||||
|
||||
Endpunkte für die Download-Queue. Ausgabedateien aus der Job-Historie können als ZIP heruntergeladen werden.
|
||||
|
||||
Basis-Pfad: `/api/downloads`
|
||||
|
||||
---
|
||||
|
||||
## `GET /api/downloads`
|
||||
|
||||
Liste aller Download-Einträge plus Zusammenfassung.
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"id": "dl-42-raw",
|
||||
"jobId": 42,
|
||||
"target": "raw",
|
||||
"status": "ready",
|
||||
"archiveName": "Job_42_raw.zip",
|
||||
"outputPath": null,
|
||||
"createdAt": "2026-03-30T10:00:00.000Z",
|
||||
"updatedAt": "2026-03-30T10:01:00.000Z",
|
||||
"errorMessage": null
|
||||
}
|
||||
],
|
||||
"summary": {
|
||||
"total": 3,
|
||||
"pending": 1,
|
||||
"processing": 0,
|
||||
"ready": 1,
|
||||
"failed": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Status-Werte:**
|
||||
|
||||
| Status | Beschreibung |
|
||||
|---|---|
|
||||
| `pending` | In der Queue, noch nicht gestartet |
|
||||
| `processing` | ZIP wird gerade erstellt |
|
||||
| `ready` | ZIP fertig, Download verfügbar |
|
||||
| `failed` | Fehler bei der Erstellung |
|
||||
|
||||
---
|
||||
|
||||
## `GET /api/downloads/summary`
|
||||
|
||||
Nur die Zusammenfassung der Download-Queue (ohne Item-Liste).
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"summary": {
|
||||
"total": 3,
|
||||
"pending": 1,
|
||||
"processing": 0,
|
||||
"ready": 1,
|
||||
"failed": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## `POST /api/downloads/history/:jobId`
|
||||
|
||||
Job-Ausgabe in die Download-Queue einreihen.
|
||||
|
||||
**Parameter:**
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
|---|---|---|
|
||||
| `jobId` | number | ID des Jobs in der Historie |
|
||||
|
||||
**Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"target": "raw",
|
||||
"outputPath": null
|
||||
}
|
||||
```
|
||||
|
||||
| Feld | Typ | Default | Beschreibung |
|
||||
|---|---|---|---|
|
||||
| `target` | string | `raw` | `raw` (RAW-Dateien) oder `movie` (Ausgabedateien) |
|
||||
| `outputPath` | string | `null` | Optionaler expliziter Ausgabepfad |
|
||||
|
||||
**Response (201 Created):**
|
||||
|
||||
```json
|
||||
{
|
||||
"created": true,
|
||||
"id": "dl-42-raw",
|
||||
"status": "pending",
|
||||
"summary": { "total": 1, "pending": 1, "processing": 0, "ready": 0, "failed": 0 }
|
||||
}
|
||||
```
|
||||
|
||||
Ist der Eintrag bereits vorhanden, wird `201` durch `200` ersetzt und `created: false` zurückgegeben.
|
||||
|
||||
---
|
||||
|
||||
## `GET /api/downloads/:id/file`
|
||||
|
||||
Fertige ZIP-Datei herunterladen.
|
||||
|
||||
**Parameter:**
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
|---|---|---|
|
||||
| `id` | string | Download-ID (z. B. `dl-42-raw`) |
|
||||
|
||||
**Response:** Datei-Download (`Content-Disposition: attachment`).
|
||||
|
||||
Schlägt fehl mit `404`, wenn kein Download-Eintrag mit dieser ID existiert oder die Datei noch nicht bereit ist.
|
||||
|
||||
---
|
||||
|
||||
## `DELETE /api/downloads/:id`
|
||||
|
||||
Download-Eintrag löschen (auch fertige ZIP-Dateien werden vom Dateisystem entfernt).
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"summary": { "total": 2, "pending": 0, "processing": 0, "ready": 2, "failed": 0 }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## WebSocket
|
||||
|
||||
Statusänderungen werden über `DOWNLOADS_UPDATED` in Echtzeit gemeldet. Vollständige Dokumentation: [WebSocket Events](websocket.md#downloads_updated).
|
||||
@@ -0,0 +1,229 @@
|
||||
# History API
|
||||
|
||||
Endpunkte für Job-Historie, Metadaten-Nachpflege, Orphan-Import und Löschoperationen.
|
||||
|
||||
---
|
||||
|
||||
## GET /api/history
|
||||
|
||||
Liefert Jobs mit optionalen Filtern.
|
||||
|
||||
**Query-Parameter:**
|
||||
|
||||
| Parameter | Typ | Beschreibung |
|
||||
|----------|-----|-------------|
|
||||
| `status` | string | Einzelstatus-Filter (legacy-kompatibel). |
|
||||
| `statuses` | string | Mehrfachstatus als CSV, z. B. `FINISHED,ERROR`. |
|
||||
| `search` | string | Suche in Titel-/IMDb-Feldern. |
|
||||
| `limit` | number | Maximale Anzahl Ergebnisse. |
|
||||
| `lite` | bool | Ohne Dateisystem-Checks (schneller). |
|
||||
| `includeChildren` | bool | Child-Jobs (z. B. Serien-/Multipart-Kinder) explizit einbeziehen. |
|
||||
|
||||
**Beispiel:**
|
||||
|
||||
```text
|
||||
GET /api/history?statuses=FINISHED,ERROR&search=Inception&limit=50&lite=1
|
||||
```
|
||||
|
||||
**Response (Beispiel):**
|
||||
|
||||
```json
|
||||
{
|
||||
"jobs": [
|
||||
{
|
||||
"id": 42,
|
||||
"status": "FINISHED",
|
||||
"title": "Inception",
|
||||
"job_kind": "bluray",
|
||||
"raw_path": "/mnt/raw/Inception - RAW - job-42",
|
||||
"output_path": "/mnt/movies/Inception (2010)/Inception (2010).mkv",
|
||||
"mediaType": "bluray",
|
||||
"ripSuccessful": true,
|
||||
"encodeSuccess": true,
|
||||
"created_at": "2026-03-10T08:00:00.000Z",
|
||||
"updated_at": "2026-03-10T10:00:00.000Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## GET /api/history/:id
|
||||
|
||||
Liefert Job-Detail.
|
||||
|
||||
**Query-Parameter:**
|
||||
|
||||
| Parameter | Typ | Standard | Beschreibung |
|
||||
|----------|-----|---------|-------------|
|
||||
| `includeLogs` | bool | `false` | Prozesslog laden. |
|
||||
| `includeLiveLog` | bool | `false` | Live-/Tail-Log laden. |
|
||||
| `includeAllLogs` | bool | `false` | vollständiges Log statt Tail. |
|
||||
| `logTailLines` | number | `800` | Tail-Länge falls nicht `includeAllLogs`. |
|
||||
| `lite` | bool | `false` | Detailantwort ohne FS-Checks. |
|
||||
|
||||
**Response (Beispiel):**
|
||||
|
||||
```json
|
||||
{
|
||||
"job": {
|
||||
"id": 42,
|
||||
"status": "FINISHED",
|
||||
"makemkvInfo": {},
|
||||
"mediainfoInfo": {},
|
||||
"handbrakeInfo": {},
|
||||
"encodePlan": {},
|
||||
"log": "...",
|
||||
"log_count": 1,
|
||||
"logMeta": {
|
||||
"loaded": true,
|
||||
"total": 800,
|
||||
"returned": 800,
|
||||
"truncated": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## GET /api/history/orphan-raw
|
||||
|
||||
Sucht RAW-Ordner ohne zugehörigen Job.
|
||||
|
||||
## POST /api/history/orphan-raw/import
|
||||
|
||||
Importiert einen RAW-Ordner als Job und triggert optional die Analyse des Imports.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{ "rawPath": "/mnt/raw/Inception (2010) [tt1375666] - RAW - job-99" }
|
||||
```
|
||||
|
||||
**Response (Beispiel):**
|
||||
|
||||
```json
|
||||
{
|
||||
"job": { "id": 77, "status": "FINISHED" },
|
||||
"activation": { "started": true },
|
||||
"activationError": null
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /api/history/:id/metadata/assign
|
||||
|
||||
Weist TMDb-Metadaten nachträglich zu oder aktualisiert bestehende Film-/Serien-Metadaten eines Jobs.
|
||||
|
||||
## POST /api/history/:id/cd/assign
|
||||
|
||||
Weist CD-Metadaten (z. B. MusicBrainz) nachträglich zu.
|
||||
|
||||
## POST /api/history/:id/error/ack
|
||||
|
||||
Quittiert einen Fehlerzustand im Historieneintrag.
|
||||
|
||||
---
|
||||
|
||||
## GET /api/history/:id/delete-preview
|
||||
|
||||
Liefert eine Vorschau der löschbaren Pfade (inkl. Scope auf verknüpfte Jobs).
|
||||
|
||||
**Query-Parameter:**
|
||||
|
||||
| Parameter | Typ | Standard | Beschreibung |
|
||||
|----------|-----|---------|-------------|
|
||||
| `includeRelated` | bool | `true` | Verknüpfte Jobs in die Vorschau einbeziehen. |
|
||||
|
||||
**Response (Beispiel):**
|
||||
|
||||
```json
|
||||
{
|
||||
"preview": {
|
||||
"jobId": 42,
|
||||
"relatedJobs": [{ "id": 42 }, { "id": 73 }],
|
||||
"pathCandidates": {
|
||||
"raw": [{ "path": "/mnt/raw/...", "exists": true, "isDirectory": true }],
|
||||
"movie": [{ "path": "/mnt/movies/...", "exists": true, "isDirectory": true }]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /api/history/:id/delete-files
|
||||
|
||||
Löscht Dateien eines Jobs, behält DB-Eintrag.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"target": "both",
|
||||
"includeRelated": true,
|
||||
"selectedRawPaths": ["/mnt/raw/Inception - RAW - Disc1"],
|
||||
"selectedMoviePaths": ["/mnt/movies/Inception (2010)"]
|
||||
}
|
||||
```
|
||||
|
||||
`target`: `raw` | `movie` | `both`
|
||||
|
||||
`selectedRawPaths` / `selectedMoviePaths` sind optional und begrenzen die Löschung auf ausgewählte Pfade aus der Vorschau.
|
||||
|
||||
---
|
||||
|
||||
## POST /api/history/:id/delete
|
||||
|
||||
Löscht Job aus DB; optional auch Dateien.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"target": "both",
|
||||
"includeRelated": true,
|
||||
"resetDriveState": false,
|
||||
"keepDetectedDevice": true,
|
||||
"preserveRawForImportJobs": false,
|
||||
"selectedRawPaths": ["/mnt/raw/Inception - RAW - Disc1"],
|
||||
"selectedMoviePaths": ["/mnt/movies/Inception (2010)"]
|
||||
}
|
||||
```
|
||||
|
||||
`target`: `none` | `raw` | `movie` | `both`
|
||||
|
||||
**Response (Beispiel):**
|
||||
|
||||
```json
|
||||
{
|
||||
"deleted": true,
|
||||
"jobId": 42,
|
||||
"fileTarget": "both",
|
||||
"fileSummary": {
|
||||
"target": "both",
|
||||
"raw": { "filesDeleted": 10 },
|
||||
"movie": { "filesDeleted": 1 }
|
||||
},
|
||||
"uiReset": {
|
||||
"reset": true,
|
||||
"state": "IDLE"
|
||||
},
|
||||
"safeguards": {
|
||||
"containsOrphanRawImportJob": false,
|
||||
"resetDriveStateApplied": false,
|
||||
"keepDetectedDeviceApplied": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Hinweise
|
||||
|
||||
- Ein aktiver Pipeline-Job kann nicht gelöscht werden (`409`).
|
||||
- Löschoperationen sind irreversibel.
|
||||
- Bei Serien-/Multipart-Containern steuern `includeRelated` und Pfadselektionen den genauen Scope.
|
||||
@@ -0,0 +1,93 @@
|
||||
# Anhang: API-Referenz
|
||||
|
||||
REST- und WebSocket-Schnittstellen für Integration, Automatisierung und Debugging.
|
||||
|
||||
## Basis-URL
|
||||
|
||||
```text
|
||||
http://localhost:3001
|
||||
```
|
||||
|
||||
API-Prefix: `/api`
|
||||
|
||||
## API-Gruppen
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- :material-heart-pulse: **Health**
|
||||
|
||||
---
|
||||
|
||||
Service-Liveness.
|
||||
|
||||
`GET /api/health`
|
||||
|
||||
- :material-pipe: **Pipeline API**
|
||||
|
||||
---
|
||||
|
||||
Analyse, Start/Retry/Cancel, Queue, Re-Encode.
|
||||
|
||||
[:octicons-arrow-right-24: Pipeline API](pipeline.md)
|
||||
|
||||
- :material-cog: **Settings API**
|
||||
|
||||
---
|
||||
|
||||
Einstellungen, Skripte/Ketten, User-Presets.
|
||||
|
||||
[:octicons-arrow-right-24: Settings API](settings.md)
|
||||
|
||||
- :material-history: **History API**
|
||||
|
||||
---
|
||||
|
||||
Job-Historie, Orphan-Import, Löschoperationen.
|
||||
|
||||
[:octicons-arrow-right-24: History API](history.md)
|
||||
|
||||
- :material-clock-outline: **Cron API**
|
||||
|
||||
---
|
||||
|
||||
Zeitgesteuerte Skript-/Kettenausführung.
|
||||
|
||||
[:octicons-arrow-right-24: Cron API](crons.md)
|
||||
|
||||
- :material-swap-horizontal: **Converter API**
|
||||
|
||||
---
|
||||
|
||||
Datei-Explorer, Upload, Job-Verwaltung für den Converter.
|
||||
|
||||
[:octicons-arrow-right-24: Converter API](converter.md)
|
||||
|
||||
- :material-download: **Downloads API**
|
||||
|
||||
---
|
||||
|
||||
Download-Queue für Ausgabedateien aus der Job-Historie.
|
||||
|
||||
[:octicons-arrow-right-24: Downloads API](downloads.md)
|
||||
|
||||
- :material-lightning-bolt: **Runtime Activities API**
|
||||
|
||||
---
|
||||
|
||||
Laufende und abgeschlossene Aktivitäten (Skripte, Ketten, Cron, Tasks).
|
||||
|
||||
[:octicons-arrow-right-24: Runtime Activities](runtime-activities.md)
|
||||
|
||||
- :material-websocket: **WebSocket Events**
|
||||
|
||||
---
|
||||
|
||||
Pipeline-, Queue-, Disk-, Settings-, Cron-, Converter- und Download-Events.
|
||||
|
||||
[:octicons-arrow-right-24: WebSocket](websocket.md)
|
||||
|
||||
</div>
|
||||
|
||||
## Hinweis
|
||||
|
||||
Ripster hat keine eingebaute Authentifizierung und ist für lokalen, geschützten Betrieb gedacht.
|
||||
@@ -0,0 +1,534 @@
|
||||
# Pipeline API
|
||||
|
||||
Endpunkte zur Steuerung des Pipeline-Workflows.
|
||||
|
||||
---
|
||||
|
||||
## GET /api/pipeline/state
|
||||
|
||||
Liefert aktuellen Pipeline- und Hardware-Monitoring-Snapshot.
|
||||
|
||||
**Response (Beispiel):**
|
||||
|
||||
```json
|
||||
{
|
||||
"pipeline": {
|
||||
"state": "READY_TO_ENCODE",
|
||||
"activeJobId": 42,
|
||||
"progress": 0,
|
||||
"eta": null,
|
||||
"statusText": "Mediainfo bestätigt - Encode manuell starten",
|
||||
"context": {
|
||||
"jobId": 42
|
||||
},
|
||||
"jobProgress": {
|
||||
"42": {
|
||||
"state": "MEDIAINFO_CHECK",
|
||||
"progress": 68.5,
|
||||
"eta": null,
|
||||
"statusText": "MEDIAINFO_CHECK 68.50%"
|
||||
}
|
||||
},
|
||||
"queue": {
|
||||
"maxParallelJobs": 1,
|
||||
"runningCount": 1,
|
||||
"queuedCount": 2,
|
||||
"runningJobs": [],
|
||||
"queuedJobs": []
|
||||
}
|
||||
},
|
||||
"hardwareMonitoring": {
|
||||
"enabled": true,
|
||||
"intervalMs": 5000,
|
||||
"updatedAt": "2026-03-10T09:00:00.000Z",
|
||||
"sample": {
|
||||
"cpu": {},
|
||||
"memory": {},
|
||||
"gpu": {},
|
||||
"storage": {}
|
||||
},
|
||||
"error": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /api/pipeline/analyze
|
||||
|
||||
Startet Disc-Analyse und legt Job an.
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"jobId": 42,
|
||||
"detectedTitle": "INCEPTION",
|
||||
"omdbCandidates": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /api/pipeline/rescan-disc
|
||||
|
||||
Erzwingt erneute Laufwerksprüfung.
|
||||
|
||||
**Response (Beispiel):**
|
||||
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"present": true,
|
||||
"changed": true,
|
||||
"emitted": "discInserted",
|
||||
"device": {
|
||||
"path": "/dev/sr0",
|
||||
"discLabel": "INCEPTION",
|
||||
"mediaProfile": "bluray"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /api/pipeline/rescan-drive
|
||||
|
||||
Erzwingt Rescan für ein konkretes Laufwerk.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{ "devicePath": "/dev/sr0" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## GET /api/pipeline/tmdb/movie/search?q=<query>
|
||||
|
||||
TMDb-Filmsuche.
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"imdbId": "tt1375666",
|
||||
"title": "Inception",
|
||||
"year": "2010",
|
||||
"type": "movie",
|
||||
"poster": "https://..."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## GET /api/pipeline/tmdb/series/search?q=<query>&season=<n>
|
||||
|
||||
TMDb-Seriensuche (für Serien-Workflow bei DVD/Blu-ray).
|
||||
|
||||
---
|
||||
|
||||
## GET /api/pipeline/cd/drives
|
||||
|
||||
Liefert Snapshot der aktuell bekannten CD-Laufwerke.
|
||||
|
||||
---
|
||||
|
||||
## GET /api/pipeline/cd/musicbrainz/search?q=<query>
|
||||
|
||||
MusicBrainz-Suche für CD-Metadaten.
|
||||
|
||||
## GET /api/pipeline/cd/musicbrainz/release/:mbId
|
||||
|
||||
Lädt Release-Details zu einer MusicBrainz-ID.
|
||||
|
||||
## POST /api/pipeline/cd/select-metadata
|
||||
|
||||
Übernimmt CD-Metadaten für einen Job.
|
||||
|
||||
**Request (Beispiel):**
|
||||
|
||||
```json
|
||||
{
|
||||
"jobId": 91,
|
||||
"title": "Album",
|
||||
"artist": "Artist",
|
||||
"year": 2020,
|
||||
"mbId": "f5093c06-23e3-404f-aeaa-40f72885ee3a",
|
||||
"coverUrl": "https://...",
|
||||
"tracks": []
|
||||
}
|
||||
```
|
||||
|
||||
## POST /api/pipeline/cd/start/:jobId
|
||||
|
||||
Startet/queued CD-Rip mit Format-/Script-/Chain-Konfiguration.
|
||||
|
||||
---
|
||||
|
||||
## POST /api/pipeline/audiobook/upload
|
||||
|
||||
Upload von AAX-Datei (Multipart/FormData).
|
||||
|
||||
**FormData-Felder:**
|
||||
|
||||
- `file` (Pflicht)
|
||||
- `format` (optional)
|
||||
- `startImmediately` (optional)
|
||||
|
||||
## GET /api/pipeline/audiobook/pending-activation
|
||||
|
||||
Zeigt AAX-Jobs mit fehlenden Activation-Bytes.
|
||||
|
||||
## POST /api/pipeline/audiobook/start/:jobId
|
||||
|
||||
Startet Audiobook-Job mit optionaler Konfiguration.
|
||||
|
||||
## GET /api/pipeline/audiobook/jobs
|
||||
|
||||
Liefert Audiobook-Jobliste.
|
||||
|
||||
## GET /api/pipeline/audiobook/output-tree
|
||||
|
||||
Read-only Baumansicht des Audiobook-Ausgabeordners.
|
||||
|
||||
---
|
||||
|
||||
## POST /api/pipeline/select-metadata
|
||||
|
||||
Setzt Metadaten (und optional Playlist) für einen Job.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"jobId": 42,
|
||||
"title": "Inception",
|
||||
"year": 2010,
|
||||
"imdbId": "tt1375666",
|
||||
"poster": "https://...",
|
||||
"fromOmdb": true,
|
||||
"selectedPlaylist": "00800"
|
||||
}
|
||||
```
|
||||
|
||||
Wichtige optionale Felder:
|
||||
|
||||
- `selectedHandBrakeTitleId` / `selectedHandBrakeTitleIds`: Titel-Auswahl für Review/MediaInfo.
|
||||
- `metadataProvider`: `omdb` oder `tmdb`.
|
||||
- `workflowKind`: bei Disc-Jobs typischerweise `film` oder `series`.
|
||||
- `discNumber`: Pflicht für Serien-Disc-Zuordnung (`workflowKind=series`).
|
||||
- `duplicateAction`: Duplikatverhalten bei Film-Metadaten (`allow_new` oder `multipart_movie`).
|
||||
- `existingJobId`: optionaler Referenzjob für `multipart_movie`.
|
||||
- `existingDiscNumber`: Disc-Nummer des bestehenden Jobs für `multipart_movie`.
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{ "job": { "id": 42, "status": "READY_TO_START" } }
|
||||
```
|
||||
|
||||
**Konflikt-Response (Beispiel, HTTP 409):**
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Metadaten bereits in der Historie gefunden. Bitte Auswahl übernehmen oder Multipart movie wählen.",
|
||||
"details": [
|
||||
{
|
||||
"code": "METADATA_DUPLICATE_FOUND",
|
||||
"mediaProfile": "bluray",
|
||||
"existingJob": {
|
||||
"id": 17,
|
||||
"title": "Inception",
|
||||
"year": 2010,
|
||||
"status": "FINISHED",
|
||||
"jobKind": "bluray",
|
||||
"discNumber": 1,
|
||||
"isMultipartMovie": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Relevante Fehlercodes (`POST /api/pipeline/select-metadata`):**
|
||||
|
||||
| Code | Bedeutung |
|
||||
|---|---|
|
||||
| `METADATA_DUPLICATE_FOUND` | Film-Metadaten existieren bereits in der Historie (Konfliktdialog im UI). |
|
||||
| `MULTIPART_DISC_REQUIRED` | Für Multipart fehlen Disc-Nummern (`discNumber`/`existingDiscNumber`). |
|
||||
| `MULTIPART_DISC_ALREADY_EXISTS` | Disc-Nummer im Multipart-Container bereits vergeben oder doppelt. |
|
||||
| `MULTIPART_MEDIA_MISMATCH` | Multipart nur bei gleichem Medientyp (DVD oder Blu-ray). |
|
||||
| `MULTIPART_SERIES_NOT_ALLOWED` | Multipart ist nur für Film-Jobs erlaubt, nicht für Serien-Workflow. |
|
||||
| `MULTIPART_METADATA_MISMATCH` | Ausgewählter bestehender Job passt nicht zu den Film-Metadaten. |
|
||||
| `SERIES_DISC_ALREADY_EXISTS` | Serien-Disc-Nummer innerhalb einer Staffel bereits vorhanden. |
|
||||
|
||||
---
|
||||
|
||||
## POST /api/pipeline/jobs/:jobId/raw-decision
|
||||
|
||||
Trifft Entscheidung bei vorhandenem RAW (`continue` oder `restart` je nach Dialogfluss).
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{ "decision": "continue" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /api/pipeline/start/:jobId
|
||||
|
||||
Startet vorbereiteten Job oder queued ihn (je nach Parallel-Limit).
|
||||
|
||||
**Mögliche Responses:**
|
||||
|
||||
```json
|
||||
{ "result": { "started": true, "stage": "RIPPING" } }
|
||||
```
|
||||
|
||||
```json
|
||||
{ "result": { "queued": true, "started": false, "queuePosition": 2, "action": "START_PREPARED" } }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /api/pipeline/confirm-encode/:jobId
|
||||
|
||||
Bestätigt Review-Auswahl (Tracks, Pre/Post-Skripte/Ketten, User-Preset).
|
||||
|
||||
**Request (typisch):**
|
||||
|
||||
```json
|
||||
{
|
||||
"selectedEncodeTitleId": 1,
|
||||
"selectedTrackSelection": {
|
||||
"1": {
|
||||
"audioTrackIds": [1, 2],
|
||||
"subtitleTrackIds": [3]
|
||||
}
|
||||
},
|
||||
"selectedPreEncodeScriptIds": [1],
|
||||
"selectedPostEncodeScriptIds": [2, 7],
|
||||
"selectedPreEncodeChainIds": [3],
|
||||
"selectedPostEncodeChainIds": [4],
|
||||
"selectedUserPresetId": 5,
|
||||
"skipPipelineStateUpdate": false
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{ "job": { "id": 42, "encode_review_confirmed": 1 } }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /api/pipeline/cancel
|
||||
|
||||
Bricht laufenden Job ab oder entfernt Queue-Eintrag.
|
||||
|
||||
**Request (optional):**
|
||||
|
||||
```json
|
||||
{ "jobId": 42 }
|
||||
```
|
||||
|
||||
**Mögliche Responses:**
|
||||
|
||||
```json
|
||||
{ "result": { "cancelled": true, "queuedOnly": true, "jobId": 42 } }
|
||||
```
|
||||
|
||||
```json
|
||||
{ "result": { "cancelled": true, "queuedOnly": false, "jobId": 42 } }
|
||||
```
|
||||
|
||||
```json
|
||||
{ "result": { "cancelled": true, "queuedOnly": false, "pending": true, "jobId": 42 } }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /api/pipeline/retry/:jobId
|
||||
|
||||
Retry für `ERROR`/`CANCELLED`-Jobs (oder Queue-Einreihung).
|
||||
|
||||
## POST /api/pipeline/reencode/:jobId
|
||||
|
||||
Startet Re-Encode aus bestehendem RAW.
|
||||
|
||||
## POST /api/pipeline/restart-review/:jobId
|
||||
|
||||
Berechnet Review aus RAW neu.
|
||||
|
||||
## POST /api/pipeline/restart-encode/:jobId
|
||||
|
||||
Startet Encoding mit letzter bestätigter Review neu.
|
||||
|
||||
## POST /api/pipeline/restart-cd-review/:jobId
|
||||
|
||||
Berechnet CD-Review aus vorhandenem RAW neu.
|
||||
|
||||
## POST /api/pipeline/resume-ready/:jobId
|
||||
|
||||
Lädt `READY_TO_ENCODE`-Job nach Neustart wieder in aktive Session.
|
||||
|
||||
## GET /api/pipeline/output-folders/:jobId
|
||||
|
||||
Liefert bekannte Output-Ordner entlang der Job-Lineage.
|
||||
|
||||
## POST /api/pipeline/delete-output-folders/:jobId
|
||||
|
||||
Löscht ausgewählte Output-Ordner.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{ "folderPaths": ["/mnt/movies/Inception (2010)"] }
|
||||
```
|
||||
|
||||
Alle Endpunkte liefern `{ result: ... }` bzw. `{ job: ... }`.
|
||||
|
||||
---
|
||||
|
||||
## Queue-Endpunkte
|
||||
|
||||
### GET /api/pipeline/queue
|
||||
|
||||
Liefert Queue-Snapshot.
|
||||
|
||||
```json
|
||||
{
|
||||
"queue": {
|
||||
"maxParallelJobs": 1,
|
||||
"runningCount": 1,
|
||||
"queuedCount": 3,
|
||||
"runningJobs": [
|
||||
{
|
||||
"jobId": 41,
|
||||
"title": "Inception",
|
||||
"status": "ENCODING",
|
||||
"lastState": "ENCODING"
|
||||
}
|
||||
],
|
||||
"queuedJobs": [
|
||||
{
|
||||
"entryId": 11,
|
||||
"position": 1,
|
||||
"type": "job",
|
||||
"jobId": 42,
|
||||
"action": "START_PREPARED",
|
||||
"actionLabel": "Start",
|
||||
"title": "Matrix",
|
||||
"status": "READY_TO_ENCODE",
|
||||
"lastState": "READY_TO_ENCODE",
|
||||
"hasScripts": true,
|
||||
"hasChains": false,
|
||||
"enqueuedAt": "2026-03-10T09:00:00.000Z"
|
||||
},
|
||||
{
|
||||
"entryId": 12,
|
||||
"position": 2,
|
||||
"type": "wait",
|
||||
"waitSeconds": 30,
|
||||
"title": "Warten 30s",
|
||||
"status": "QUEUED",
|
||||
"enqueuedAt": "2026-03-10T09:01:00.000Z"
|
||||
}
|
||||
],
|
||||
"updatedAt": "2026-03-10T09:01:02.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### POST /api/pipeline/queue/reorder
|
||||
|
||||
Sortiert Queue-Einträge neu.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"orderedEntryIds": [12, 11]
|
||||
}
|
||||
```
|
||||
|
||||
Legacy fallback wird akzeptiert:
|
||||
|
||||
```json
|
||||
{
|
||||
"orderedJobIds": [42, 43]
|
||||
}
|
||||
```
|
||||
|
||||
### POST /api/pipeline/queue/entry
|
||||
|
||||
Fügt Nicht-Job-Queue-Eintrag hinzu (`script`, `chain`, `wait`).
|
||||
|
||||
**Request-Beispiele:**
|
||||
|
||||
```json
|
||||
{ "type": "script", "scriptId": 3 }
|
||||
```
|
||||
|
||||
```json
|
||||
{ "type": "chain", "chainId": 2, "insertAfterEntryId": 11 }
|
||||
```
|
||||
|
||||
```json
|
||||
{ "type": "wait", "waitSeconds": 45 }
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"result": { "entryId": 12, "type": "wait", "position": 2 },
|
||||
"queue": { "...": "..." }
|
||||
}
|
||||
```
|
||||
|
||||
### DELETE /api/pipeline/queue/entry/:entryId
|
||||
|
||||
Entfernt Queue-Eintrag.
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{ "queue": { "...": "..." } }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pipeline-Zustände
|
||||
|
||||
| State | Bedeutung |
|
||||
|------|-----------|
|
||||
| `IDLE` | Wartet auf Medium |
|
||||
| `DISC_DETECTED` | Medium erkannt |
|
||||
| `ANALYZING` | MakeMKV-Analyse läuft |
|
||||
| `METADATA_SELECTION` | Metadaten-Auswahl |
|
||||
| `WAITING_FOR_USER_DECISION` | Nutzerentscheidung erforderlich (Playlist-Auswahl oder RAW-Entscheidung) |
|
||||
| `READY_TO_START` | Übergang vor Start |
|
||||
| `RIPPING` | MakeMKV-Rip läuft |
|
||||
| `MEDIAINFO_CHECK` | Titel-/Track-Auswertung |
|
||||
| `READY_TO_ENCODE` | Review bereit |
|
||||
| `ENCODING` | HandBrake-Encoding läuft |
|
||||
| `CD_METADATA_SELECTION` | CD-Metadatenauswahl aktiv |
|
||||
| `CD_READY_TO_RIP` | CD-Job ist startbereit |
|
||||
| `CD_ANALYZING` | CD-Struktur/Tracks werden vorbereitet |
|
||||
| `CD_RIPPING` | CD-Ripping läuft |
|
||||
| `CD_ENCODING` | CD-Encode läuft |
|
||||
| `FINISHED` | Abgeschlossen |
|
||||
| `DONE` | Abgeschlossen (v. a. Audiobook/Converter/CD-Varianten) |
|
||||
| `CANCELLED` | Abgebrochen |
|
||||
| `ERROR` | Fehler |
|
||||
@@ -0,0 +1,235 @@
|
||||
# Runtime Activities API
|
||||
|
||||
Ripster verfolgt alle laufenden und kürzlich abgeschlossenen Aktivitäten (Skripte, Skript-Ketten, Cron-Jobs, interne Tasks) in Echtzeit über den `RuntimeActivityService`.
|
||||
|
||||
---
|
||||
|
||||
## Übersicht
|
||||
|
||||
Aktivitäten entstehen, wenn Ripster intern Aktionen ausführt – z. B. beim Start eines Cron-Jobs, beim Ausführen einer Skript-Kette oder beim Durchlaufen von Pipeline-Schritten. Sie sind **nicht persistent** (kein DB-Speicher) und werden nur im Arbeitsspeicher gehalten.
|
||||
|
||||
- **Aktive Aktivitäten** (`active`): Laufen gerade.
|
||||
- **Letzte Aktivitäten** (`recent`): Abgeschlossen, max. 120 Einträge.
|
||||
|
||||
Änderungen werden über WebSocket (`RUNTIME_ACTIVITY_CHANGED`) in Echtzeit gesendet.
|
||||
|
||||
---
|
||||
|
||||
## Aktivitäts-Objekt
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 7,
|
||||
"type": "chain",
|
||||
"name": "Post-Encode Aufräumen",
|
||||
"status": "running",
|
||||
"source": "cron",
|
||||
"message": "Schritt 2 von 3",
|
||||
"currentStep": "cleanup.sh",
|
||||
"currentStepType": "script",
|
||||
"currentScriptName": "cleanup.sh",
|
||||
"stepIndex": 2,
|
||||
"stepTotal": 3,
|
||||
"parentActivityId": null,
|
||||
"jobId": 42,
|
||||
"cronJobId": 3,
|
||||
"chainId": 5,
|
||||
"scriptId": null,
|
||||
"canCancel": true,
|
||||
"canNextStep": false,
|
||||
"outcome": "running",
|
||||
"errorMessage": null,
|
||||
"output": null,
|
||||
"stdout": null,
|
||||
"stderr": null,
|
||||
"stdoutTruncated": false,
|
||||
"stderrTruncated": false,
|
||||
"startedAt": "2026-03-10T10:00:00.000Z",
|
||||
"finishedAt": null,
|
||||
"durationMs": null,
|
||||
"exitCode": null,
|
||||
"success": null
|
||||
}
|
||||
```
|
||||
|
||||
### Felder
|
||||
|
||||
| Feld | Typ | Beschreibung |
|
||||
|------|-----|--------------|
|
||||
| `id` | `number` | Eindeutige ID (Laufzähler, nicht persistent) |
|
||||
| `type` | `string` | Art der Aktivität: `script` \| `chain` \| `cron` \| `task` |
|
||||
| `name` | `string \| null` | Anzeigename der Aktivität |
|
||||
| `status` | `string` | Aktueller Status: `running` \| `success` \| `error` |
|
||||
| `source` | `string \| null` | Auslöser (z. B. `cron`, `pipeline`, `manual`) |
|
||||
| `message` | `string \| null` | Kurztext zum aktuellen Zustand |
|
||||
| `currentStep` | `string \| null` | Name des aktuell ausgeführten Schritts |
|
||||
| `currentStepType` | `string \| null` | Typ des Schritts (z. B. `script`, `wait`) |
|
||||
| `currentScriptName` | `string \| null` | Name des Skripts im aktuellen Schritt |
|
||||
| `stepIndex` | `number \| null` | Aktueller Schritt (1-basiert) |
|
||||
| `stepTotal` | `number \| null` | Gesamtanzahl Schritte |
|
||||
| `parentActivityId` | `number \| null` | ID der übergeordneten Aktivität |
|
||||
| `jobId` | `number \| null` | Verknüpfte Job-ID |
|
||||
| `cronJobId` | `number \| null` | Verknüpfte Cron-Job-ID |
|
||||
| `chainId` | `number \| null` | Verknüpfte Skript-Ketten-ID |
|
||||
| `scriptId` | `number \| null` | Verknüpfte Skript-ID |
|
||||
| `canCancel` | `boolean` | Abbrechen über API möglich |
|
||||
| `canNextStep` | `boolean` | Nächster Schritt über API auslösbar |
|
||||
| `outcome` | `string \| null` | Abschluss-Ergebnis: `success` \| `error` \| `cancelled` \| `skipped` \| `running` |
|
||||
| `errorMessage` | `string \| null` | Fehlermeldung (max. 2.000 Zeichen) |
|
||||
| `output` | `string \| null` | Allgemeine Ausgabe (max. 12.000 Zeichen) |
|
||||
| `stdout` | `string \| null` | Standardausgabe des Prozesses (max. 12.000 Zeichen) |
|
||||
| `stderr` | `string \| null` | Fehlerausgabe des Prozesses (max. 12.000 Zeichen) |
|
||||
| `stdoutTruncated` | `boolean` | `true`, wenn `stdout` gekürzt wurde |
|
||||
| `stderrTruncated` | `boolean` | `true`, wenn `stderr` gekürzt wurde |
|
||||
| `startedAt` | `string` | ISO-8601-Zeitstempel des Starts |
|
||||
| `finishedAt` | `string \| null` | ISO-8601-Zeitstempel des Endes |
|
||||
| `durationMs` | `number \| null` | Laufzeit in Millisekunden |
|
||||
| `exitCode` | `number \| null` | Exit-Code des Prozesses |
|
||||
| `success` | `boolean \| null` | Erfolgsstatus (`null` bei laufender Aktivität) |
|
||||
|
||||
---
|
||||
|
||||
## Snapshot-Objekt
|
||||
|
||||
Alle Aktivitäts-Endpunkte geben einen Snapshot zurück:
|
||||
|
||||
```json
|
||||
{
|
||||
"active": [ /* laufende Aktivitäten, nach startedAt absteigend */ ],
|
||||
"recent": [ /* abgeschlossene Aktivitäten, nach finishedAt absteigend, max. 120 */ ],
|
||||
"updatedAt": "2026-03-10T10:05:00.000Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Endpunkte
|
||||
|
||||
### GET `/api/runtime/activities`
|
||||
|
||||
Aktuellen Aktivitäts-Snapshot abrufen.
|
||||
|
||||
**Antwort:**
|
||||
|
||||
```json
|
||||
{
|
||||
"active": [],
|
||||
"recent": [
|
||||
{
|
||||
"id": 5,
|
||||
"type": "script",
|
||||
"name": "notify.sh",
|
||||
"status": "success",
|
||||
"outcome": "success",
|
||||
"startedAt": "2026-03-10T09:58:00.000Z",
|
||||
"finishedAt": "2026-03-10T09:58:02.000Z",
|
||||
"durationMs": 2100,
|
||||
"exitCode": 0,
|
||||
"success": true,
|
||||
"canCancel": false,
|
||||
"canNextStep": false
|
||||
}
|
||||
],
|
||||
"updatedAt": "2026-03-10T10:05:00.000Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### POST `/api/runtime/activities/:id/cancel`
|
||||
|
||||
Aktive Aktivität abbrechen (nur wenn `canCancel: true`).
|
||||
|
||||
**Parameter:**
|
||||
|
||||
| Name | In | Typ | Beschreibung |
|
||||
|------|----|-----|--------------|
|
||||
| `id` | path | `number` | Aktivitäts-ID |
|
||||
| `reason` | body | `string` | Optionaler Abbruchgrund |
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{ "reason": "Manueller Abbruch durch Benutzer" }
|
||||
```
|
||||
|
||||
**Antwort (Erfolg):**
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"action": null,
|
||||
"snapshot": { "active": [], "recent": [], "updatedAt": "..." }
|
||||
}
|
||||
```
|
||||
|
||||
**Fehlercodes:**
|
||||
|
||||
| HTTP | Bedeutung |
|
||||
|------|-----------|
|
||||
| `404` | Aktivität nicht gefunden oder bereits abgeschlossen |
|
||||
| `409` | Abbrechen wird von dieser Aktivität nicht unterstützt |
|
||||
|
||||
---
|
||||
|
||||
### POST `/api/runtime/activities/:id/next-step`
|
||||
|
||||
Nächsten Schritt einer Aktivität auslösen (nur wenn `canNextStep: true`).
|
||||
|
||||
**Parameter:**
|
||||
|
||||
| Name | In | Typ | Beschreibung |
|
||||
|------|----|-----|--------------|
|
||||
| `id` | path | `number` | Aktivitäts-ID |
|
||||
|
||||
**Antwort (Erfolg):**
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"action": null,
|
||||
"snapshot": { "active": [], "recent": [], "updatedAt": "..." }
|
||||
}
|
||||
```
|
||||
|
||||
**Fehlercodes:**
|
||||
|
||||
| HTTP | Bedeutung |
|
||||
|------|-----------|
|
||||
| `404` | Aktivität nicht gefunden |
|
||||
| `409` | Nächster Schritt wird von dieser Aktivität nicht unterstützt |
|
||||
|
||||
---
|
||||
|
||||
### POST `/api/runtime/activities/clear-recent`
|
||||
|
||||
Alle abgeschlossenen Aktivitäten aus `recent` löschen.
|
||||
|
||||
**Antwort:**
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"removed": 14,
|
||||
"snapshot": { "active": [], "recent": [], "updatedAt": "..." }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Grenzwerte
|
||||
|
||||
| Wert | Limit |
|
||||
|------|-------|
|
||||
| Maximale `recent`-Einträge | 120 |
|
||||
| Maximale Länge `stdout` / `stderr` / `output` | 12.000 Zeichen |
|
||||
| Maximale Länge `errorMessage` / `message` | 2.000 Zeichen |
|
||||
| Maximale Länge `outcome` | 40 Zeichen |
|
||||
|
||||
Gekürzte Ausgaben erhalten den Suffix ` ...[gekürzt]` (bei Inline-Text) bzw. `\n...[gekürzt]` (bei mehrzeiligem Output).
|
||||
|
||||
---
|
||||
|
||||
## Echtzeit-Updates
|
||||
|
||||
Änderungen werden automatisch als [`RUNTIME_ACTIVITY_CHANGED`](websocket.md#runtime_activity_changed) WebSocket-Event gesendet. Die Frontend-Komponente braucht `GET /api/runtime/activities` nur beim initialen Laden aufzurufen.
|
||||
@@ -0,0 +1,424 @@
|
||||
# Settings API
|
||||
|
||||
Endpunkte für Einstellungen, Skripte, Skript-Ketten und User-Presets.
|
||||
|
||||
---
|
||||
|
||||
## GET /api/settings
|
||||
|
||||
Liefert alle Einstellungen kategorisiert.
|
||||
|
||||
**Response (Struktur):**
|
||||
|
||||
```json
|
||||
{
|
||||
"categories": [
|
||||
{
|
||||
"category": "Pfade",
|
||||
"settings": [
|
||||
{
|
||||
"key": "raw_dir",
|
||||
"label": "Raw Ausgabeordner",
|
||||
"type": "path",
|
||||
"required": true,
|
||||
"description": "...",
|
||||
"defaultValue": "data/output/raw",
|
||||
"options": [],
|
||||
"validation": { "minLength": 1 },
|
||||
"value": "data/output/raw",
|
||||
"orderIndex": 100
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## PUT /api/settings/:key
|
||||
|
||||
Aktualisiert eine einzelne Einstellung.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{ "value": "/mnt/storage/raw" }
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"setting": {
|
||||
"key": "raw_dir",
|
||||
"value": "/mnt/storage/raw"
|
||||
},
|
||||
"reviewRefresh": {
|
||||
"triggered": false,
|
||||
"reason": "not_ready"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`reviewRefresh` ist `null` oder ein Objekt mit Status der optionalen Review-Neuberechnung.
|
||||
|
||||
---
|
||||
|
||||
## PUT /api/settings
|
||||
|
||||
Aktualisiert mehrere Einstellungen atomar.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"settings": {
|
||||
"raw_dir": "/mnt/storage/raw",
|
||||
"movie_dir": "/mnt/storage/movies",
|
||||
"handbrake_preset_bluray": "H.264 MKV 1080p30"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"changes": [
|
||||
{ "key": "raw_dir", "value": "/mnt/storage/raw" },
|
||||
{ "key": "movie_dir", "value": "/mnt/storage/movies" }
|
||||
],
|
||||
"reviewRefresh": {
|
||||
"triggered": true,
|
||||
"jobId": 42,
|
||||
"relevantKeys": ["handbrake_preset_bluray"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Bei Validierungsfehlern kommt `400` mit `error.details[]`.
|
||||
|
||||
---
|
||||
|
||||
## GET /api/settings/handbrake-presets
|
||||
|
||||
Liest Preset-Liste via `HandBrakeCLI -z` (mit Fallback auf konfigurierte Presets).
|
||||
|
||||
**Response (Beispiel):**
|
||||
|
||||
```json
|
||||
{
|
||||
"source": "handbrake-cli",
|
||||
"message": null,
|
||||
"options": [
|
||||
{ "label": "General/", "value": "__group__general", "disabled": true, "category": "General" },
|
||||
{ "label": " Fast 1080p30", "value": "Fast 1080p30", "category": "General" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## POST /api/settings/pushover/test
|
||||
|
||||
Sendet Testnachricht über aktuelle PushOver-Settings.
|
||||
|
||||
**Request (optional):**
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "Test",
|
||||
"message": "Ripster Test"
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"sent": true,
|
||||
"eventKey": "test",
|
||||
"requestId": "..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Wenn PushOver deaktiviert ist oder Credentials fehlen, kommt i. d. R. ebenfalls `200` mit `sent: false` + `reason`.
|
||||
|
||||
---
|
||||
|
||||
## Skripte
|
||||
|
||||
Basis: `/api/settings/scripts`
|
||||
|
||||
### GET /api/settings/scripts
|
||||
|
||||
```json
|
||||
{ "scripts": [ { "id": 1, "name": "...", "scriptBody": "...", "orderIndex": 1, "createdAt": "...", "updatedAt": "..." } ] }
|
||||
```
|
||||
|
||||
### POST /api/settings/scripts
|
||||
|
||||
```json
|
||||
{ "name": "Move", "scriptBody": "mv \"$RIPSTER_OUTPUT_PATH\" /mnt/movies/" }
|
||||
```
|
||||
|
||||
Response: `201` mit `{ "script": { ... } }`
|
||||
|
||||
### PUT /api/settings/scripts/:id
|
||||
|
||||
Body wie `POST`, Response `{ "script": { ... } }`.
|
||||
|
||||
### DELETE /api/settings/scripts/:id
|
||||
|
||||
Response `{ "removed": { ... } }`.
|
||||
|
||||
### POST /api/settings/scripts/reorder
|
||||
|
||||
```json
|
||||
{ "orderedScriptIds": [3, 1, 2] }
|
||||
```
|
||||
|
||||
Response `{ "scripts": [ ... ] }`.
|
||||
|
||||
### POST /api/settings/scripts/:id/test
|
||||
|
||||
Führt Skript als Testlauf aus.
|
||||
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"scriptId": 1,
|
||||
"scriptName": "Move",
|
||||
"success": true,
|
||||
"exitCode": 0,
|
||||
"signal": null,
|
||||
"timedOut": false,
|
||||
"durationMs": 120,
|
||||
"stdout": "...",
|
||||
"stderr": "...",
|
||||
"stdoutTruncated": false,
|
||||
"stderrTruncated": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Umgebungsvariablen für Skripte
|
||||
|
||||
Diese Variablen werden beim Ausführen gesetzt:
|
||||
|
||||
- `RIPSTER_SCRIPT_RUN_AT`
|
||||
- `RIPSTER_JOB_ID`
|
||||
- `RIPSTER_JOB_TITLE`
|
||||
- `RIPSTER_MODE`
|
||||
- `RIPSTER_INPUT_PATH`
|
||||
- `RIPSTER_OUTPUT_PATH`
|
||||
- `RIPSTER_RAW_PATH`
|
||||
- `RIPSTER_SCRIPT_ID`
|
||||
- `RIPSTER_SCRIPT_NAME`
|
||||
- `RIPSTER_SCRIPT_SOURCE`
|
||||
|
||||
---
|
||||
|
||||
## Skript-Ketten
|
||||
|
||||
Basis: `/api/settings/script-chains`
|
||||
|
||||
Eine Kette hat Schritte vom Typ:
|
||||
|
||||
- `script` (`scriptId` erforderlich)
|
||||
- `wait` (`waitSeconds` 1..3600)
|
||||
|
||||
### GET /api/settings/script-chains
|
||||
|
||||
Response `{ "chains": [ ... ] }` (inkl. `steps[]`).
|
||||
|
||||
### GET /api/settings/script-chains/:id
|
||||
|
||||
Response `{ "chain": { ... } }`.
|
||||
|
||||
### POST /api/settings/script-chains
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "After Encode",
|
||||
"steps": [
|
||||
{ "stepType": "script", "scriptId": 1 },
|
||||
{ "stepType": "wait", "waitSeconds": 15 },
|
||||
{ "stepType": "script", "scriptId": 2 }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Response: `201` mit `{ "chain": { ... } }`
|
||||
|
||||
### PUT /api/settings/script-chains/:id
|
||||
|
||||
Body wie `POST`, Response `{ "chain": { ... } }`.
|
||||
|
||||
### DELETE /api/settings/script-chains/:id
|
||||
|
||||
Response `{ "removed": { ... } }`.
|
||||
|
||||
### POST /api/settings/script-chains/reorder
|
||||
|
||||
```json
|
||||
{ "orderedChainIds": [2, 1, 3] }
|
||||
```
|
||||
|
||||
Response `{ "chains": [ ... ] }`.
|
||||
|
||||
### POST /api/settings/script-chains/:id/test
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{
|
||||
"result": {
|
||||
"chainId": 2,
|
||||
"chainName": "After Encode",
|
||||
"steps": 3,
|
||||
"succeeded": 3,
|
||||
"failed": 0,
|
||||
"aborted": false,
|
||||
"results": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## User-Presets
|
||||
|
||||
Basis: `/api/settings/user-presets`
|
||||
|
||||
### GET /api/settings/user-presets
|
||||
|
||||
Optionaler Query-Parameter: `media_type=bluray|dvd|other|all`
|
||||
|
||||
```json
|
||||
{
|
||||
"presets": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Blu-ray HQ",
|
||||
"mediaType": "bluray",
|
||||
"handbrakePreset": "H.264 MKV 1080p30",
|
||||
"extraArgs": "--encoder-preset slow",
|
||||
"description": "...",
|
||||
"createdAt": "...",
|
||||
"updatedAt": "..."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### POST /api/settings/user-presets
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Blu-ray HQ",
|
||||
"mediaType": "bluray",
|
||||
"handbrakePreset": "H.264 MKV 1080p30",
|
||||
"extraArgs": "--encoder-preset slow",
|
||||
"description": "optional"
|
||||
}
|
||||
```
|
||||
|
||||
Response: `201` mit `{ "preset": { ... } }`
|
||||
|
||||
### PUT /api/settings/user-presets/:id
|
||||
|
||||
Body mit beliebigen Feldern aus `POST`, Response `{ "preset": { ... } }`.
|
||||
|
||||
### DELETE /api/settings/user-presets/:id
|
||||
|
||||
Response `{ "removed": { ... } }`.
|
||||
|
||||
---
|
||||
|
||||
## Weitere Endpunkte
|
||||
|
||||
### GET /api/settings/effective-paths
|
||||
|
||||
Liefert aufgelöste, effektiv genutzte Pfade aus den Settings (für UI- und Diagnosezwecke).
|
||||
|
||||
### POST /api/settings/coverart/recover
|
||||
|
||||
Startet eine manuelle Coverart-Recovery.
|
||||
|
||||
**Response (Beispiel):**
|
||||
|
||||
```json
|
||||
{
|
||||
"result": { "started": true },
|
||||
"scheduler": { "enabled": true }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Activation Bytes (AAX)
|
||||
|
||||
### GET /api/settings/activation-bytes
|
||||
|
||||
Liest gecachte AAX-Activation-Bytes.
|
||||
|
||||
### POST /api/settings/activation-bytes
|
||||
|
||||
Speichert Activation-Bytes.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{
|
||||
"checksum": "abc123...",
|
||||
"activationBytes": "1a2b3c4d"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Laufwerke
|
||||
|
||||
### GET /api/settings/drives
|
||||
|
||||
Liefert erkannte optische Laufwerke (`/dev/...`) inkl. MakeMKV-Disc-Index.
|
||||
|
||||
### POST /api/settings/drives/force-unlock
|
||||
|
||||
Erzwingt Entsperren aktiver Laufwerkslocks.
|
||||
|
||||
Hinweis: Expertenmodus (`ui_expert_mode`) ist erforderlich, sonst `403`.
|
||||
|
||||
**Request (ein Laufwerk):**
|
||||
|
||||
```json
|
||||
{ "devicePath": "/dev/sr0" }
|
||||
```
|
||||
|
||||
**Request (alle):**
|
||||
|
||||
```json
|
||||
{ "all": true }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## UI Preferences
|
||||
|
||||
### GET /api/settings/prefs/:key
|
||||
|
||||
Liest einen persistierten UI-Preference-Wert.
|
||||
|
||||
### PUT /api/settings/prefs/:key
|
||||
|
||||
Speichert einen persistierten UI-Preference-Wert.
|
||||
|
||||
**Request:**
|
||||
|
||||
```json
|
||||
{ "value": "{\"columns\":[\"id\",\"status\"]}" }
|
||||
```
|
||||
@@ -0,0 +1,294 @@
|
||||
# WebSocket Events
|
||||
|
||||
Ripster sendet Echtzeit-Updates über `/ws`.
|
||||
|
||||
---
|
||||
|
||||
## Verbindung
|
||||
|
||||
```js
|
||||
const ws = new WebSocket('ws://localhost:3001/ws');
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
const msg = JSON.parse(event.data);
|
||||
console.log(msg.type, msg.payload);
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Nachrichtenformat
|
||||
|
||||
Die meisten Broadcasts haben dieses Schema:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "EVENT_TYPE",
|
||||
"payload": {},
|
||||
"timestamp": "2026-03-10T09:00:00.000Z"
|
||||
}
|
||||
```
|
||||
|
||||
Ausnahme: `WS_CONNECTED` beim Verbindungsaufbau enthält kein `timestamp`.
|
||||
|
||||
---
|
||||
|
||||
## Event-Typen
|
||||
|
||||
### WS_CONNECTED
|
||||
|
||||
Sofort nach erfolgreicher Verbindung.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "WS_CONNECTED",
|
||||
"payload": {
|
||||
"connectedAt": "2026-03-10T09:00:00.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### PIPELINE_STATE_CHANGED
|
||||
|
||||
Neuer Pipeline-Snapshot.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "PIPELINE_STATE_CHANGED",
|
||||
"payload": {
|
||||
"state": "ENCODING",
|
||||
"activeJobId": 42,
|
||||
"progress": 62.5,
|
||||
"eta": "00:12:34",
|
||||
"statusText": "ENCODING 62.50%",
|
||||
"context": {},
|
||||
"jobProgress": {
|
||||
"42": {
|
||||
"state": "ENCODING",
|
||||
"progress": 62.5,
|
||||
"eta": "00:12:34",
|
||||
"statusText": "ENCODING 62.50%"
|
||||
}
|
||||
},
|
||||
"queue": {
|
||||
"maxParallelJobs": 1,
|
||||
"runningCount": 1,
|
||||
"queuedCount": 2,
|
||||
"runningJobs": [],
|
||||
"queuedJobs": []
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### PIPELINE_PROGRESS
|
||||
|
||||
Laufende Fortschrittsupdates.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "PIPELINE_PROGRESS",
|
||||
"payload": {
|
||||
"state": "ENCODING",
|
||||
"activeJobId": 42,
|
||||
"progress": 62.5,
|
||||
"eta": "00:12:34",
|
||||
"statusText": "ENCODING 62.50%"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### PIPELINE_QUEUE_CHANGED
|
||||
|
||||
Queue-Snapshot aktualisiert.
|
||||
|
||||
### DISC_DETECTED / DISC_REMOVED
|
||||
|
||||
Disc-Insertion/-Removal.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "DISC_DETECTED",
|
||||
"payload": {
|
||||
"device": {
|
||||
"path": "/dev/sr0",
|
||||
"discLabel": "INCEPTION",
|
||||
"model": "ASUS BW-16D1HT",
|
||||
"fstype": "udf",
|
||||
"mountpoint": null,
|
||||
"mediaProfile": "bluray"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`mediaProfile`: `bluray` | `dvd` | `other` | `null`
|
||||
|
||||
### HARDWARE_MONITOR_UPDATE
|
||||
|
||||
Snapshot aus Hardware-Monitoring.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "HARDWARE_MONITOR_UPDATE",
|
||||
"payload": {
|
||||
"enabled": true,
|
||||
"intervalMs": 5000,
|
||||
"updatedAt": "2026-03-10T09:00:00.000Z",
|
||||
"sample": {
|
||||
"cpu": {},
|
||||
"memory": {},
|
||||
"gpu": {},
|
||||
"storage": {}
|
||||
},
|
||||
"error": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### PIPELINE_ERROR
|
||||
|
||||
Fehler bei Disc-Event-Verarbeitung in Pipeline.
|
||||
|
||||
### DISK_DETECTION_ERROR
|
||||
|
||||
Fehler in Laufwerkserkennung.
|
||||
|
||||
### SETTINGS_UPDATED
|
||||
|
||||
Einzelnes Setting wurde gespeichert.
|
||||
|
||||
### SETTINGS_BULK_UPDATED
|
||||
|
||||
Bulk-Settings gespeichert.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "SETTINGS_BULK_UPDATED",
|
||||
"payload": {
|
||||
"count": 3,
|
||||
"keys": ["raw_dir", "movie_dir", "handbrake_preset_bluray"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### SETTINGS_SCRIPTS_UPDATED
|
||||
|
||||
Skript geändert (`created|updated|deleted|reordered`).
|
||||
|
||||
### SETTINGS_SCRIPT_CHAINS_UPDATED
|
||||
|
||||
Skript-Kette geändert (`created|updated|deleted|reordered`).
|
||||
|
||||
### USER_PRESETS_UPDATED
|
||||
|
||||
User-Preset geändert (`created|updated|deleted`).
|
||||
|
||||
### CRON_JOBS_UPDATED
|
||||
|
||||
Cron-Config geändert (`created|updated|deleted`).
|
||||
|
||||
### CRON_JOB_UPDATED
|
||||
|
||||
Laufzeitstatus eines Cron-Jobs geändert.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "CRON_JOB_UPDATED",
|
||||
"payload": {
|
||||
"id": 1,
|
||||
"lastRunStatus": "running",
|
||||
"lastRunAt": "2026-03-10T10:00:00.000Z",
|
||||
"nextRunAt": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### RUNTIME_ACTIVITY_CHANGED
|
||||
|
||||
Vollständiger Snapshot aller laufenden und kürzlich abgeschlossenen Aktivitäten.
|
||||
|
||||
Wird ausgelöst, wenn eine Aktivität gestartet, aktualisiert oder abgeschlossen wird sowie nach `clear-recent`.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "RUNTIME_ACTIVITY_CHANGED",
|
||||
"payload": {
|
||||
"active": [
|
||||
{
|
||||
"id": 7,
|
||||
"type": "chain",
|
||||
"name": "Post-Encode Aufräumen",
|
||||
"status": "running",
|
||||
"source": "cron",
|
||||
"message": "Schritt 2 von 3",
|
||||
"currentStep": "cleanup.sh",
|
||||
"currentStepType": "script",
|
||||
"stepIndex": 2,
|
||||
"stepTotal": 3,
|
||||
"canCancel": true,
|
||||
"canNextStep": false,
|
||||
"outcome": "running",
|
||||
"startedAt": "2026-03-10T10:00:00.000Z",
|
||||
"finishedAt": null,
|
||||
"durationMs": null
|
||||
}
|
||||
],
|
||||
"recent": [],
|
||||
"updatedAt": "2026-03-10T10:00:05.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Vollständige Feldbeschreibung: [Runtime Activities API](runtime-activities.md).
|
||||
|
||||
### CONVERTER_SCAN_UPDATE
|
||||
|
||||
Wird nach einem Scan des Converter-Eingangsordners gesendet (manuell oder per Polling).
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "CONVERTER_SCAN_UPDATE",
|
||||
"payload": {
|
||||
"entryCount": 12
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### DOWNLOADS_UPDATED
|
||||
|
||||
Wird bei jeder Statusänderung in der Download-Queue gesendet.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "DOWNLOADS_UPDATED",
|
||||
"payload": {
|
||||
"reason": "ready",
|
||||
"item": {
|
||||
"id": "dl-1",
|
||||
"jobId": 42,
|
||||
"status": "ready",
|
||||
"archiveName": "Job_42_movie.zip",
|
||||
"createdAt": "2026-03-30T10:00:00.000Z"
|
||||
},
|
||||
"summary": {
|
||||
"total": 3,
|
||||
"pending": 1,
|
||||
"processing": 0,
|
||||
"ready": 1,
|
||||
"failed": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Mögliche `reason`-Werte: `queued`, `processing`, `ready`, `failed`, `deleted`.
|
||||
|
||||
---
|
||||
|
||||
## Reconnect-Verhalten
|
||||
|
||||
`useWebSocket` verbindet bei Abbruch automatisch neu:
|
||||
|
||||
- Retry-Intervall: `1500ms`
|
||||
- Wiederverbindung bis Komponente unmounted wird
|
||||
@@ -0,0 +1,30 @@
|
||||
# Technischer Anhang
|
||||
|
||||
Dieser Bereich enthält die technische Referenz hinter dem Benutzerhandbuch.
|
||||
|
||||
## Inhalt
|
||||
|
||||
- **Konfiguration**
|
||||
- komplette Feldreferenz
|
||||
- Umgebungsvariablen
|
||||
- **Pipeline intern**
|
||||
- Zustandsmodell
|
||||
- Encode-Planung
|
||||
- Playlist-Analyse
|
||||
- Pre-/Post-Encode-Ausführungen
|
||||
- **API-Referenz**
|
||||
- REST-Endpunkte
|
||||
- WebSocket-Events
|
||||
- **Architektur**
|
||||
- Backend-/Frontend-Aufbau
|
||||
- Datenbank
|
||||
- **Deployment**
|
||||
- Betrieb in Entwicklung und Produktion
|
||||
- **Externe Tools**
|
||||
- MakeMKV, HandBrake, MediaInfo
|
||||
|
||||
## Wann du in den Anhang wechselst
|
||||
|
||||
- du integrierst Ripster mit anderen Systemen
|
||||
- du betreibst mehrere Instanzen oder willst tiefer debuggen
|
||||
- du brauchst Feld-/API-/Schema-Details für Automatisierung
|
||||
@@ -0,0 +1,241 @@
|
||||
# Backend-Services
|
||||
|
||||
Das Backend ist in Services aufgeteilt, die von Express-Routen orchestriert werden. Seit v0.12.0 erfolgt die Medienverarbeitung über ein **Plugin-System**.
|
||||
|
||||
---
|
||||
|
||||
## Plugin-System (`src/plugins/`)
|
||||
|
||||
Ab v0.12.0 ist die Pipeline modular aufgebaut. Jeder Medientyp wird von einem eigenen Plugin verwaltet.
|
||||
|
||||
### Basisklassen
|
||||
|
||||
- **`PluginBase.js`** — Abstrakte Basisklasse `SourcePlugin` mit Lifecycle-Methoden
|
||||
- **`PluginRegistry.js`** — Dynamische Plugin-Erkennung, prioritätsbasierte Auswahl, Settings-Schema-Aggregation
|
||||
- **`PluginContext.js`** — Ausführungskontext (Logger, Callbacks, Signals) für Plugin-Aufrufe
|
||||
|
||||
### Plugin-Lifecycle
|
||||
|
||||
Jedes Plugin implementiert die folgenden Methoden:
|
||||
|
||||
| Methode | Beschreibung |
|
||||
|---|---|
|
||||
| `detect(discInfo)` | Medientyp-Erkennung |
|
||||
| `analyze(devicePath, job, ctx)` | Analyse / Metadaten-Extraktion |
|
||||
| `rip(job, ctx)` | Rohdaten-Extraktion |
|
||||
| `review(job, ctx)` | Optionale Vorschau-Vorbereitung |
|
||||
| `encode(job, ctx)` | Finales Encoding/Konvertierung |
|
||||
| `finalize(job, ctx)` | Nachbearbeitung |
|
||||
| `onCancel(job, ctx)` | Bereinigung bei Abbruch |
|
||||
| `onRetry(job, ctx)` | Zustand-Reset vor Retry |
|
||||
|
||||
### Implementierte Plugins
|
||||
|
||||
- **`BluRayPlugin.js`** — Blu-ray via MakeMKV (Backup-Modus)
|
||||
- **`DVDPlugin.js`** — DVD via MakeMKV (MKV-Modus)
|
||||
- **`CdPlugin.js`** — Audio-CD via cdparanoia + FFmpeg (experimentell)
|
||||
- **`AudiobookPlugin.js`** — AAX/M4B via FFmpeg mit Kapitel-Splitting
|
||||
- **`ConverterPlugin.js`** — Generische Audio/Video-Konvertierung via FFmpeg
|
||||
- **`VideoDiscPlugin.js`** — Gemeinsame Basis für Blu-ray/DVD (MediaInfo-Parsing)
|
||||
|
||||
---
|
||||
|
||||
## `pipelineService.js`
|
||||
|
||||
Zentrale Workflow-Orchestrierung.
|
||||
|
||||
Aufgaben:
|
||||
|
||||
- Pipeline-State-Machine + Persistenz (`pipeline_state`)
|
||||
- Disc-Analyse/Rip/Review/Encode via Plugin-Delegation
|
||||
- Queue-Management (Jobs + `script|chain|wait` Einträge)
|
||||
- Retry/Re-Encode/Restart-Flows
|
||||
- WebSocket-Broadcasts für State/Progress/Queue
|
||||
- Converter-Job-Verwaltung (`createConverterJobFromEntry`, `uploadConverterFiles`, `startConverterJob`)
|
||||
|
||||
Wichtige Methoden:
|
||||
|
||||
- `analyzeDisc()`
|
||||
- `selectMetadata()`
|
||||
- `startPreparedJob()`
|
||||
- `confirmEncodeReview()`
|
||||
- `cancel()`
|
||||
- `retry()`
|
||||
- `reencodeFromRaw()`
|
||||
- `restartReviewFromRaw()`
|
||||
- `restartEncodeWithLastSettings()`
|
||||
- `resumeReadyToEncodeJob()`
|
||||
- `enqueueNonJobEntry()`, `reorderQueue()`, `removeQueueEntry()`
|
||||
- `createConverterJobFromEntry()`, `createConverterJobsFromSelection()`
|
||||
- `uploadConverterFiles()`, `startConverterJob()`
|
||||
|
||||
---
|
||||
|
||||
## `diskDetectionService.js`
|
||||
|
||||
Pollt Laufwerk(e) und emittiert:
|
||||
|
||||
- `discInserted`
|
||||
- `discRemoved`
|
||||
- `error`
|
||||
|
||||
Zusatz:
|
||||
|
||||
- Modus `auto` oder `explicit`
|
||||
- heuristische `mediaProfile`-Erkennung (`bluray`/`dvd`/`other`)
|
||||
- `rescanAndEmit()` für manuellen Trigger
|
||||
|
||||
---
|
||||
|
||||
## `settingsService.js`
|
||||
|
||||
Settings-Layer mit Validation/Serialisierung.
|
||||
|
||||
Features:
|
||||
|
||||
- `getCategorizedSettings()` für UI-Form
|
||||
- `setSettingValue()` / `setSettingsBulk()`
|
||||
- profilspezifische Auflösung (`resolveEffectiveToolSettings`)
|
||||
- CLI-Config-Building für MakeMKV/HandBrake/MediaInfo/FFmpeg
|
||||
- HandBrake-Preset-Liste via `HandBrakeCLI -z`
|
||||
- MakeMKV-Key-Synchronisation aus `makemkv_registration_key` nach `~/.MakeMKV/settings.conf`
|
||||
- Pfadauflösung für alle Medienprofile inkl. Audiobook und Converter
|
||||
|
||||
---
|
||||
|
||||
## `historyService.js`
|
||||
|
||||
Historie + Dateioperationen.
|
||||
|
||||
Features:
|
||||
|
||||
- Job-Liste/Detail inkl. Log-Tail
|
||||
- Orphan-RAW-Erkennung und Import
|
||||
- TMDb-Neuzuordnung
|
||||
- Dateilöschung (`raw|movie|both`)
|
||||
- Job-Löschung (`none|raw|movie|both`)
|
||||
|
||||
---
|
||||
|
||||
## `audiobookService.js`
|
||||
|
||||
Audiobook-Verarbeitung (AAX/M4B).
|
||||
|
||||
Features:
|
||||
|
||||
- FFprobe-basierte Analyse (Kapitel, Metadaten)
|
||||
- FFmpeg-basiertes Encoding mit Kapitel-Splitting
|
||||
- Ausgabeformate: M4B, MP3, FLAC
|
||||
- Template-basierte Pfade (`{author}`, `{title}`, `{year}`, `{narrator}`, `{series}`, `{part}`)
|
||||
|
||||
---
|
||||
|
||||
## `activationBytesService.js`
|
||||
|
||||
Verwaltung von Audible-Activation-Bytes für AAX-DRM-Handling.
|
||||
|
||||
Features:
|
||||
|
||||
- SHA-1-Prüfsumme der AAX-Datei berechnen
|
||||
- Activation Bytes in `aax_activation_bytes`-Tabelle cachen
|
||||
- Lookup via `audnexService` (wenn konfiguriert)
|
||||
|
||||
---
|
||||
|
||||
## `converterScanService.js`
|
||||
|
||||
Dateisystem-Überwachung des Converter-Eingangsordners.
|
||||
|
||||
Features:
|
||||
|
||||
- Vollständiger FS-Baum (`getTree()`)
|
||||
- DB-basierter Datei-Explorer (`getEntries()`)
|
||||
- Manueller und automatischer Scan (Polling)
|
||||
- Pfad-Normalisierung mit Traversal-Schutz
|
||||
- WebSocket-Broadcast: `CONVERTER_SCAN_UPDATE`
|
||||
|
||||
---
|
||||
|
||||
## `downloadService.js`
|
||||
|
||||
Download-Queue für Ausgabedateien aus der Historie.
|
||||
|
||||
Features:
|
||||
|
||||
- Job in Download-Queue einreihen (`enqueueHistoryJob`)
|
||||
- ZIP-Archiv aus Ausgabedateien erstellen (`archiver`)
|
||||
- Datei-Streaming via `res.download()`
|
||||
- WebSocket-Broadcast: `DOWNLOADS_UPDATED` bei Status-Änderungen
|
||||
- Download-Item löschen
|
||||
|
||||
---
|
||||
|
||||
## `cronService.js`
|
||||
|
||||
Integriertes Cron-System ohne externe Parser-Library.
|
||||
|
||||
Features:
|
||||
|
||||
- 5-Feld-Cron-Parser + `nextRun`-Berechnung
|
||||
- Quellen: `script` oder `chain`
|
||||
- Laufzeitlogs (`cron_run_logs`)
|
||||
- manuelles Triggern
|
||||
- WebSocket-Events: `CRON_JOBS_UPDATED`, `CRON_JOB_UPDATED`
|
||||
|
||||
---
|
||||
|
||||
## `runtimeActivityService.js`
|
||||
|
||||
In-Memory-Tracking aller laufenden und kürzlich abgeschlossenen Aktivitäten (Skripte, Ketten, Cron-Jobs, Tasks).
|
||||
|
||||
Features:
|
||||
|
||||
- `startActivity(type, payload)` → Aktivität registrieren, ID zurückgeben
|
||||
- `updateActivity(id, patch)` → Laufende Aktivität aktualisieren
|
||||
- `completeActivity(id, payload)` → Aktivität abschließen und in `recent` verschieben
|
||||
- `setControls(id, { cancel, nextStep })` → Steuer-Handler registrieren (für `canCancel`/`canNextStep`)
|
||||
- `requestCancel(id)` / `requestNextStep(id)` → Steuer-Handler aufrufen
|
||||
- `clearRecent()` → Abgeschlossene Aktivitäten löschen
|
||||
- `getSnapshot()` → Snapshot mit `active` + `recent` + `updatedAt`
|
||||
- Broadcasts `RUNTIME_ACTIVITY_CHANGED` über WebSocket bei jeder Änderung
|
||||
|
||||
Limits:
|
||||
|
||||
- `recent` max. 120 Einträge
|
||||
- `stdout`/`stderr`/`output` max. 12.000 Zeichen
|
||||
- `message`/`errorMessage` max. 2.000 Zeichen
|
||||
|
||||
Vollständige API-Dokumentation: [Runtime Activities API](../api/runtime-activities.md)
|
||||
|
||||
---
|
||||
|
||||
## Weitere Services
|
||||
|
||||
- `scriptService.js` (CRUD + Test + Wrapper-Ausführung)
|
||||
- `scriptChainService.js` (CRUD + Step-Execution)
|
||||
- `userPresetService.js` (HandBrake User-Presets)
|
||||
- `hardwareMonitorService.js` (CPU/RAM/GPU/Storage)
|
||||
- `websocketService.js` (Client-Registry + Broadcast)
|
||||
- `notificationService.js` (PushOver)
|
||||
- `cdRipService.js` (CD-Ripping mit cdparanoia)
|
||||
- `musicBrainzService.js` (MusicBrainz-Metadaten-Lookup)
|
||||
- `audnexService.js` (Audnex-API für Audiobook-Metadaten)
|
||||
- `coverArtRecoveryService.js` (Cover-Art-Wiederherstellung)
|
||||
- `thumbnailService.js` (Vorschaubild-Generierung)
|
||||
- `tmdbService.js` (Film-/Serien-Metadaten-Suche)
|
||||
- `logger.js` (rotierende Datei-Logs)
|
||||
|
||||
---
|
||||
|
||||
## Bootstrapping (`src/index.js`)
|
||||
|
||||
Beim Start:
|
||||
|
||||
1. DB init/migrate
|
||||
2. Pipeline-Init (inkl. Plugin-Registry)
|
||||
3. Cron-Init
|
||||
4. Express-Routes + Error-Handler
|
||||
5. WebSocket-Server auf `/ws`
|
||||
6. Hardware-Monitoring-Init
|
||||
7. Disk-Detection-Start
|
||||
8. Converter-Scan-Service-Init (Polling falls aktiviert)
|
||||
@@ -0,0 +1,203 @@
|
||||
# Datenbank
|
||||
|
||||
Ripster verwendet SQLite (`backend/data/ripster.db`).
|
||||
|
||||
---
|
||||
|
||||
## Tabellen
|
||||
|
||||
```text
|
||||
settings_schema
|
||||
settings_values
|
||||
jobs
|
||||
job_lineage_artifacts
|
||||
job_output_folders
|
||||
pipeline_state
|
||||
scripts
|
||||
script_chains
|
||||
script_chain_steps
|
||||
user_presets
|
||||
cron_jobs
|
||||
cron_run_logs
|
||||
aax_activation_bytes
|
||||
user_prefs
|
||||
converter_scan_entries
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## `jobs`
|
||||
|
||||
Speichert Pipeline-Lifecycle und Artefakte pro Job.
|
||||
|
||||
Zentrale Felder:
|
||||
|
||||
- Metadaten: `title`, `year`, `imdb_id`, `poster_url`, `omdb_json`, `selected_from_omdb`
|
||||
- Laufzeit: `start_time`, `end_time`, `status`, `last_state`
|
||||
- Pfade: `raw_path`, `output_path`, `encode_input_path`
|
||||
- Tool-Ausgaben: `makemkv_info_json`, `handbrake_info_json`, `mediainfo_info_json`, `encode_plan_json`
|
||||
- Kontrolle: `encode_review_confirmed`, `rip_successful`, `error_message`
|
||||
- Medientyp: `media_type` (`bluray|dvd|cd|audiobook|converter`)
|
||||
- Job-Typ/Beziehung: `job_kind`, `parent_job_id`
|
||||
- Multipart-/Disc-Merkmale: `is_multipart_movie`, `disc_number`, `metadata_fingerprint`
|
||||
- Prüfsumme: `aax_checksum` (für AAX-Dateien)
|
||||
- Audit: `created_at`, `updated_at`
|
||||
|
||||
Typische `job_kind`-Werte:
|
||||
|
||||
- Standard: `bluray`, `dvd`, `cd`, `audiobook`, `converter_audio`, `converter_video`, `converter_iso`
|
||||
- Serien: `dvd_series_container`, `dvd_series_child`
|
||||
- Multipart Film: `multipart_movie_container`, `multipart_movie_child`
|
||||
|
||||
Wichtige Indizes:
|
||||
|
||||
- `idx_jobs_status`
|
||||
- `idx_jobs_parent_job_id`
|
||||
- `idx_jobs_job_kind`
|
||||
- `idx_jobs_disc_number`
|
||||
- `idx_jobs_metadata_fingerprint`
|
||||
|
||||
---
|
||||
|
||||
## `job_lineage_artifacts`
|
||||
|
||||
Verknüpft Jobs mit ihren Quell-Jobs (z. B. Re-Encode aus einem vorherigen Rip).
|
||||
|
||||
Felder:
|
||||
|
||||
- `job_id` — der abgeleitete Job
|
||||
- `source_job_id` — der Quell-Job
|
||||
- `artifact_type` — Art der Verknüpfung (z. B. `reencode`, `restart_review`)
|
||||
- `created_at`
|
||||
|
||||
---
|
||||
|
||||
## `job_output_folders`
|
||||
|
||||
Verfolgt Ausgabepfade pro Job (mehrere Ausgaben möglich, z. B. bei Kapitel-Splitting).
|
||||
|
||||
Felder:
|
||||
|
||||
- `job_id`
|
||||
- `folder_path`
|
||||
- `label` — optionaler Bezeichner
|
||||
- `created_at`
|
||||
|
||||
---
|
||||
|
||||
## `pipeline_state`
|
||||
|
||||
Singleton-Tabelle (`id = 1`) für aktiven Snapshot:
|
||||
|
||||
- `state`
|
||||
- `active_job_id`
|
||||
- `progress`
|
||||
- `eta`
|
||||
- `status_text`
|
||||
- `context_json`
|
||||
- `updated_at`
|
||||
|
||||
---
|
||||
|
||||
## `settings_schema` + `settings_values`
|
||||
|
||||
- `settings_schema`: Definition (Typ, Default, Validation, Reihenfolge)
|
||||
- `settings_values`: aktueller Wert pro Key
|
||||
|
||||
---
|
||||
|
||||
## `scripts`, `script_chains`, `script_chain_steps`
|
||||
|
||||
- `scripts`: Shell-Skripte (`name`, `script_body`, `order_index`)
|
||||
- `script_chains`: Ketten (`name`, `order_index`)
|
||||
- `script_chain_steps`: Schritte je Kette
|
||||
- `step_type`: `script` oder `wait`
|
||||
- `script_id` oder `wait_seconds`
|
||||
|
||||
---
|
||||
|
||||
## `user_presets`
|
||||
|
||||
Benannte HandBrake-Preset-Sets:
|
||||
|
||||
- `name`
|
||||
- `media_type` (`bluray|dvd|other|all`)
|
||||
- `handbrake_preset`
|
||||
- `extra_args`
|
||||
- `description`
|
||||
|
||||
---
|
||||
|
||||
## `cron_jobs` + `cron_run_logs`
|
||||
|
||||
- `cron_jobs`: Zeitplan + Status
|
||||
- `cron_run_logs`: einzelne Läufe
|
||||
- `status`: `running|success|error`
|
||||
- `output`
|
||||
- `error_message`
|
||||
|
||||
---
|
||||
|
||||
## `aax_activation_bytes`
|
||||
|
||||
Cache für Audible-Activation-Bytes (AAX-DRM).
|
||||
|
||||
Felder:
|
||||
|
||||
- `checksum` — SHA-1-Prüfsumme der AAX-Datei (Primärschlüssel)
|
||||
- `activation_bytes` — Hex-String der Activation Bytes
|
||||
- `created_at`
|
||||
|
||||
---
|
||||
|
||||
## `user_prefs`
|
||||
|
||||
Benutzer-spezifische Einstellungen (Key-Value).
|
||||
|
||||
Felder:
|
||||
|
||||
- `key`
|
||||
- `value`
|
||||
- `updated_at`
|
||||
|
||||
---
|
||||
|
||||
## `converter_scan_entries`
|
||||
|
||||
DB-seitige Erfassung gescannter Dateien im Converter-Eingangsordner.
|
||||
|
||||
Felder:
|
||||
|
||||
- `rel_path` — relativer Pfad zum `converter_raw_dir`
|
||||
- `is_dir` — Verzeichnis-Flag
|
||||
- `size` — Dateigröße in Bytes
|
||||
- `modified_at` — Datei-Änderungsdatum
|
||||
- `job_id` — zugewiesener Converter-Job (falls vorhanden)
|
||||
- `scanned_at`
|
||||
|
||||
---
|
||||
|
||||
## Migration/Recovery
|
||||
|
||||
Beim Start werden Schema und Settings-Metadaten automatisch abgeglichen.
|
||||
|
||||
Bei korruptem SQLite-File:
|
||||
|
||||
1. Datei wird nach `backend/data/corrupt-backups/` verschoben
|
||||
2. neue DB wird initialisiert
|
||||
3. Schema wird neu aufgebaut
|
||||
|
||||
---
|
||||
|
||||
## Direkte Inspektion
|
||||
|
||||
```bash
|
||||
sqlite3 backend/data/ripster.db
|
||||
|
||||
.mode table
|
||||
SELECT id, status, title, media_type, created_at FROM jobs ORDER BY created_at DESC;
|
||||
SELECT id, parent_job_id, job_kind, is_multipart_movie, disc_number FROM jobs ORDER BY created_at DESC;
|
||||
SELECT key, value FROM settings_values ORDER BY key;
|
||||
SELECT checksum, activation_bytes FROM aax_activation_bytes;
|
||||
SELECT rel_path, job_id FROM converter_scan_entries;
|
||||
```
|
||||
@@ -0,0 +1,125 @@
|
||||
# Frontend-Komponenten
|
||||
|
||||
Frontend: React + PrimeReact + Vite.
|
||||
|
||||
---
|
||||
|
||||
## Hauptseiten
|
||||
|
||||
### `RipperPage.jsx`
|
||||
|
||||
Pipeline-Steuerung:
|
||||
|
||||
- Status/Progress/ETA
|
||||
- Metadaten-Dialog
|
||||
- Playlist-Entscheidung
|
||||
- Review-Panel (Track-Auswahl)
|
||||
- Queue-Interaktion (reorder/add/remove)
|
||||
- Job-Aktionen (Start/Cancel/Retry/Re-Encode)
|
||||
- Hardware-Monitoring-Anzeige
|
||||
- Aktivitäts-Tracking (Skripte, Ketten, Cron)
|
||||
|
||||
### `SettingsPage.jsx`
|
||||
|
||||
Konfiguration:
|
||||
|
||||
- dynamisches Settings-Formular (`DynamicSettingsForm`)
|
||||
- Skripte/Ketten inkl. Reorder/Test
|
||||
- User-Presets
|
||||
- Cron-Jobs (`CronJobsTab`)
|
||||
|
||||
### `HistoryPage.jsx`
|
||||
|
||||
Historie:
|
||||
|
||||
- Job-Liste/Filter
|
||||
- Job-Details + Logs
|
||||
- TMDb-Neuzuordnung
|
||||
- Re-Encode/Restart-Workflows
|
||||
|
||||
### `ConverterPage.jsx`
|
||||
|
||||
Datei-Converter:
|
||||
|
||||
- Datei-Explorer des Converter-Eingangsordners (Baum-Ansicht)
|
||||
- Upload von Audio/Video-Dateien (bis zu 50 Dateien gleichzeitig)
|
||||
- Dateiverwaltung: Umbenennen, Verschieben, Löschen, Ordner erstellen
|
||||
- Jobs aus Dateiauswahl erstellen
|
||||
- Converter-Job-Konfiguration (Ausgabeformat, Preset, Tracks)
|
||||
- Job-Start, Abbruch, Löschung
|
||||
- Automatischer Scan-Status
|
||||
|
||||
### `AudiobooksPage.jsx`
|
||||
|
||||
Dedizierter AAX-/Audiobook-Flow:
|
||||
|
||||
- Upload-Panel für AAX-Dateien
|
||||
- aktive Audiobook-Jobkarten mit Start/Cancel/Retry/Delete
|
||||
- Audiobook-Konfigurationspanel und Output-Explorer
|
||||
|
||||
### `DownloadsPage.jsx`
|
||||
|
||||
Download-Queue:
|
||||
|
||||
- Ausgabedateien aus der Job-Historie in die Queue einreihen
|
||||
- Download-Status verfolgen (ausstehend, wird verarbeitet, bereit, fehlgeschlagen)
|
||||
- Dateien als ZIP herunterladen
|
||||
- Download-Einträge löschen
|
||||
|
||||
### `DatabasePage.jsx`
|
||||
|
||||
Expert-Modus:
|
||||
|
||||
- Tabellarische Rohsicht der Job-Datenbank
|
||||
- Orphan-RAW-Import
|
||||
|
||||
---
|
||||
|
||||
## Wichtige Komponenten
|
||||
|
||||
- `PipelineStatusCard.jsx` — Pipeline-Status-Anzeige mit Progress
|
||||
- `MetadataSelectionDialog.jsx` — TMDb-Metadaten-Auswahl
|
||||
- `MediaInfoReviewPanel.jsx` — Track-Auswahl-Interface (Video/Audio/Untertitel)
|
||||
- `JobDetailDialog.jsx` — Job-Detailansicht mit Logs
|
||||
- `CronJobsTab.jsx` — Cron-Job-Verwaltung
|
||||
- `DynamicSettingsForm.jsx` — Schema-gesteuertes Einstellungsformular
|
||||
- `ConverterJobCard.jsx` — Converter-Job-Darstellung
|
||||
- `CdRipConfigPanel.jsx` — Konfiguration für Audio-CD-Ripping
|
||||
|
||||
---
|
||||
|
||||
## API-Client (`api/client.js`)
|
||||
|
||||
- zentraler `request()` mit JSON-Handling
|
||||
- Fehlerobjekt aus API wird auf `Error(message)` gemappt
|
||||
- `VITE_API_BASE` default `/api`
|
||||
|
||||
---
|
||||
|
||||
## WebSocket (`hooks/useWebSocket.js`)
|
||||
|
||||
- URL: `VITE_WS_URL` oder automatisch `ws(s)://<host>/ws`
|
||||
- Auto-Reconnect mit 1500ms Intervall
|
||||
|
||||
In `App.jsx` werden u. a. verarbeitet:
|
||||
|
||||
- `PIPELINE_STATE_CHANGED`
|
||||
- `PIPELINE_PROGRESS`
|
||||
- `PIPELINE_QUEUE_CHANGED`
|
||||
- Disk erkannt / Disk entfernt
|
||||
- `HARDWARE_MONITOR_UPDATE`
|
||||
- `DOWNLOADS_UPDATED`
|
||||
- `CONVERTER_SCAN_UPDATE`
|
||||
- `RUNTIME_ACTIVITY_CHANGED`
|
||||
|
||||
---
|
||||
|
||||
## Build/Run
|
||||
|
||||
```bash
|
||||
# dev
|
||||
npm run dev --prefix frontend
|
||||
|
||||
# prod build
|
||||
npm run build --prefix frontend
|
||||
```
|
||||
@@ -0,0 +1,52 @@
|
||||
# Anhang: Architektur
|
||||
|
||||
Ripster ist eine Client-Server-Anwendung mit REST + WebSocket und externen CLI-Tools.
|
||||
|
||||
---
|
||||
|
||||
## Systemüberblick
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph Browser["Browser (React)"]
|
||||
Ripper[Ripper]
|
||||
Settings[Einstellungen]
|
||||
History[Historie]
|
||||
end
|
||||
|
||||
subgraph Backend["Node.js Backend"]
|
||||
API[REST API\nExpress]
|
||||
WS[WebSocket\n/ws]
|
||||
Pipeline[pipelineService]
|
||||
Cron[cronService]
|
||||
DB[(SQLite)]
|
||||
end
|
||||
|
||||
subgraph Tools["Externe Tools"]
|
||||
MakeMKV[makemkvcon]
|
||||
HandBrake[HandBrakeCLI]
|
||||
MediaInfo[mediainfo]
|
||||
end
|
||||
|
||||
Browser <-->|HTTP| API
|
||||
Browser <-->|WebSocket| WS
|
||||
Pipeline --> MakeMKV
|
||||
Pipeline --> HandBrake
|
||||
Pipeline --> MediaInfo
|
||||
API --> DB
|
||||
Pipeline --> DB
|
||||
Cron --> DB
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Details
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- [:octicons-arrow-right-24: Übersicht](overview.md)
|
||||
- [:octicons-arrow-right-24: Backend-Services](backend.md)
|
||||
- [:octicons-arrow-right-24: Frontend-Komponenten](frontend.md)
|
||||
- [:octicons-arrow-right-24: Datenbank](database.md)
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,94 @@
|
||||
# Architektur-Übersicht
|
||||
|
||||
---
|
||||
|
||||
## Kernprinzipien
|
||||
|
||||
### Event-getriebene Pipeline
|
||||
|
||||
`pipelineService` hält einen Snapshot der State-Machine und broadcastet Änderungen sofort via WebSocket.
|
||||
|
||||
```text
|
||||
State-Änderung -> PIPELINE_STATE_CHANGED/PIPELINE_PROGRESS -> Frontend-Update
|
||||
```
|
||||
|
||||
### Service-Layer
|
||||
|
||||
```text
|
||||
Route -> Service -> DB/Tool-Execution
|
||||
```
|
||||
|
||||
Routes enthalten kaum Business-Logik.
|
||||
|
||||
### Schema-getriebene Settings
|
||||
|
||||
Settings sind DB-schema-getrieben (`settings_schema` + `settings_values`), UI rendert dynamisch aus diesen Daten.
|
||||
|
||||
---
|
||||
|
||||
## Echtzeit-Kommunikation
|
||||
|
||||
WebSocket läuft auf `/ws`.
|
||||
|
||||
Wichtige Events:
|
||||
|
||||
- `PIPELINE_STATE_CHANGED`, `PIPELINE_PROGRESS`, `PIPELINE_QUEUE_CHANGED`
|
||||
- Disk erkannt, Disk entfernt
|
||||
- `HARDWARE_MONITOR_UPDATE`
|
||||
- `SETTINGS_UPDATED`, `SETTINGS_BULK_UPDATED`
|
||||
- `SETTINGS_SCRIPTS_UPDATED`, `SETTINGS_SCRIPT_CHAINS_UPDATED`, `USER_PRESETS_UPDATED`
|
||||
- `CRON_JOBS_UPDATED`, `CRON_JOB_UPDATED`
|
||||
- `PIPELINE_ERROR`, `DISK_DETECTION_ERROR`
|
||||
|
||||
---
|
||||
|
||||
## Prozessausführung
|
||||
|
||||
Externe Tools werden als Child-Processes gestartet (`processRunner`):
|
||||
|
||||
- Streaming von stdout/stderr
|
||||
- Progress-Parsing (`progressParsers.js`)
|
||||
- kontrollierter Abbruch (SIGINT/SIGKILL-Fallback)
|
||||
|
||||
---
|
||||
|
||||
## Persistenz
|
||||
|
||||
SQLite-Datei: `backend/data/ripster.db`
|
||||
|
||||
Kern-Tabellen:
|
||||
|
||||
- `jobs`, `pipeline_state`
|
||||
- `settings_schema`, `settings_values`
|
||||
- `scripts`, `script_chains`, `script_chain_steps`
|
||||
- `user_presets`
|
||||
- `cron_jobs`, `cron_run_logs`
|
||||
|
||||
Beim Start werden Schema und Settings-Migrationen automatisch ausgeführt.
|
||||
|
||||
---
|
||||
|
||||
## Fehlerbehandlung
|
||||
|
||||
Zentrales Error-Handling liefert:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"message": "...",
|
||||
"statusCode": 400,
|
||||
"reqId": "...",
|
||||
"details": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Fehlgeschlagene Jobs bleiben in der Historie (`Fehler` oder `Abgebrochen`) und können erneut gestartet werden.
|
||||
|
||||
---
|
||||
|
||||
## CORS & Runtime-Konfig
|
||||
|
||||
- `CORS_ORIGIN` default: `*`
|
||||
- `LOG_LEVEL` default: `info`
|
||||
- DB-/Log-Pfade über `DB_PATH`/`LOG_DIR` konfigurierbar
|
||||
@@ -0,0 +1,67 @@
|
||||
# Umgebungsvariablen
|
||||
|
||||
Umgebungsvariablen steuern Backend/Vite außerhalb der DB-basierten UI-Settings.
|
||||
|
||||
---
|
||||
|
||||
## Backend (`backend/.env`)
|
||||
|
||||
| Variable | Default (Code) | Beschreibung |
|
||||
|---------|------------------|-------------|
|
||||
| `PORT` | `3001` | Express-Port |
|
||||
| `DB_PATH` | `backend/data/ripster.db` | SQLite-Datei (relativ zu `backend/`) |
|
||||
| `LOG_DIR` | `backend/logs` | Fallback-Logverzeichnis (wenn `log_dir`-Setting nicht gesetzt/lesbar) |
|
||||
| `CORS_ORIGIN` | `*` | CORS-Origin für API |
|
||||
| `LOG_LEVEL` | `info` | `debug`, `info`, `warn`, `error` |
|
||||
|
||||
Beispiel:
|
||||
|
||||
```env
|
||||
PORT=3001
|
||||
DB_PATH=/var/lib/ripster/ripster.db
|
||||
LOG_DIR=/var/log/ripster
|
||||
CORS_ORIGIN=http://192.168.1.50:5173
|
||||
LOG_LEVEL=info
|
||||
```
|
||||
|
||||
Hinweis: `backend/.env.example` enthält bewusst dev-freundliche Werte (z. B. lokaler `CORS_ORIGIN`).
|
||||
|
||||
---
|
||||
|
||||
## Frontend (`frontend/.env`)
|
||||
|
||||
| Variable | Default | Beschreibung |
|
||||
|---------|---------|-------------|
|
||||
| `VITE_API_BASE` | `/api` | API-Basis für Fetch-Client |
|
||||
| `VITE_WS_URL` | automatisch aus `window.location` + `/ws` | Optional explizite WebSocket-URL |
|
||||
| `VITE_PUBLIC_ORIGIN` | leer | Öffentliche Vite-Origin (Remote-Dev) |
|
||||
| `VITE_ALLOWED_HOSTS` | `true` | Komma-separierte Hostliste für Vite `allowedHosts` |
|
||||
| `VITE_HMR_PROTOCOL` | abgeleitet aus `VITE_PUBLIC_ORIGIN` | HMR-Protokoll (`ws`/`wss`) |
|
||||
| `VITE_HMR_HOST` | abgeleitet aus `VITE_PUBLIC_ORIGIN` | HMR-Host |
|
||||
| `VITE_HMR_CLIENT_PORT` | abgeleitet aus `VITE_PUBLIC_ORIGIN` | HMR-Client-Port |
|
||||
|
||||
Beispiele:
|
||||
|
||||
```env
|
||||
# lokal (mit Vite-Proxy)
|
||||
VITE_API_BASE=/api
|
||||
```
|
||||
|
||||
```env
|
||||
# remote dev
|
||||
VITE_API_BASE=http://192.168.1.50:3001/api
|
||||
VITE_WS_URL=ws://192.168.1.50:3001/ws
|
||||
VITE_PUBLIC_ORIGIN=http://192.168.1.50:5173
|
||||
VITE_ALLOWED_HOSTS=192.168.1.50,ripster.local
|
||||
VITE_HMR_PROTOCOL=ws
|
||||
VITE_HMR_HOST=192.168.1.50
|
||||
VITE_HMR_CLIENT_PORT=5173
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Priorität
|
||||
|
||||
1. Prozess-Umgebungsvariablen
|
||||
2. `.env`
|
||||
3. Code-Defaults
|
||||
@@ -0,0 +1,29 @@
|
||||
# Anhang: Konfiguration
|
||||
|
||||
Dieser Abschnitt ist die technische Referenz zu allen Konfigurationsarten in Ripster.
|
||||
|
||||
## Inhalte
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- :material-tune: **Einstellungsreferenz**
|
||||
|
||||
---
|
||||
|
||||
Vollständige Liste aller UI-Settings (Typ, Default, Hinweise).
|
||||
|
||||
[:octicons-arrow-right-24: Einstellungsreferenz](settings-reference.md)
|
||||
|
||||
- :material-variable: **Umgebungsvariablen**
|
||||
|
||||
---
|
||||
|
||||
`backend/.env` und `frontend/.env` inkl. Prioritäten.
|
||||
|
||||
[:octicons-arrow-right-24: Umgebungsvariablen](environment.md)
|
||||
|
||||
</div>
|
||||
|
||||
## Zurück zum Handbuch
|
||||
|
||||
- [Benutzerhandbuch Überblick](../getting-started/index.md)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,85 @@
|
||||
# Entwicklungsumgebung
|
||||
|
||||
---
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
- Node.js >= 20.19.0
|
||||
- externe Tools installiert (`makemkvcon`, `HandBrakeCLI`, `mediainfo`)
|
||||
|
||||
---
|
||||
|
||||
## Schnellstart
|
||||
|
||||
```bash
|
||||
./start.sh
|
||||
```
|
||||
|
||||
Startet:
|
||||
|
||||
- Backend (`http://localhost:3001`, mit nodemon)
|
||||
- Frontend (`http://localhost:5173`, mit Vite HMR)
|
||||
|
||||
Stoppen: `Ctrl+C`.
|
||||
|
||||
---
|
||||
|
||||
## Manuell
|
||||
|
||||
### Backend
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Frontend
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Vite-Proxy (Dev)
|
||||
|
||||
`frontend/vite.config.js` proxied standardmäßig:
|
||||
|
||||
- `/api` -> `http://127.0.0.1:3001`
|
||||
- `/ws` -> `ws://127.0.0.1:3001`
|
||||
|
||||
---
|
||||
|
||||
## Remote-Dev (optional)
|
||||
|
||||
Beispiel `frontend/.env.local`:
|
||||
|
||||
```env
|
||||
VITE_API_BASE=http://192.168.1.100:3001/api
|
||||
VITE_WS_URL=ws://192.168.1.100:3001/ws
|
||||
VITE_PUBLIC_ORIGIN=http://192.168.1.100:5173
|
||||
VITE_ALLOWED_HOSTS=192.168.1.100,ripster.local
|
||||
VITE_HMR_PROTOCOL=ws
|
||||
VITE_HMR_HOST=192.168.1.100
|
||||
VITE_HMR_CLIENT_PORT=5173
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Nützliche Kommandos
|
||||
|
||||
```bash
|
||||
# Root dev (backend + frontend)
|
||||
npm run dev
|
||||
|
||||
# einzeln
|
||||
npm run dev:backend
|
||||
npm run dev:frontend
|
||||
|
||||
# Frontend Build
|
||||
npm run build:frontend
|
||||
```
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Anhang: Deployment
|
||||
|
||||
Technische Betriebsdokumentation für Entwicklung und Produktion.
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- :material-laptop: **Entwicklungsumgebung**
|
||||
|
||||
---
|
||||
|
||||
Lokale Entwicklung mit Hot-Reload.
|
||||
|
||||
[:octicons-arrow-right-24: Entwicklung](development.md)
|
||||
|
||||
- :material-server: **Produktion**
|
||||
|
||||
---
|
||||
|
||||
Installation und Betrieb auf Servern.
|
||||
|
||||
[:octicons-arrow-right-24: Produktion](production.md)
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,233 @@
|
||||
# Produktions-Deployment
|
||||
|
||||
---
|
||||
|
||||
## Automatische Installation (empfohlen)
|
||||
|
||||
Das mitgelieferte `install.sh` richtet Ripster vollautomatisch ein – inklusive Node.js, MakeMKV, HandBrake, nginx und systemd-Dienst.
|
||||
|
||||
**Unterstützte Systeme laut Script:** Debian, Ubuntu, Linux Mint, Pop!_OS
|
||||
**Voraussetzung:** root-Rechte, Internetzugang
|
||||
|
||||
### Schnellstart via curl
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/Mboehmlaender/ripster/main/install.sh | sudo bash
|
||||
```
|
||||
|
||||
Oder mit wget:
|
||||
|
||||
```bash
|
||||
wget -qO- https://raw.githubusercontent.com/Mboehmlaender/ripster/main/install.sh | sudo bash
|
||||
```
|
||||
|
||||
!!! warning "Optionen nur via Datei"
|
||||
Beim Pipen von curl/wget können keine Argumente übergeben werden. Für benutzerdefinierte Optionen zuerst herunterladen und dann mit `sudo bash install.sh [Optionen]` ausführen.
|
||||
|
||||
### Optionen
|
||||
|
||||
| Option | Standard | Beschreibung |
|
||||
|--------|----------|--------------|
|
||||
| `--branch <branch>` | `dev` | Git-Branch für die Installation |
|
||||
| `--dir <pfad>` | `/opt/ripster` | Installationsverzeichnis |
|
||||
| `--user <benutzer>` | `ripster` | Systembenutzer für den Dienst |
|
||||
| `--port <port>` | `3001` | Backend-Port |
|
||||
| `--host <hostname>` | Auto (Maschinen-IP) | Hostname/IP für die Weboberfläche |
|
||||
| `--no-makemkv` | – | MakeMKV-Installation überspringen |
|
||||
| `--no-handbrake` | – | HandBrake-Installation überspringen |
|
||||
| `--no-nginx` | – | nginx-Einrichtung überspringen |
|
||||
| `--reinstall` | – | Bestehende Installation aktualisieren (Daten bleiben erhalten) |
|
||||
| `-h`, `--help` | – | Hilfe anzeigen |
|
||||
|
||||
### Beispiele
|
||||
|
||||
```bash
|
||||
# Standard-Installation
|
||||
sudo bash install.sh
|
||||
|
||||
# Anderen Branch und Port verwenden
|
||||
sudo bash install.sh --branch dev --port 8080
|
||||
|
||||
# Ohne MakeMKV (bereits installiert)
|
||||
sudo bash install.sh --no-makemkv
|
||||
|
||||
# Bestehende Installation aktualisieren
|
||||
sudo bash install.sh --reinstall
|
||||
|
||||
# Ohne nginx (eigener Reverse-Proxy)
|
||||
sudo bash install.sh --no-nginx --host mein-server.local
|
||||
```
|
||||
|
||||
### Was das Skript erledigt
|
||||
|
||||
1. **Systemprüfung** – OS-Erkennung und Root-Check
|
||||
2. **Systempakete** – `curl`, `wget`, `git`, `mediainfo`, `udev` u. a.
|
||||
3. **Node.js 20** – via NodeSource, falls noch nicht installiert
|
||||
4. **MakeMKV** – aktuelle Version wird aus dem offiziellen Forum ermittelt und aus dem Quellcode kompiliert (kann mit `--no-makemkv` übersprungen werden)
|
||||
5. **HandBrake** – interaktive Auswahl:
|
||||
- **Option 1**: Standard (`apt install handbrake-cli`)
|
||||
- **Option 2**: Gebündelte GPU-Version mit NVDEC aus `bin/HandBrakeCLI`
|
||||
6. **Systembenutzer** `ripster` – ohne Login-Shell und ohne Home-Verzeichnis; Gruppen werden (falls vorhanden) ergänzt: `cdrom`, `optical`, `disk`, `video`, `render`
|
||||
7. **Repository** – klont Branch nach `--dir` (bei `--reinstall`: sichert `backend/data`, aktualisiert Repo, stellt Daten wieder her)
|
||||
8. **Verzeichnisse** – stellt u. a. sicher: `backend/data`, `backend/logs`, `backend/data/output/raw`, `backend/data/output/movies`, `backend/data/logs`
|
||||
9. **npm-Abhängigkeiten** – Root, Backend (nur production), Frontend
|
||||
10. **Frontend-Build** – `npm run build` mit relativen API-URLs (nginx-kompatibel)
|
||||
11. **Backend `.env`** – wird automatisch generiert (bei `--reinstall` bleibt bestehende `.env` erhalten)
|
||||
12. **Berechtigungen** – zunächst `ripster:ripster` auf Installationsverzeichnis; bei sudo-Aufruf werden Output-/Log-Ordner auf `<aufrufender user>:ripster` mit `775` gesetzt; `.env` wird auf `600` gesetzt
|
||||
13. **MakeMKV User-Ordner** – erstellt bei sudo-Aufruf `~/.MakeMKV` für den aufrufenden Benutzer
|
||||
14. **systemd-Dienst** – `ripster-backend.service` erstellt, aktiviert und gestartet
|
||||
15. **nginx** – konfiguriert als Reverse-Proxy für Frontend, `/api/` und `/ws` (kann mit `--no-nginx` übersprungen werden)
|
||||
|
||||
### Nach der Installation
|
||||
|
||||
```bash
|
||||
# Status prüfen
|
||||
sudo systemctl status ripster-backend
|
||||
|
||||
# Logs verfolgen
|
||||
sudo journalctl -u ripster-backend -f
|
||||
|
||||
# Neustart
|
||||
sudo systemctl restart ripster-backend
|
||||
|
||||
# Aktualisieren
|
||||
sudo bash /opt/ripster/install.sh --reinstall
|
||||
```
|
||||
|
||||
**Zugriff:** `http://<Maschinen-IP>` (oder der mit `--host` angegebene Hostname)
|
||||
|
||||
### HandBrake-Modus (GPU/NVDEC)
|
||||
|
||||
Bei nicht-interaktiver Ausführung (Pipe von curl) wird automatisch die Standard-Version gewählt. Für die GPU-Version zuerst herunterladen:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/Mboehmlaender/ripster/main/install.sh -o install.sh
|
||||
sudo bash install.sh
|
||||
# → Interaktive Auswahl: Option 2 für NVDEC
|
||||
```
|
||||
|
||||
Das gebündelte Binary liegt unter `bin/HandBrakeCLI` und wird nach `/usr/local/bin/HandBrakeCLI` kopiert.
|
||||
|
||||
---
|
||||
|
||||
## Manuelle Installation
|
||||
|
||||
Die folgenden Abschnitte beschreiben die einzelnen Schritte für manuelle oder angepasste Setups.
|
||||
|
||||
### Empfohlene Architektur
|
||||
|
||||
```text
|
||||
Client
|
||||
-> nginx (Reverse Proxy + statisches Frontend)
|
||||
-> Backend API/WebSocket (Node.js, Port 3001)
|
||||
```
|
||||
|
||||
Wichtig: Das Backend serviert im aktuellen Stand keine `frontend/dist`-Dateien automatisch.
|
||||
|
||||
---
|
||||
|
||||
## 1) Frontend builden
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
Artefakte liegen in `frontend/dist/`.
|
||||
|
||||
---
|
||||
|
||||
## 2) Backend als systemd-Service
|
||||
|
||||
Beispiel `/etc/systemd/system/ripster-backend.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Ripster Backend
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=ripster
|
||||
WorkingDirectory=/opt/ripster/backend
|
||||
ExecStart=/usr/bin/env node src/index.js
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
Environment=NODE_ENV=production
|
||||
Environment=PORT=3001
|
||||
Environment=LOG_LEVEL=info
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Aktivieren:
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now ripster-backend
|
||||
sudo systemctl status ripster-backend
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3) nginx konfigurieren
|
||||
|
||||
Beispiel `/etc/nginx/sites-available/ripster`:
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name ripster.local;
|
||||
client_max_body_size 8G;
|
||||
|
||||
root /opt/ripster/frontend/dist;
|
||||
index index.html;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://127.0.0.1:3001;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
}
|
||||
|
||||
location /ws {
|
||||
proxy_pass http://127.0.0.1:3001;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Aktivieren:
|
||||
|
||||
```bash
|
||||
sudo ln -s /etc/nginx/sites-available/ripster /etc/nginx/sites-enabled/
|
||||
sudo nginx -t
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
Hinweis: Fuer groessere Uploads wie `.aax`-Audiobooks muss `client_max_body_size` ausreichend hoch gesetzt sein. Im mitgelieferten Beispiel sind `8G` hinterlegt.
|
||||
|
||||
---
|
||||
|
||||
## Datenbank-Backup
|
||||
|
||||
```bash
|
||||
sqlite3 /opt/ripster/backend/data/ripster.db \
|
||||
".backup '/var/backups/ripster-$(date +%Y%m%d).db'"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sicherheit
|
||||
|
||||
- Ripster hat keine eingebaute Authentifizierung.
|
||||
- Für externen Zugriff mindestens Basic Auth + TLS + Netzwerksegmentierung/VPN einsetzen.
|
||||
- Secrets nicht ins Repo committen (`.env`, Settings-Felder).
|
||||
@@ -0,0 +1,151 @@
|
||||
# Ersteinrichtung
|
||||
|
||||
Diese Seite ist die Betriebs-Checkliste vor dem ersten produktiven Lauf.
|
||||
|
||||
## Ziel der Ersteinrichtung
|
||||
|
||||
Vor dem ersten Job sollten fünf Bereiche sauber gesetzt sein:
|
||||
|
||||
1. Pfade und Templates
|
||||
2. Laufwerk und Disc-Erkennung
|
||||
3. Metadatenzugang über TMDb
|
||||
4. Encode-Standards und Queue-Regeln
|
||||
5. optionale Automatisierung und Benachrichtigungen
|
||||
|
||||
## Empfohlene Reihenfolge
|
||||
|
||||
### 1. Basis in `Settings -> Konfiguration`
|
||||
|
||||
Prüfe zuerst diese Kernfelder:
|
||||
|
||||
- RAW- und Zielordner für Blu-ray, DVD, CD, Audiobooks und Converter
|
||||
- `Log Ordner`
|
||||
- `TMDb Read Access Token`
|
||||
- `MakeMKV Kommando`, `HandBrake Kommando`, `Mediainfo Kommando`
|
||||
- `FFmpeg Kommando`, `FFprobe Kommando`, `cdparanoia Kommando`, `mkvmerge Kommando`, falls du die jeweiligen Workflows nutzt
|
||||
|
||||
Danach speichern.
|
||||
|
||||
### 2. Pfade und Templates bewusst festlegen
|
||||
|
||||
Wichtig für den Alltag:
|
||||
|
||||
- Film-Workflows nutzen die RAW- und Film-Ausgabeordner sowie die Film-Output-Templates
|
||||
- Serien-Workflows nutzen zusätzlich die Serien-RAW-Ordner, die Serien-Zielordner und die Episode-/Multi-Episode-Templates
|
||||
- Audiobooks nutzen `Audiobook RAW-Ordner`, `Audiobook Output-Ordner`, `Audiobook RAW Template`, `Output Template (Audiobook)` und `Kapitel Template (Audiobook)`
|
||||
- Converter nutzt `Converter Raw-Ordner`, `Converter Ausgabe (Video)`, `Converter Ausgabe (Audio)` sowie `Output-Template (Video)` und `Output-Template (Audio)`
|
||||
- Downloads nutzen `Download ZIP-Ordner`
|
||||
|
||||
Wenn du auf NAS, USB oder mit anderen Benutzern/Gruppen schreiben willst, prüfe auch die jeweils zugehörigen `Eigentümer ...`-Felder.
|
||||
|
||||
### 3. Laufwerk und automatische Erkennung prüfen
|
||||
|
||||
Relevant:
|
||||
|
||||
- `Laufwerksmodus`
|
||||
- `Explizite Laufwerke`, falls du nicht mit Auto-Discovery arbeiten willst
|
||||
- `Automatische Disk-Erkennung`
|
||||
- `Polling Intervall (ms)` im Expertenmodus
|
||||
- `Laufwerk nach Rip auswerfen`
|
||||
|
||||
Empfehlung:
|
||||
|
||||
- Einzelnes Standardlaufwerk: `auto`
|
||||
- mehrere stabile Laufwerke oder ungewöhnliche Device-Mappings: `Explizite Laufwerke`
|
||||
|
||||
### 4. TMDb und Metadatenverhalten festlegen
|
||||
|
||||
Relevant:
|
||||
|
||||
- `TMDb Read Access Token`
|
||||
- `Film-Sprache`
|
||||
- `Fallback Sprache`
|
||||
- `Coverart-Nachladen aktiv`
|
||||
- `Coverart-Prüfintervall (Stunden)`
|
||||
- `NFO nach Encode erzeugen`
|
||||
|
||||
Diese Einstellungen wirken direkt in Metadatensuche, Serienzuordnung, Nachpflege von Covern und im finalen Output.
|
||||
|
||||
### 5. Encode- und Review-Standards festlegen
|
||||
|
||||
Für Video-Workflows besonders wichtig:
|
||||
|
||||
- `Minimale Titellänge (Minuten)`
|
||||
- `TMDb Runtime-Abzug für Playlistfilter (%)`
|
||||
- `HandBrake Preset` und `HandBrake Extra Args` je Medium
|
||||
- `Review Audio-Sprachen (...)`
|
||||
- `Review UT-Sprachen (...)`
|
||||
- `Ausgabeformat`
|
||||
|
||||
Praxis:
|
||||
|
||||
- `Minimale Titellänge` filtert Bonusmaterial früh weg
|
||||
- `TMDb Runtime-Abzug ...` lockert bei problematischen Blu-rays die Laufzeitprüfung der Playlist-Kandidaten
|
||||
- Review-Sprachen bestimmen, welche Audio-/Untertitelspuren in der Review schon vorausgewählt sind
|
||||
|
||||
### 6. Queue-Verhalten definieren
|
||||
|
||||
Stelle diese vier Felder bewusst ein:
|
||||
|
||||
- `Parallele Jobs`
|
||||
- `Max. parallele Audio CD Jobs`
|
||||
- `Max. Encodes gesamt (medienunabhängig)`
|
||||
- `Audio CDs: Queue-Reihenfolge überspringen`
|
||||
|
||||
Damit steuerst du, wie aggressiv Ripster mehrere Jobs gleichzeitig startet.
|
||||
|
||||
### 7. Optional: User-Presets und Standard-Zuordnungen
|
||||
|
||||
Unter `Settings -> Encode-Presets` kannst du:
|
||||
|
||||
- eigene HandBrake-User-Presets anlegen
|
||||
- Standard-Zuordnungen für `Blu-ray Film`, `Blu-ray Serie`, `DVD Film`, `DVD Serie` setzen
|
||||
|
||||
Diese Defaults wirken später in der Review automatisch vorbefüllend.
|
||||
|
||||
### 8. Optional: Benachrichtigungen
|
||||
|
||||
Prüfe:
|
||||
|
||||
- `PushOver aktiviert`
|
||||
- Token/User/optional Device
|
||||
- Event-Toggles wie `Bei manueller Auswahl senden`, `Bei Rip-Start senden`, `Bei Erfolg senden`
|
||||
|
||||
Danach in `Settings` den Button `PushOver Test` ausführen.
|
||||
|
||||
### 9. Optional: Automatisierung
|
||||
|
||||
Erst wenn die Grundkonfiguration stabil ist:
|
||||
|
||||
1. Skripte anlegen und testen
|
||||
2. Skriptketten aufbauen
|
||||
3. Cronjobs aktivieren
|
||||
|
||||
## Funktionsprüfung
|
||||
|
||||
Ein sinnvoller Kurztest:
|
||||
|
||||
1. Disc in `Ripper` erkennen lassen
|
||||
2. `Analyse starten`
|
||||
3. TMDb-Metadaten übernehmen
|
||||
4. ggf. Playlist-/RAW-Entscheidung durchlaufen
|
||||
5. bis `Bereit zum Encodieren` kommen
|
||||
6. Encode starten
|
||||
7. Ergebnis in `Historie` prüfen
|
||||
|
||||
## Typische Konfigurationsfehler
|
||||
|
||||
| Symptom | Häufige Ursache |
|
||||
|---|---|
|
||||
| Disc wird nicht erkannt | Laufwerksmodus oder Auto-Erkennung passt nicht |
|
||||
| Playlist-Auswahl wirkt unplausibel | `Minimale Titellänge` oder `TMDb Runtime-Abzug ...` ist zu streng/zu locker |
|
||||
| falsche Spuren sind in der Review vorausgewählt | Review-Sprachfilter oder HandBrake-Args greifen unerwartet |
|
||||
| Ausgabe landet am falschen Ort | Profilpfade oder Templates greifen über Fallback |
|
||||
| Queue verhält sich unerwartet | `Parallele Jobs`, CD-Limit und Gesamtlimit widersprechen sich |
|
||||
|
||||
## Weiter
|
||||
|
||||
- [Erster Lauf](quickstart.md)
|
||||
- [GUI-Seiten](../gui/index.md)
|
||||
- [Workflows aus Nutzersicht](../workflows/index.md)
|
||||
- [Alle Einstellungen](../configuration/settings-reference.md)
|
||||
@@ -0,0 +1,33 @@
|
||||
# Benutzerhandbuch Überblick
|
||||
|
||||
Dieses Kapitel ist für den **Betrieb von Ripster im Alltag** geschrieben.
|
||||
|
||||
## Zielgruppe
|
||||
|
||||
- Anwender, die Discs verarbeiten wollen
|
||||
- Betreiber, die den täglichen Ablauf stabil fahren möchten
|
||||
- Power-User, die Queue/Skripte/Cron im UI steuern möchten
|
||||
|
||||
## Kapitelstruktur
|
||||
|
||||
| Kapitel | Zweck |
|
||||
|---|---|
|
||||
| [Voraussetzungen](prerequisites.md) | Produktions- vs. Dev-Voraussetzungen klar trennen |
|
||||
| [Installation](installation.md) | Ripster aufsetzen und starten |
|
||||
| [Ersteinrichtung](configuration.md) | Pfade, Tools und Metadaten korrekt setzen |
|
||||
| [Erster Lauf](quickstart.md) | Ein kompletter Job von Disc bis Datei |
|
||||
| [GUI-Seiten](../gui/index.md) | Alle Ansichten und Aktionen im Detail |
|
||||
| [Workflows](../workflows/index.md) | Typische Abläufe und Entscheidungen aus User-Sicht |
|
||||
|
||||
## Wenn du neu startest
|
||||
|
||||
1. [Voraussetzungen](prerequisites.md)
|
||||
2. [Installation](installation.md)
|
||||
3. [Ersteinrichtung](configuration.md)
|
||||
4. [Erster Lauf](quickstart.md)
|
||||
|
||||
## Wenn Ripster bereits läuft
|
||||
|
||||
1. [GUI-Seiten](../gui/index.md)
|
||||
2. [Workflows](../workflows/index.md)
|
||||
3. Bei Detailfragen: [Technischer Anhang](../appendix/index.md)
|
||||
@@ -0,0 +1,119 @@
|
||||
# Installation
|
||||
|
||||
Die empfohlene Installation startet immer über `setup.sh`. `setup.sh` lädt das passende `install.sh` aus dem gewünschten Branch und übergibt alle weiteren Parameter unverändert an den eigentlichen Installer.
|
||||
|
||||
Wichtig:
|
||||
|
||||
- Standard-Einstieg: `setup.sh`
|
||||
- kein `curl | bash`
|
||||
- du musst die Tools nicht manuell vorinstallieren, sofern du sie nicht bewusst mit `--no-*` auslässt
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
- unterstütztes Linux-System
|
||||
- Root-Rechte oder `sudo`
|
||||
- Internetzugang während der Installation
|
||||
|
||||
Der Installer erkennt aktuell:
|
||||
|
||||
- Debian
|
||||
- Ubuntu
|
||||
- Linux Mint
|
||||
- Pop!_OS
|
||||
|
||||
## Standardinstallation
|
||||
|
||||
```bash
|
||||
wget -qO setup.sh https://raw.githubusercontent.com/Mboehmlaender/ripster/main/setup.sh
|
||||
bash setup.sh
|
||||
```
|
||||
|
||||
Ohne `--branch` fragt `setup.sh` interaktiv nach dem gewünschten Branch.
|
||||
|
||||
Die typischen Branches sind:
|
||||
|
||||
- `main`: stabiles Release
|
||||
- `dev`: aktueller Entwicklungsstand
|
||||
|
||||
## Installation mit Branch oder Optionen
|
||||
|
||||
Beispiele:
|
||||
|
||||
```bash
|
||||
bash setup.sh --branch main
|
||||
bash setup.sh --branch dev
|
||||
bash setup.sh --branch dev --dir /opt/ripster --user ripster --port 3001 --host 192.168.1.10
|
||||
```
|
||||
|
||||
`setup.sh` wertet selbst nur `--branch` aus. Alles andere übernimmt `install.sh`.
|
||||
|
||||
## Wichtige Optionen von `install.sh`
|
||||
|
||||
| Option | Default | Zweck |
|
||||
|---|---|---|
|
||||
| `--branch <branch>` | `dev` | installiert genau diesen Git-Branch |
|
||||
| `--dir <pfad>` | `/opt/ripster` | Installationsverzeichnis |
|
||||
| `--user <benutzer>` | `ripster` | Systembenutzer für den Dienst |
|
||||
| `--port <port>` | `3001` | Backend-Port |
|
||||
| `--host <hostname|ip>` | automatisch ermittelte Host-IP | Hostname/IP für Webzugriff und CORS |
|
||||
| `--no-makemkv` | aus | MakeMKV nicht installieren |
|
||||
| `--no-handbrake` | aus | HandBrake nicht installieren |
|
||||
| `--no-nginx` | aus | nginx-Setup überspringen |
|
||||
| `--no-system-deps` | aus | Systemabhängigkeiten nicht nachinstallieren |
|
||||
| `--reinstall` | aus | bestehende Installation aktualisieren |
|
||||
|
||||
## Was der Installer einrichtet
|
||||
|
||||
Typischer Ablauf:
|
||||
|
||||
1. Betriebssystem, Root-Rechte und Host prüfen
|
||||
2. Systemabhängigkeiten installieren
|
||||
3. Node.js 20 sicherstellen
|
||||
4. optional MakeMKV installieren
|
||||
5. optional HandBrakeCLI installieren
|
||||
6. optional nginx konfigurieren
|
||||
7. Repository nach `--dir` klonen oder aktualisieren
|
||||
8. Backend-/Frontend-Abhängigkeiten installieren
|
||||
9. Frontend bauen
|
||||
10. `backend/.env` und Laufzeitverzeichnisse vorbereiten
|
||||
11. `ripster-backend.service` anlegen und starten
|
||||
|
||||
## Dienst prüfen
|
||||
|
||||
```bash
|
||||
sudo systemctl status ripster-backend
|
||||
```
|
||||
|
||||
Typische Aufrufe im Betrieb:
|
||||
|
||||
```bash
|
||||
sudo journalctl -u ripster-backend -f
|
||||
sudo systemctl restart ripster-backend
|
||||
```
|
||||
|
||||
## Update einer bestehenden Installation
|
||||
|
||||
Standard:
|
||||
|
||||
```bash
|
||||
sudo bash /opt/ripster/install.sh --reinstall
|
||||
```
|
||||
|
||||
Wenn die Installation mit abweichenden Kernparametern eingerichtet wurde, dieselben Parameter wieder mitgeben:
|
||||
|
||||
```bash
|
||||
sudo bash /opt/ripster/install.sh --reinstall --dir /opt/ripster --user ripster --port 3001 --host 192.168.1.10
|
||||
```
|
||||
|
||||
Alternativ kannst du auch erneut über `setup.sh` gehen:
|
||||
|
||||
```bash
|
||||
sudo bash /opt/ripster/setup.sh --reinstall
|
||||
```
|
||||
|
||||
`--reinstall` aktualisiert die Installation, behält aber die persistenten Daten der bestehenden Instanz.
|
||||
|
||||
## Danach weiter
|
||||
|
||||
1. [Ersteinrichtung](configuration.md)
|
||||
2. [Erster Lauf](quickstart.md)
|
||||
@@ -0,0 +1,58 @@
|
||||
# Voraussetzungen
|
||||
|
||||
Die Voraussetzungen hängen davon ab, ob du Ripster produktiv installieren oder lokal entwickeln willst.
|
||||
|
||||
## Produktionsbetrieb mit `setup.sh`
|
||||
|
||||
Für den normalen Betrieb brauchst du nur die Basisvoraussetzungen. Die eigentlichen Tools werden vom Installer eingerichtet, sofern du sie nicht bewusst mit `--no-*` überspringst.
|
||||
|
||||
### Pflicht
|
||||
|
||||
- unterstütztes Linux-System
|
||||
- Root-Rechte oder `sudo`
|
||||
- Internetzugang während der Installation
|
||||
- optisches Laufwerk, wenn du Disc-Workflows nutzen willst
|
||||
|
||||
Der Installer unterstützt aktuell:
|
||||
|
||||
- Debian
|
||||
- Ubuntu
|
||||
- Linux Mint
|
||||
- Pop!_OS
|
||||
|
||||
Standard-Einstieg:
|
||||
|
||||
```bash
|
||||
wget -qO setup.sh https://raw.githubusercontent.com/Mboehmlaender/ripster/main/setup.sh
|
||||
bash setup.sh
|
||||
```
|
||||
|
||||
### Laufwerk kurz prüfen
|
||||
|
||||
```bash
|
||||
ls /dev/sr*
|
||||
lsblk | grep rom
|
||||
```
|
||||
|
||||
### Optional vorab
|
||||
|
||||
- TMDb Read Access Token für Film-/Serien-Metadaten
|
||||
- PushOver-Zugangsdaten für Benachrichtigungen
|
||||
|
||||
Beides kann auch erst nach der Installation in `Settings` gesetzt werden.
|
||||
|
||||
## Entwicklungsmodus
|
||||
|
||||
Wenn du lokal entwickelst (`./start.sh`, `npm run dev`), gelten zusätzliche Voraussetzungen:
|
||||
|
||||
- Node.js `>= 20.19.0`
|
||||
- `makemkvcon`, `HandBrakeCLI`, `mediainfo` im `PATH`
|
||||
|
||||
Details: [Entwicklungsumgebung](../deployment/development.md)
|
||||
|
||||
## Abschluss-Checkliste
|
||||
|
||||
- [ ] Linux + Root/Sudo + Internet vorhanden
|
||||
- [ ] optisches Laufwerk vorhanden, falls Disc-Ripping genutzt werden soll
|
||||
- [ ] TMDb/PushOver-Zugangsdaten liegen bereit, falls diese Funktionen sofort genutzt werden sollen
|
||||
- [ ] im Dev-Modus zusätzlich Node.js und CLI-Tools lokal verfügbar
|
||||
@@ -0,0 +1,151 @@
|
||||
# Erster Lauf
|
||||
|
||||
Dieser Ablauf führt einen typischen Disc-Job von Erkennung bis fertiger Datei durch.
|
||||
|
||||
## 1. Disc erkennen
|
||||
|
||||
1. `Ripper` öffnen
|
||||
2. Disc einlegen
|
||||
3. auf `Medium erkannt` warten
|
||||
|
||||
Prüfen:
|
||||
|
||||
- `Disk-Information` zeigt Device, Label und Laufwerksstatus
|
||||
- falls nicht: `Laufwerk neu lesen`
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Laufwerksmodus`
|
||||
- `Automatische Disk-Erkennung`
|
||||
- `Polling Intervall (ms)`
|
||||
|
||||
## 2. Analyse starten
|
||||
|
||||
Aktion:
|
||||
|
||||
- `Analyse starten`
|
||||
|
||||
Erwartung:
|
||||
|
||||
- Status `Analyse`
|
||||
- danach der Metadaten-Dialog
|
||||
|
||||
Relevantes Setting:
|
||||
|
||||
- `Minimale Titellänge (Minuten)` beeinflusst bereits, welche Titel/Playlists Ripster später als relevant betrachtet
|
||||
|
||||
## 3. Metadaten in TMDb bestätigen
|
||||
|
||||
Im Dialog:
|
||||
|
||||
1. Treffer suchen oder filtern
|
||||
2. Film oder Serie auswählen
|
||||
3. bei Serien zusätzlich `Disc-Nummer` setzen
|
||||
4. `Auswahl übernehmen`
|
||||
|
||||
Mögliche Abzweigungen:
|
||||
|
||||
- Duplikatfilm: `Übernahme erzwingen` oder `Multipart movie`
|
||||
- vorhandenes RAW: Entscheidungsdialog `weiterverwenden` oder `neu rippen`
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `TMDb Read Access Token`
|
||||
- `Film-Sprache`
|
||||
- `Fallback Sprache`
|
||||
|
||||
## 4. RAW- und Playlist-Entscheidungen
|
||||
|
||||
Je nach Disc-Situation geht es jetzt unterschiedlich weiter.
|
||||
|
||||
### Normalfall
|
||||
|
||||
`Startbereit` -> `Rippen` -> `Mediainfo-Prüfung`
|
||||
|
||||
### Vorhandenes RAW
|
||||
|
||||
Kein neuer Rip, sondern erst eine Entscheidung:
|
||||
|
||||
- vorhandenes RAW weiterverwenden
|
||||
- RAW löschen und Rip neu starten
|
||||
- bei passenden Film-Konstellationen optional Multipart mit Orphan-RAW
|
||||
|
||||
### Playlist- oder Titelauswahl erforderlich
|
||||
|
||||
Bei bestimmten Blu-ray-/DVD-Fällen erscheint `Warte auf Auswahl`.
|
||||
|
||||
Dann bestätigst du:
|
||||
|
||||
- eine Playlist
|
||||
- oder einen/mehrere HandBrake-Titel
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Minimale Titellänge (Minuten)`
|
||||
- `TMDb Runtime-Abzug für Playlistfilter (%)`
|
||||
|
||||
## 5. Encode-Review abschließen
|
||||
|
||||
Bei `Bereit zum Encodieren` prüfst du:
|
||||
|
||||
- Titelwahl
|
||||
- Audio-Spuren
|
||||
- Untertitel
|
||||
- User-Preset oder HandBrake-Preset
|
||||
- Pre-/Post-Encode-Skripte und Ketten
|
||||
|
||||
Dann:
|
||||
|
||||
- `Encoding starten`
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `HandBrake Preset` und `HandBrake Extra Args` je Medium
|
||||
- `Review Audio-Sprachen (...)`
|
||||
- `Review UT-Sprachen (...)`
|
||||
- `Ausgabeformat`
|
||||
- Standard-Zuordnungen unter `Settings -> Encode-Presets`
|
||||
|
||||
## 6. Encoding überwachen
|
||||
|
||||
Während `Encodieren`:
|
||||
|
||||
- Fortschritt/ETA im Ripper
|
||||
- Queue-Status beobachten
|
||||
- bei Bedarf `Hardware`-Ansicht öffnen
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Parallele Jobs`
|
||||
- `Max. parallele Audio CD Jobs`
|
||||
- `Max. Encodes gesamt (medienunabhängig)`
|
||||
- `Hardware Monitoring aktiviert`
|
||||
- `Hardware Monitoring Intervall (ms)`
|
||||
|
||||
## 7. Ergebnis verifizieren
|
||||
|
||||
Nach `Fertig`:
|
||||
|
||||
1. `Historie` öffnen
|
||||
2. Jobdetail prüfen
|
||||
3. Output-Pfad und Log kontrollieren
|
||||
|
||||
Kontrollpunkte:
|
||||
|
||||
- finale Datei liegt am erwarteten Template-Pfad
|
||||
- RAW-Ordner ist finalisiert
|
||||
- optional `.nfo` wurde erzeugt, falls aktiviert
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- Film-Output-Templates oder Serien-Templates
|
||||
- `Serien-Ordner (Blu-ray)` und `Serien-Ordner (DVD)` plus die Episode-/Multi-Episode-Templates
|
||||
- `NFO nach Encode erzeugen`
|
||||
|
||||
## 8. Typische Folgeaktionen
|
||||
|
||||
- falsche TMDb-Zuordnung: `TMDb neu zuweisen`
|
||||
- andere Trackauswahl: `Review neu starten`
|
||||
- erneuter Encode aus RAW: `RAW neu encodieren`
|
||||
- gleicher Plan erneut: `Encode neu starten`
|
||||
- Rip erneut versuchen: `Retry Rippen`
|
||||
@@ -0,0 +1,108 @@
|
||||
# Audiobooks
|
||||
|
||||
Die Seite `Audiobooks` ist der spezialisierte Workflow für Audible-`*.aax`-Dateien.
|
||||
|
||||
## Seitenstruktur
|
||||
|
||||
Die Oberfläche besteht aus zwei Hauptbereichen:
|
||||
|
||||
1. `Audiobooks Upload`
|
||||
2. `Audiobook Jobs`
|
||||
|
||||
## 1. Audiobooks Upload
|
||||
|
||||
Der Upload akzeptiert ausschließlich `.aax`.
|
||||
|
||||
### Bedienung
|
||||
|
||||
- Datei auswählen oder per Drag-and-Drop ablegen
|
||||
- Upload starten
|
||||
- Auswahl entfernen oder laufenden Upload abbrechen
|
||||
|
||||
Während des Uploads zeigt die UI:
|
||||
|
||||
- Prozentfortschritt
|
||||
- übertragene und gesamte Bytes
|
||||
- Statusmeldung
|
||||
|
||||
### Ablauf nach erfolgreichem Upload
|
||||
|
||||
- die AAX-Datei wird geprüft
|
||||
- Ripster versucht Metadata, Kapitel und Activation-Bytes-Kontext aufzubauen
|
||||
- ein Audiobook-Job wird angelegt
|
||||
- der Job startet direkt oder wird in die Queue eingereiht
|
||||
|
||||
## 2. Audiobook Jobs
|
||||
|
||||
Die Seite zeigt aktive Jobs. Abgeschlossene Jobs findest du in der `Historie`.
|
||||
|
||||
Ein Job kann eingeklappt oder ausgeklappt werden und zeigt:
|
||||
|
||||
- Titel, Autor, Sprecher, Jahr
|
||||
- Kapitelanzahl
|
||||
- Fortschritt und ETA
|
||||
- bei Split-Ausgabe den Kapitelstatus
|
||||
|
||||
## Konfigurierbare Job-Parameter
|
||||
|
||||
Im ausgeklappten Job kannst du setzen:
|
||||
|
||||
- Ausgabeformat `m4b`, `mp3` oder `flac`
|
||||
- formatspezifische Optionen
|
||||
- Kapitelnamen
|
||||
- Pre-Encode-Skripte und -Ketten
|
||||
- Post-Encode-Skripte und -Ketten
|
||||
|
||||
### Formatverhalten
|
||||
|
||||
- `m4b`: eine Datei mit Kapitelmarken
|
||||
- `mp3`: eine Datei pro Kapitel
|
||||
- `flac`: eine Datei pro Kapitel
|
||||
|
||||
Wenn du `mp3` oder `flac` wählst, zeigt die UI zusätzlich eine Kapitel-Status-Tabelle.
|
||||
|
||||
## Activation Bytes
|
||||
|
||||
Wenn Ripster für eine Datei keine Activation Bytes verwenden kann, wird im Workflow eine manuelle Eingabe nötig.
|
||||
|
||||
Wichtig:
|
||||
|
||||
- die Bytes werden lokal gecacht
|
||||
- derselbe AAX-Hash muss dann später nicht erneut manuell eingegeben werden
|
||||
- der Expertenblock in `Settings` zeigt bekannte Cache-Einträge an
|
||||
|
||||
## Relevante Settings
|
||||
|
||||
- `Audiobook RAW-Ordner`
|
||||
- `Audiobook Output-Ordner`
|
||||
- `Eigentümer Audiobook RAW-Ordner`
|
||||
- `Eigentümer Audiobook Output-Ordner`
|
||||
- `Audiobook RAW Template`
|
||||
- `Output Template (Audiobook)`
|
||||
- `Kapitel Template (Audiobook)`
|
||||
- `FFprobe Kommando`
|
||||
- `FFmpeg Kommando`
|
||||
|
||||
### So wirken die Settings im Alltag
|
||||
|
||||
- `Audiobook RAW Template` bestimmt den Namen des AAX-RAW-Ordners
|
||||
- `Output Template (Audiobook)` bestimmt die Einzeldatei für `m4b`
|
||||
- `Kapitel Template (Audiobook)` bestimmt Zielstruktur und Dateinamen für `mp3`/`flac`
|
||||
- `FFprobe Kommando` liest Kapitel und Metadaten
|
||||
- `FFmpeg Kommando` erzeugt die finalen Dateien
|
||||
|
||||
## Queue und Laufzeit
|
||||
|
||||
Audiobook-Jobs nutzen dieselbe globale Pipeline wie die anderen Bereiche.
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Parallele Jobs`
|
||||
- `Max. Encodes gesamt (medienunabhängig)`
|
||||
|
||||
## Typische Fehlerbilder
|
||||
|
||||
- Upload wird abgelehnt: Datei ist keine gültige `*.aax`
|
||||
- Analyse schlägt fehl: `ffprobe` ist nicht erreichbar
|
||||
- Encode schlägt fehl: `ffmpeg` ist nicht erreichbar
|
||||
- Ausgabe landet unerwartet: Templates oder Zielpfade passen nicht zur gewünschten Struktur
|
||||
@@ -0,0 +1,128 @@
|
||||
# Converter
|
||||
|
||||
Die Seite `Converter` verarbeitet vorhandene Dateien ohne Laufwerks-Rip. Sie ist für Video-, Audio- und ISO-Dateien gedacht, die bereits auf dem System liegen oder hochgeladen werden.
|
||||
|
||||
## Betriebsmodell
|
||||
|
||||
Der Converter arbeitet auf dem in `Settings` festgelegten `Converter Raw-Ordner`.
|
||||
|
||||
Dort landen:
|
||||
|
||||
- Uploads
|
||||
- neu angelegte Ordner
|
||||
- umbenannte oder verschobene Dateien
|
||||
- alle Dateien, aus denen später Converter-Jobs entstehen
|
||||
|
||||
Wichtig:
|
||||
|
||||
- Upload erzeugt nicht automatisch einen Job
|
||||
- die Joberstellung erfolgt bewusst aus der Explorer-Auswahl
|
||||
|
||||
## Datei-Explorer
|
||||
|
||||
Der Explorer zeigt den kompletten Baum unter `Converter Raw-Ordner`.
|
||||
|
||||
Aktionen:
|
||||
|
||||
| Aktion | Wirkung |
|
||||
|---|---|
|
||||
| `Upload` | schreibt neue Dateien in den Converter-RAW-Baum |
|
||||
| `Ordner erstellen` | legt Unterordner an |
|
||||
| `Umbenennen` | benennt Datei oder Ordner um |
|
||||
| `Verschieben` | verschiebt Einträge innerhalb des Raw-Baums |
|
||||
| `Löschen` | entfernt Datei oder Ordner dauerhaft |
|
||||
| `Scannen` | synchronisiert Dateisystem und Converter-Datenbank |
|
||||
|
||||
### Upload- und Scan-Regeln
|
||||
|
||||
- Dateiendungen müssen in `Erlaubte Datei-Endungen` enthalten sein
|
||||
- neue Dateien erscheinen sofort nach manuellem Scan
|
||||
- mit Polling auch automatisch
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Erlaubte Datei-Endungen`
|
||||
- `Auto-Scan (Polling)`
|
||||
- `Polling-Intervall (Sekunden)`
|
||||
|
||||
## Joberstellung aus Explorer-Auswahl
|
||||
|
||||
Es gibt zwei Audio-Strategien:
|
||||
|
||||
1. `Ein Job pro Datei`
|
||||
2. `Gemeinsamer Job (Audio)`
|
||||
|
||||
Verhalten:
|
||||
|
||||
- Video und ISO werden immer als Einzeljobs angelegt
|
||||
- Audio kann als gemeinsamer Album-/Ordner-Job erzeugt werden
|
||||
|
||||
Shared-Audio-Job:
|
||||
|
||||
- hält mehrere `inputPaths`
|
||||
- kann vor dem Start erweitert oder reduziert werden
|
||||
|
||||
## Job-Konfiguration
|
||||
|
||||
Vor dem Start je Job einstellbar:
|
||||
|
||||
- `converterMediaType`
|
||||
- `outputFormat`
|
||||
- Metadaten
|
||||
- Track-/Titelwahl bei Video/ISO
|
||||
- User-Preset und HandBrake-Preset bei Video
|
||||
- Pre-/Post-Encode-Skripte und Ketten
|
||||
|
||||
Spezifika:
|
||||
|
||||
- Video/ISO durchlaufen eine Review ähnlich zum Disc-Flow
|
||||
- Audio wird direkt über Format und Audio-Optionen konfiguriert
|
||||
|
||||
## Ausgabe-Pfade
|
||||
|
||||
### Video / ISO
|
||||
|
||||
- Zielordner: `Converter Ausgabe (Video)`
|
||||
- Dateiname: `Output-Template (Video)`
|
||||
- Endung: aus dem gewählten Ausgabeformat
|
||||
|
||||
### Audio
|
||||
|
||||
- Zielordner: `Converter Ausgabe (Audio)`
|
||||
- Dateiname/Ordner: `Output-Template (Audio)`
|
||||
- bei Shared- oder Folder-Jobs entsteht eine Ordnerstruktur mit mehreren Track-Dateien
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Converter Ausgabe (Video)`
|
||||
- `Converter Ausgabe (Audio)`
|
||||
- `Output-Template (Video)`
|
||||
- `Output-Template (Audio)`
|
||||
- `Eigentümer Converter Video Output-Ordner`
|
||||
- `Eigentümer Converter Audio Output-Ordner`
|
||||
|
||||
## Queue und Start
|
||||
|
||||
Converter-Jobs laufen über dieselbe globale Pipeline-Queue wie Ripper und Audiobooks.
|
||||
|
||||
Das bedeutet:
|
||||
|
||||
- sofortiger Start, wenn Limits frei sind
|
||||
- sonst Einreihung in die Warteschlange
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Parallele Jobs`
|
||||
- `Max. Encodes gesamt (medienunabhängig)`
|
||||
|
||||
## Typische Einsatzfälle
|
||||
|
||||
- vorhandene MKV/MP4-Dateien mit neuem Preset encodieren
|
||||
- ISO-Dateien in einen Video-Workflow überführen
|
||||
- Musikdateien gesammelt in einen Audio-Ordner-Job packen
|
||||
- Medien auf anderem Storage per Upload oder Dateibaum vorbereiten
|
||||
|
||||
## Abgrenzung zu Audiobooks
|
||||
|
||||
- `Converter`: beliebige Audio-, Video- und ISO-Dateien
|
||||
- `Audiobooks`: spezialisierter AAX-Workflow mit Activation Bytes, Kapitelmetadaten und Kapiteltemplates
|
||||
@@ -0,0 +1,35 @@
|
||||
# Database (Expert)
|
||||
|
||||
`/database` ist die Recovery- und Expertensicht für Fälle, in denen Dateisystem und Historie nicht mehr sauber zusammenpassen.
|
||||
|
||||
## Zugriff
|
||||
|
||||
- direkte Route: `/database`
|
||||
- nicht Teil der Standardnavigation
|
||||
|
||||
## Bereich `Gefundene RAW-Einträge`
|
||||
|
||||
Dieser Bereich listet RAW-Verzeichnisse ohne zugeordneten Historie-Job.
|
||||
|
||||
Aktionen:
|
||||
|
||||
- `RAW prüfen`: scannt konfigurierte RAW-Wurzeln
|
||||
- `Job anlegen`: erstellt aus einem orphan RAW einen neuen Historie-Job
|
||||
|
||||
## Was bei `Job anlegen` passiert
|
||||
|
||||
- RAW-Pfad wird als Importquelle registriert
|
||||
- Job wird in die Historie geschrieben
|
||||
- anschließende Analyse läuft als RAW-basierter Einstieg (ohne klassischen Disc-Read)
|
||||
|
||||
Typischer Einsatz:
|
||||
|
||||
- manuelle Dateioperationen außerhalb der UI
|
||||
- Migrationen
|
||||
- Wiederherstellung nach abgebrochenen Läufen
|
||||
|
||||
## Sicherheits- und Betriebsregeln
|
||||
|
||||
- Aktionen wirken direkt auf produktive Historie/Dateipfade.
|
||||
- Vor Import oder Löschung immer Pfad und Ziel prüfen.
|
||||
- Diese Seite nur für Recovery-Szenarien nutzen, nicht für normalen Tagesbetrieb.
|
||||
@@ -0,0 +1,58 @@
|
||||
# Downloads
|
||||
|
||||
Auf `Downloads` werden ZIP-Archive für Historie-Artefakte erstellt und bereitgestellt.
|
||||
|
||||
## Was heruntergeladen werden kann
|
||||
|
||||
Ein Download-Eintrag referenziert immer einen Historie-Job und genau ein Ziel:
|
||||
|
||||
- `RAW`
|
||||
- `Output`
|
||||
|
||||
Erzeugt wird ein ZIP-Archiv im Download-Verzeichnis des Backends.
|
||||
|
||||
## Statusmodell
|
||||
|
||||
| Status | Bedeutung |
|
||||
|---|---|
|
||||
| `queued` | Eintrag erstellt, wartet auf Verarbeitung |
|
||||
| `processing` | ZIP wird gerade gebaut |
|
||||
| `ready` | Archiv fertig, Download-Link aktiv |
|
||||
| `failed` | Erzeugung oder Zugriff fehlgeschlagen |
|
||||
|
||||
## Eintrag anlegen
|
||||
|
||||
Startpunkt ist die `Historie`:
|
||||
|
||||
1. Job öffnen.
|
||||
2. Download einreihen.
|
||||
3. Ziel (`RAW` oder `Output`) wählen.
|
||||
4. Status in `Downloads` verfolgen.
|
||||
|
||||
## Wichtige Laufzeitdetails
|
||||
|
||||
- Wenn bereits ein passendes, aktuelles Archiv existiert, kann der Eintrag wiederverwendet werden.
|
||||
- Nach Backend-Neustart werden unterbrochene `queued`/`processing`-Einträge geprüft und fortgesetzt.
|
||||
- Fehlt eine erwartete ZIP-Datei bei `ready`, wird der Eintrag auf `failed` gesetzt.
|
||||
|
||||
## Download auslösen
|
||||
|
||||
Bei Status `ready`:
|
||||
|
||||
- Download-Button lädt die ZIP direkt aus `/api/downloads/:id/file`.
|
||||
|
||||
## Einträge entfernen
|
||||
|
||||
`Löschen` entfernt:
|
||||
|
||||
- Queue-Metadaten
|
||||
- zugehörige Archivdatei
|
||||
|
||||
Nicht erlaubt:
|
||||
|
||||
- Löschen während `queued`/`processing`
|
||||
|
||||
## Echtzeitaktualisierung
|
||||
|
||||
Die Seite reagiert auf `DOWNLOADS_UPDATED` per WebSocket.
|
||||
Dadurch sind Statuswechsel ohne Reload sichtbar.
|
||||
@@ -0,0 +1,45 @@
|
||||
# Hardware
|
||||
|
||||
Die Seite `Hardware` ist die ausführliche Detailansicht für das Live-Monitoring aus dem `Ripper`.
|
||||
|
||||
## Was die Seite zeigt
|
||||
|
||||
- aktuelle CPU-Auslastung
|
||||
- RAM-Auslastung
|
||||
- GPU-Auslastung und VRAM, falls vorhanden
|
||||
- Temperaturen
|
||||
- Verlaufshistorie für Auslastung und Temperatur
|
||||
- Zeitfenster für `1h`, `6h`, `24h`, `4d`
|
||||
|
||||
## Live-Bereich
|
||||
|
||||
Oben zeigt die Seite:
|
||||
|
||||
- ob Monitoring aktiv ist
|
||||
- aktuelles Polling-Intervall
|
||||
- Zeitpunkt der letzten Messung
|
||||
|
||||
Wenn Monitoring deaktiviert ist, führt die Seite direkt zu `Settings`.
|
||||
|
||||
## Historie
|
||||
|
||||
Die Historie lädt Messpunkte aus dem Backend und zeigt:
|
||||
|
||||
- Auslastung als Linienchart
|
||||
- Temperatur als Linienchart
|
||||
- umschaltbare Serien für CPU, RAM und GPU
|
||||
|
||||
Das ist besonders nützlich bei:
|
||||
|
||||
- mehreren parallelen Encodes
|
||||
- Fehlersuche bei Hitzespitzen
|
||||
- Abschätzung, ob weitere Jobs sinnvoll gestartet werden können
|
||||
|
||||
## Relevante Settings
|
||||
|
||||
- `Hardware Monitoring aktiviert`
|
||||
- `Hardware Monitoring Intervall (ms)`
|
||||
|
||||
Außerdem sinnvoll:
|
||||
|
||||
- `Externe Speicher`, damit Speicherstände im `Ripper` sinnvoll angezeigt werden
|
||||
@@ -0,0 +1,88 @@
|
||||
# Historie
|
||||
|
||||
`Historie` ist die Kontroll- und Nachbearbeitungsoberfläche für alle bereits angelegten Jobs.
|
||||
|
||||
## Hauptansicht
|
||||
|
||||
Filter und Arbeitsmittel:
|
||||
|
||||
- Suche
|
||||
- Statusfilter
|
||||
- Mediumfilter
|
||||
- Sortierung
|
||||
- Listen-/Grid-Layout
|
||||
|
||||
Jeder Eintrag zeigt auf einen Blick:
|
||||
|
||||
- Titel, Jahr, Poster oder Cover
|
||||
- Status und Zeitstempel
|
||||
- RAW- und Output-Verfügbarkeit
|
||||
- Medien- und Containerhinweise
|
||||
|
||||
## Detaildialog
|
||||
|
||||
Der Detaildialog bündelt:
|
||||
|
||||
- Metadaten
|
||||
- Jobstatus und Fehlertexte
|
||||
- RAW- und Output-Pfade
|
||||
- Encode-Plan und Trackauswahl
|
||||
- ausgeführte Kommandos
|
||||
- Prozesslog
|
||||
- verfügbare Folgeaktionen
|
||||
|
||||
Bei Seriencontainern und Multipart-Jobs wird container- und child-orientiert dargestellt.
|
||||
|
||||
## Nachbearbeitungsaktionen
|
||||
|
||||
| Aktion | Typischer Einsatz | Technische Wirkung |
|
||||
|---|---|---|
|
||||
| `TMDb neu zuweisen` | falsches Match, anderer Film, andere Staffel | Metadaten werden neu geschrieben; Poster, Jahr und ggf. Ordnername werden best effort aktualisiert |
|
||||
| `Review neu starten` | neue Track-/Titelbewertung nötig | Review wird aus vorhandenem RAW neu aufgebaut |
|
||||
| `RAW neu encodieren` | neuer Encode mit vorhandenem RAW | startet Encode ohne neuen Disc-Rip |
|
||||
| `Encode neu starten` | gleiche bestätigte Auswahl erneut fahren | letzter bestätigter Plan wird geladen |
|
||||
| `Retry Rippen` | Rip oder Analyse erneut anstoßen | neuer Rip-Lauf inklusive RAW-Phase |
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Encode-Neustart: unvollständige Ausgabe löschen`
|
||||
- `NFO nach Encode erzeugen`
|
||||
|
||||
## Löschaktionen und Vorschau
|
||||
|
||||
Vor dem endgültigen Löschen zeigt Ripster eine Vorschau mit:
|
||||
|
||||
- RAW-Kandidaten
|
||||
- Movie-/Episode-Kandidaten
|
||||
- Related-Scope für Container, Kinder und verbundene Jobs
|
||||
|
||||
Wichtige Punkte:
|
||||
|
||||
- Pfade sind selektierbar
|
||||
- bei mehreren RAW-Kandidaten muss mindestens ein RAW-Pfad gewählt werden
|
||||
- Schutzlogik verhindert Löschungen außerhalb erlaubter Root-Verzeichnisse
|
||||
|
||||
## Serien- und Multipart-Sicht
|
||||
|
||||
### Serien
|
||||
|
||||
- Container zeigt den aggregierten Zustand der Child-Jobs
|
||||
- Disk- und Episodenaktionen können child-spezifisch ausgeführt werden
|
||||
- `Im Ripper öffnen` hilft bei offenen Reviews
|
||||
|
||||
### Multipart
|
||||
|
||||
- gemeinsamer Container mit Disc-Childs
|
||||
- Disc-Nummern bleiben pro Child nachvollziehbar
|
||||
- Delete-Preview kann Related-Pfade gemeinsam auflösen
|
||||
|
||||
## Logs sinnvoll nutzen
|
||||
|
||||
- `Tail laden` für schnellen Fehlerkontext
|
||||
- `Vollständiges Log laden` für tiefe Analyse
|
||||
|
||||
Empfehlung:
|
||||
|
||||
1. erst den Tail prüfen
|
||||
2. dann die Stelle im Log eingrenzen
|
||||
3. anschließend die passende Wiederanlauf-Aktion wählen
|
||||
@@ -0,0 +1,42 @@
|
||||
# GUI-Seiten
|
||||
|
||||
Dieses Kapitel ist das Bedienhandbuch für die Oberflächen im Alltag.
|
||||
|
||||
## Seitenüberblick
|
||||
|
||||
| Seite | Rolle im Betrieb | Typischer Einsatz |
|
||||
|---|---|---|
|
||||
| [Ripper](ripper.md) | Live-Steuerung der Disc-Pipeline | Disc erkennen, Analyse starten, Entscheidungen treffen, Queue steuern |
|
||||
| [Hardware](hardware.md) | Detailansicht für Live-Monitoring | CPU/RAM/GPU und Verlauf prüfen |
|
||||
| [Audiobooks](audiobooks.md) | AAX-Spezialflow | Upload, Kapitelprüfung und Encode von Audiobooks |
|
||||
| [Settings](settings.md) | Konfiguration und Automatisierung | Pfade, Tools, Queue, Presets, Skripte, Cron |
|
||||
| [Historie](history.md) | Nachbearbeitung und Kontrolle | Logs, Re-Encode, TMDb-Neuzuordnung, Löschvorschau |
|
||||
| [Converter](converter.md) | dateibasierte Konvertierung | Video/Audio/ISO ohne Disc-Rip verarbeiten |
|
||||
| [Downloads](downloads.md) | ZIP-Exports | RAW/Output aus der Historie bereitstellen |
|
||||
| [Database (Expert)](database.md) | Recovery-Sicht | orphan RAW finden, prüfen und importieren |
|
||||
| [TMDb Migration](tmdb-migration.md) | Sonderseite für Altbestände | alte Jobs gesammelt auf TMDb umstellen |
|
||||
|
||||
## Empfohlener Tagesablauf
|
||||
|
||||
1. `Ripper`, `Converter` oder `Audiobooks`: neue Arbeit starten
|
||||
2. `Historie`: Ergebnisse kontrollieren und ggf. nachbearbeiten
|
||||
3. `Downloads`: Artefakte für externe Übergabe vorbereiten
|
||||
4. `Settings`: Regeln, Presets oder Limits nur kontrolliert anpassen
|
||||
5. `Hardware`: bei Lastspitzen oder Batch-Läufen den Verlauf prüfen
|
||||
|
||||
## Navigation
|
||||
|
||||
Direkt in der Top-Navigation:
|
||||
|
||||
- `Ripper`
|
||||
- `Converter`
|
||||
- `Audiobooks`
|
||||
- `Settings`
|
||||
- `Historie`
|
||||
- `Downloads`
|
||||
|
||||
Zusatzansichten:
|
||||
|
||||
- `Hardware` unter `/hardware`
|
||||
- `Database` unter `/database` und im Expertenmodus zusätzlich in der Navigation
|
||||
- `TMDb Migration` unter `/tmdb-migration` als Direktlink
|
||||
@@ -0,0 +1,227 @@
|
||||
# Ripper
|
||||
|
||||
Die Seite `Ripper` ist die Live-Steuerung der Disc-Pipeline. Hier laufen Disc-Erkennung, Queue, manuelle Entscheidungen, Review und aktive Jobs zusammen.
|
||||
|
||||
## Seitenaufbau
|
||||
|
||||
Die wichtigsten Bereiche:
|
||||
|
||||
1. `Hardware`
|
||||
2. `Job Queue`
|
||||
3. `Skript- / Cron-Status`
|
||||
4. `Job Übersicht`
|
||||
5. `Disk-Information`
|
||||
|
||||
## 1. Hardware
|
||||
|
||||
Die Hardware-Karte zeigt live:
|
||||
|
||||
- CPU
|
||||
- RAM
|
||||
- GPU, falls vorhanden
|
||||
- freie Speicherstände der konfigurierten Pfade
|
||||
|
||||
Aktionen:
|
||||
|
||||
- Klick auf das Hardware-Symbol öffnet die Seite [Hardware](hardware.md)
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Hardware Monitoring aktiviert`
|
||||
- `Hardware Monitoring Intervall (ms)`
|
||||
- `Externe Speicher`
|
||||
|
||||
## 2. Job Queue
|
||||
|
||||
Es gibt zwei operative Zonen:
|
||||
|
||||
- laufende Jobs
|
||||
- Warteschlange
|
||||
|
||||
Mögliche Queue-Einträge:
|
||||
|
||||
- normale Job-Starts
|
||||
- `Retry Rippen`
|
||||
- `RAW neu encodieren`
|
||||
- `Encode neu starten`
|
||||
- `Review neu starten`
|
||||
- `Audio CD starten`
|
||||
- `Skript`
|
||||
- `Skriptkette`
|
||||
- `Warten`
|
||||
|
||||
Wichtige Regeln:
|
||||
|
||||
- Reihenfolge ist per Drag-and-Drop änderbar
|
||||
- `Warten` blockiert nachfolgende Starts, bis keine aktive Verarbeitung mehr läuft
|
||||
- Queue-Einträge können auch ohne Medienjob existieren
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Parallele Jobs`
|
||||
- `Max. parallele Audio CD Jobs`
|
||||
- `Max. Encodes gesamt (medienunabhängig)`
|
||||
- `Audio CDs: Queue-Reihenfolge überspringen`
|
||||
|
||||
## 3. Skript- / Cron-Status
|
||||
|
||||
Zeigt Runtime-Aktivitäten:
|
||||
|
||||
- laufende Skripte
|
||||
- laufende Ketten
|
||||
- Cron-Ausführungen
|
||||
- kürzlich abgeschlossene Aktivitäten
|
||||
|
||||
Aktionen:
|
||||
|
||||
- `Nächster Schritt` bei Ketten
|
||||
- `Abbrechen`
|
||||
- `Liste leeren`
|
||||
|
||||
## 4. Job Übersicht
|
||||
|
||||
Die Jobliste ist der zentrale Arbeitsbereich. Ein Klick öffnet den jeweiligen `Pipeline-Status`.
|
||||
|
||||
### Zustandsabhängige Hauptaktionen
|
||||
|
||||
| Zustand | Typische Aktion | Ergebnis |
|
||||
|---|---|---|
|
||||
| `Medium erkannt` | `Analyse starten` | MakeMKV-Analyse beginnt |
|
||||
| `Metadatenauswahl` | `Metadaten öffnen` | TMDb-Dialog für Film/Serie |
|
||||
| `Warte auf Auswahl` | Entscheidung bestätigen | Flow geht an die passende Stelle weiter |
|
||||
| `Startbereit` | `Job starten` | Rip oder RAW-basierte Prüfung startet |
|
||||
| `Bereit zum Encodieren` | `Encoding starten` | HandBrake startet mit bestätigter Auswahl |
|
||||
| laufend | `Abbrechen` | Job wird gestoppt |
|
||||
| `Fehler` / `Abgebrochen` | `Retry Rippen` | neuer Rip-Anlauf |
|
||||
|
||||
### Was `Warte auf Auswahl` heute bedeuten kann
|
||||
|
||||
Der Status ist nicht nur für eine einzige Entscheidung da. Im aktuellen Stand gibt es drei typische Fälle:
|
||||
|
||||
#### Vorhandenes RAW
|
||||
|
||||
Ripster hat zu den Metadaten bereits ein passendes RAW gefunden. Dann entscheidest du:
|
||||
|
||||
- mit RAW weiterarbeiten
|
||||
- RAW löschen und neu rippen
|
||||
- in passenden Film-Fällen optional Multipart mit Orphan-RAW bilden
|
||||
|
||||
#### Playlist-Auswahl
|
||||
|
||||
Bei mehrdeutigen Blu-rays oder bestimmten DVD-Fällen musst du eine Playlist bestätigen. Die Liste zeigt unter anderem:
|
||||
|
||||
- Playlist-Datei
|
||||
- Titel-ID
|
||||
- Laufzeit
|
||||
- Score
|
||||
- Empfehlung
|
||||
- Segment- und Audio-Vorschau
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Minimale Titellänge (Minuten)`
|
||||
- `TMDb Runtime-Abzug für Playlistfilter (%)`
|
||||
- `Bei manueller Auswahl senden` für PushOver
|
||||
|
||||
#### Titelauswahl / PlayAll-Grenzfall
|
||||
|
||||
Wenn Ripster mehrere HandBrake-Titel als plausibel erkannt hat, musst du einen oder mehrere Titel bestätigen. Bei Serien kann das der Grenzfall `PlayAll oder Doppelfolge?` sein.
|
||||
|
||||
## 5. Review-Bereich (`Bereit zum Encodieren`)
|
||||
|
||||
Hier triffst du die eigentliche Encode-Entscheidung.
|
||||
|
||||
Du legst fest:
|
||||
|
||||
- welchen Titel Ripster encodieren soll
|
||||
- welche Audio-Spuren übernommen werden
|
||||
- welche Untertitel übernommen, erzwungen oder eingebrannt werden
|
||||
- welches User-Preset oder HandBrake-Preset verwendet wird
|
||||
- welche Pre-/Post-Encode-Skripte oder Ketten mitlaufen
|
||||
|
||||
Wichtig:
|
||||
|
||||
- ohne diese Bestätigung startet kein produktiver Encode
|
||||
- bei Multipart-Locks können Einstellungen von einer Referenz-Disc übernommen und gesperrt sein
|
||||
|
||||
### Welche Settings hier direkt sichtbar werden
|
||||
|
||||
- `HandBrake Preset`
|
||||
- `HandBrake Extra Args`
|
||||
- `Review Audio-Sprachen (...)`
|
||||
- `Review UT-Sprachen (...)`
|
||||
- `Ausgabeformat`
|
||||
- Standard-Zuordnungen aus `Settings -> Encode-Presets`
|
||||
|
||||
## RAW-Ordnerphasen
|
||||
|
||||
Der Ripper arbeitet mit drei RAW-Zuständen:
|
||||
|
||||
- `Incomplete_...` während eines unvollständigen Rips
|
||||
- `Rip_Complete_...` nach erfolgreichem Rip, vor dem finalen Encode
|
||||
- ohne Prefix nach erfolgreichem Encode
|
||||
|
||||
Das ist wichtig für:
|
||||
|
||||
- Recovery
|
||||
- RAW-Wiederverwendung
|
||||
- Delete-Preview in `Historie`
|
||||
|
||||
## Disk-Information
|
||||
|
||||
Zeigt aktuelle Laufwerksdaten:
|
||||
|
||||
- Device-Pfad
|
||||
- Modell
|
||||
- Disc-Label
|
||||
- Mount-Informationen
|
||||
|
||||
Aktionen:
|
||||
|
||||
- `Laufwerk neu lesen`
|
||||
- `Disk neu analysieren`
|
||||
- Metadaten-Dialog öffnen
|
||||
|
||||
Hinweis:
|
||||
|
||||
- `Laufwerk neu lesen` ist nicht mehr an einen festen Pipeline-State gebunden
|
||||
|
||||
## Wichtige Dialoge
|
||||
|
||||
### Metadaten auswählen
|
||||
|
||||
Im Dialog bestätigst du Film- oder Serienmetadaten aus TMDb.
|
||||
|
||||
Sonderfälle:
|
||||
|
||||
- Film-Duplikat: `Übernahme erzwingen` oder `Multipart movie`
|
||||
- Serie: `Disc-Nummer` ist Pflicht
|
||||
|
||||
### Vorhandenes RAW erkannt
|
||||
|
||||
Wenn zu den Metadaten bereits RAW existiert, fordert Ripster eine explizite Entscheidung:
|
||||
|
||||
- vorhandenes RAW verwenden
|
||||
- RAW verwerfen/löschen und neu rippen
|
||||
|
||||
### Queue-Eintrag einfügen
|
||||
|
||||
Du kannst gezielt ab Position einfügen:
|
||||
|
||||
- Skript
|
||||
- Skriptkette
|
||||
- Wartezeit
|
||||
|
||||
### Audible Activation Bytes eintragen
|
||||
|
||||
Wenn für eine AAX-Datei keine Activation Bytes verfügbar sind, öffnet Ripster einen Dialog zur manuellen Eingabe.
|
||||
|
||||
- Format: genau 8 Hex-Zeichen, z. B. `1a2b3c4d`
|
||||
- Speicherung: lokal im Activation-Bytes-Cache
|
||||
- Wirkung: der Audiobook-Flow kann anschließend fortgesetzt werden
|
||||
|
||||
## Siehe auch
|
||||
|
||||
- [Hardware](hardware.md)
|
||||
- [Settings](settings.md)
|
||||
- [Workflows aus Nutzersicht](../workflows/index.md)
|
||||
@@ -0,0 +1,283 @@
|
||||
# Settings
|
||||
|
||||
Die Seite `Settings` ist das Kontrollzentrum für Laufzeitverhalten, Standardwerte und Automatisierung. Alles, was spätere Jobs automatisch tun oder vorschlagen, wird hier vorbereitet.
|
||||
|
||||
Für die detaillierte Feld-für-Feld-Erklärung jeder einzelnen Einstellung nutze die Seite [Einstellungsreferenz](../configuration/settings-reference.md). Dort ist jedes sichtbare Feld aus der GUI mit Wirkung, Workflow-Bezug und typischem Einsatz beschrieben.
|
||||
|
||||
## Tab-Überblick
|
||||
|
||||
| Tab | Zweck |
|
||||
|---|---|
|
||||
| `Konfiguration` | alle fachlichen Einstellungen aus der GUI |
|
||||
| `Scripte` | einzelne Bash-Skripte anlegen, testen und sortieren |
|
||||
| `Skriptketten` | mehrstufige Abläufe aus Skript- und Warte-Schritten bauen |
|
||||
| `Encode-Presets` | eigene Video-Presets und Standard-Zuordnungen pflegen |
|
||||
| `Cronjobs` | zeitgesteuerte Ausführung von Skripten oder Ketten |
|
||||
|
||||
## Tab `Konfiguration`
|
||||
|
||||
### Bedienlogik
|
||||
|
||||
1. Felder ändern
|
||||
2. `Änderungen speichern` klicken
|
||||
3. erst dann gelten die neuen Werte für künftige Starts, Reviews oder Scheduler
|
||||
|
||||
Ausnahmen:
|
||||
|
||||
- `Expertenmodus` wird sofort gespeichert
|
||||
- Buttons wie `PushOver Test`, `Coverarts prüfen` oder der MakeMKV-Betakey-Import lösen direkte Aktionen aus
|
||||
|
||||
### Toolbar-Aktionen
|
||||
|
||||
- `Änderungen speichern`: schreibt nur geänderte Felder
|
||||
- `Änderungen verwerfen`: setzt den Formularzustand zurück
|
||||
- `Neu laden`: lädt Schema und Werte neu
|
||||
- `PushOver Test`: sendet eine Testnachricht mit den aktuellen PushOver-Werten
|
||||
- `Coverarts prüfen`: startet den Coverart-Recovery-Lauf sofort
|
||||
|
||||
### Was die Kategorien im Alltag steuern
|
||||
|
||||
#### Benachrichtigungen
|
||||
|
||||
Hier steuerst du zwei Dinge:
|
||||
|
||||
- ob und wohin Ripster PushOver-Nachrichten sendet
|
||||
- bei welchen Ereignissen Ripster überhaupt benachrichtigt
|
||||
|
||||
Wichtig:
|
||||
|
||||
- `PushOver aktiviert` ist der Master-Schalter
|
||||
- `Bei manueller Auswahl senden` ist besonders relevant für Playlist-, RAW- oder Titelentscheidungen
|
||||
- der `Expertenmodus` blendet zusätzliche technische Felder in der gesamten Settings-Seite ein
|
||||
|
||||
#### Laufwerk
|
||||
|
||||
Diese Kategorie beeinflusst, wie Ripster optische Laufwerke findet und überwacht.
|
||||
|
||||
Typische Fragen:
|
||||
|
||||
- Soll Ripster Laufwerke automatisch erkennen?
|
||||
- Soll ein bestimmtes Laufwerk fest an einen MakeMKV-Index gebunden werden?
|
||||
- Soll das Laufwerk nach erfolgreichem Rip automatisch auswerfen?
|
||||
|
||||
Das ist vor allem wichtig bei:
|
||||
|
||||
- mehreren Laufwerken
|
||||
- USB-SATA-Adaptern
|
||||
- Hosts mit instabilen Device-Namen
|
||||
|
||||
#### Logging
|
||||
|
||||
Diese Felder ändern nicht die Job-Logs auf Platte, sondern die Ausgabe im Server-Terminal.
|
||||
|
||||
Damit steuerst du zum Beispiel:
|
||||
|
||||
- ob `start.sh` oder ein Terminal-Run sehr gesprächig sein darf
|
||||
- ob HTTP-Requests im Terminal sichtbar sein sollen
|
||||
- ob DEBUG/INFO/WARN/ERROR dort mitlaufen
|
||||
|
||||
#### Metadaten
|
||||
|
||||
Hier legst du fest, wie Ripster mit TMDb, Covern und NFO-Dateien umgeht.
|
||||
|
||||
Besonders wichtig:
|
||||
|
||||
- ohne `TMDb Read Access Token` funktionieren Film-/Seriensuche und Neu-Zuordnung nur eingeschränkt oder gar nicht
|
||||
- `Film-Sprache` und `Fallback Sprache` bestimmen, welche Titel, Beschreibungen und Staffelinformationen bevorzugt werden
|
||||
- `Coverart-Nachladen aktiv` hilft bei nachträglich fehlenden Postern/Covern
|
||||
|
||||
#### Monitoring
|
||||
|
||||
Steuert das Hardware-Monitoring für:
|
||||
|
||||
- CPU
|
||||
- RAM
|
||||
- GPU
|
||||
- Speicherstände
|
||||
|
||||
Diese Werte erscheinen:
|
||||
|
||||
- kompakt im `Ripper`
|
||||
- ausführlich in der Seite `Hardware`
|
||||
|
||||
#### Pfade
|
||||
|
||||
Hier legst du fest, wohin Ripster schreibt und wie Dateien benannt werden.
|
||||
|
||||
Die Felder steuern:
|
||||
|
||||
- RAW-Verzeichnisse pro Medium
|
||||
- Zielordner für Filme, Serien, CDs, Audiobooks, Converter und Downloads
|
||||
- Eigentümer per `user:gruppe`
|
||||
- Templates für Datei- und Ordnernamen
|
||||
|
||||
Praxisbeispiele:
|
||||
|
||||
- Serien getrennt von Filmen ablegen
|
||||
- RAW auf große HDD, Final-Output auf NAS
|
||||
- Audiobooks kapitelweise in Unterordnern strukturieren
|
||||
|
||||
#### Converter
|
||||
|
||||
Diese Kategorie wirkt nur auf die Seite `Converter`.
|
||||
|
||||
Sie steuert:
|
||||
|
||||
- welche Dateiendungen der Upload und der Verzeichnisscan akzeptieren
|
||||
- ob der Converter-RAW-Baum automatisch neu gescannt wird
|
||||
- wie häufig dieses Polling läuft
|
||||
|
||||
#### Tools
|
||||
|
||||
Diese Kategorie entscheidet über das technische Verhalten der eigentlichen Pipeline.
|
||||
|
||||
Dazu gehören:
|
||||
|
||||
- Pfade/Befehle für externe Tools
|
||||
- MakeMKV-Filter und Rip-Modi
|
||||
- HandBrake-Presets und Extra-Args
|
||||
- Vorauswahl von Audio-/Untertitelsprachen in der Review
|
||||
- Ausgabeformate
|
||||
- Queue- und Parallelitätsregeln
|
||||
- Timeout für Script-Tests
|
||||
|
||||
Für die Nutzer-Workflows besonders relevant:
|
||||
|
||||
- `Minimale Titellänge (Minuten)`
|
||||
- `TMDb Runtime-Abzug für Playlistfilter (%)`
|
||||
- `HandBrake Preset` und `HandBrake Extra Args`
|
||||
- `Review Audio-Sprachen (...)`
|
||||
- `Review UT-Sprachen (...)`
|
||||
- `Parallele Jobs`
|
||||
- `Max. parallele Audio CD Jobs`
|
||||
- `Max. Encodes gesamt (medienunabhängig)`
|
||||
|
||||
### Kategorie `Pfade`: Besondere Interaktion
|
||||
|
||||
Die Pfad-Kategorie hat eine eigene Darstellung:
|
||||
|
||||
- Tabelle `Effektive Pfade`: zeigt die aktuell wirklich verwendeten Laufzeitpfade inklusive Fallbacks
|
||||
- Accordion pro Bereich wie `Blu-ray`, `DVD`, `CD / Audio`, `Audiobook`, `Converter`, `Downloads`, `Logs`
|
||||
- Owner-Felder (`*_owner`) erscheinen direkt beim zugehörigen Pfad
|
||||
- Owner-Felder sind deaktiviert, solange der zugehörige Pfad leer ist
|
||||
|
||||
### Spezial-Editoren
|
||||
|
||||
- `Explizite Laufwerke`: Editor für mehrere Laufwerke mit Pfad und MakeMKV-Index
|
||||
- `Externe Speicher`: Liste aus Anzeigename und Pfad für die Speicheranzeige
|
||||
- `Erlaubte Datei-Endungen`: Auswahl der erlaubten Upload-/Scan-Endungen
|
||||
- `MakeMKV Key`: inkl. Betakey-Hinweis und Übernahme-Button
|
||||
|
||||
### Wichtig für Reviews und Workflows
|
||||
|
||||
Die Seite `Settings` bestimmt direkt, was Nutzer später im Workflow sehen:
|
||||
|
||||
- Playlist-Kandidaten werden durch `Minimale Titellänge` und `TMDb Runtime-Abzug ...` beeinflusst
|
||||
- Audio-/Untertitel-Vorauswahlen in `Bereit zum Encodieren` hängen an den Review-Sprachfeldern
|
||||
- automatisch vorgeschlagene Presets hängen an den Standard-Zuordnungen unter `Encode-Presets`
|
||||
- Queue-Verhalten im `Ripper` hängt an den drei Parallelitätsfeldern plus `Audio CDs: Queue-Reihenfolge überspringen`
|
||||
|
||||
## Tab `Scripte`
|
||||
|
||||
Funktionen:
|
||||
|
||||
- Skript anlegen
|
||||
- Skript bearbeiten
|
||||
- Skript löschen
|
||||
- Skript testen
|
||||
- Reihenfolge per Drag-and-Drop ändern
|
||||
- Favorit markieren
|
||||
|
||||
Das Testergebnis zeigt:
|
||||
|
||||
- Erfolg oder Fehler
|
||||
- Exit-Code
|
||||
- Dauer
|
||||
- stdout/stderr
|
||||
- Timeout, falls `Script-Test Timeout (ms)` greift
|
||||
|
||||
## Tab `Skriptketten`
|
||||
|
||||
Skriptketten bestehen aus Schritten:
|
||||
|
||||
- `Skript`
|
||||
- `Warten (Sekunden)`
|
||||
|
||||
Funktionen:
|
||||
|
||||
- Ketten anlegen, bearbeiten, löschen
|
||||
- Reihenfolge der Ketten ändern
|
||||
- einzelne Ketten testen
|
||||
- Schritte innerhalb der Kette per Drag-and-Drop sortieren
|
||||
|
||||
Wichtig:
|
||||
|
||||
- dieselben Skripte können sowohl in Jobs als auch in Ketten und Cronjobs wiederverwendet werden
|
||||
|
||||
## Tab `Encode-Presets`
|
||||
|
||||
Hier werden Video-Standards für Disc- und Converter-Workflows verwaltet.
|
||||
|
||||
### Standard-Zuordnungen
|
||||
|
||||
Es gibt vier feste Slots:
|
||||
|
||||
- `Blu-ray Film`
|
||||
- `Blu-ray Serie`
|
||||
- `DVD Film`
|
||||
- `DVD Serie`
|
||||
|
||||
Wenn für einen Workflow hier ein Default gesetzt ist, erscheint dieses User-Preset später in der Review bereits vorausgewählt.
|
||||
|
||||
### Preset-Inhalt
|
||||
|
||||
Ein User-Preset besteht aus:
|
||||
|
||||
- Name
|
||||
- Medientyp (`all`, `bluray`, `dvd`)
|
||||
- HandBrake-Preset
|
||||
- Extra Args
|
||||
- optionaler Beschreibung
|
||||
|
||||
## Tab `Cronjobs`
|
||||
|
||||
Funktionen:
|
||||
|
||||
- Cronjob anlegen, bearbeiten, löschen
|
||||
- Cron-Ausdruck live validieren
|
||||
- Quelle wählen: `Skript` oder `Skriptkette`
|
||||
- Aktiv- und PushOver-Status pro Job setzen
|
||||
- `Jetzt ausführen`
|
||||
- Lauf-Logs öffnen
|
||||
|
||||
Die Runtime-Aktivitäten der laufenden Cronjobs werden zusätzlich live angezeigt.
|
||||
|
||||
## Expertenbereich: Activation Bytes Cache
|
||||
|
||||
Dieser Block wird nur im Expertenmodus angezeigt.
|
||||
|
||||
Er zeigt lokal bekannte AAX-Activation-Bytes mit:
|
||||
|
||||
- Prüfsumme
|
||||
- Activation Bytes
|
||||
- Speicherzeitpunkt
|
||||
|
||||
Das hilft bei Audiobook-Workflows, wenn dieselbe Datei oder derselbe Hash später erneut auftaucht.
|
||||
|
||||
## Validierung von Template-Feldern
|
||||
|
||||
Template-Felder akzeptieren nur:
|
||||
|
||||
- Buchstaben und Ziffern
|
||||
- Leerzeichen
|
||||
- `_` und `-`
|
||||
- Platzhalter in `{...}` oder `${...}`
|
||||
- `/` für Unterordner
|
||||
|
||||
Damit verhindert Ripster fehlerhafte Dateinamen schon beim Speichern.
|
||||
|
||||
## Siehe auch
|
||||
|
||||
- [Alle Einstellungen](../configuration/settings-reference.md)
|
||||
- [Ripper](ripper.md)
|
||||
- [Workflows aus Nutzersicht](../workflows/index.md)
|
||||
@@ -0,0 +1,52 @@
|
||||
# TMDb Migration
|
||||
|
||||
Die Seite `TMDb Migration` ist eine Sonderansicht für ältere Bestandsjobs, die noch nicht als auf TMDb migriert markiert sind.
|
||||
|
||||
## Zugriff
|
||||
|
||||
- Direktlink: `/tmdb-migration`
|
||||
- nicht in der normalen Top-Navigation verlinkt
|
||||
|
||||
## Wofür die Seite gedacht ist
|
||||
|
||||
Typische Einsatzfälle:
|
||||
|
||||
- Altbestand aus früheren Ständen bereinigen
|
||||
- mehrere Jobs nacheinander auf aktuelle TMDb-Metadaten umstellen
|
||||
- Historie konsistent auf den heutigen Metadaten-Workflow bringen
|
||||
|
||||
## Funktionsweise
|
||||
|
||||
Die Seite lädt offene Migrationskandidaten und zeigt:
|
||||
|
||||
- Job-ID
|
||||
- Titel
|
||||
- Jahr
|
||||
- Medium
|
||||
- aktuellen Status
|
||||
|
||||
Aktionen:
|
||||
|
||||
- `Liste neu laden`
|
||||
- `Start`
|
||||
- `Stop`
|
||||
|
||||
## Ablauf einer Sequenz
|
||||
|
||||
1. Jobliste laden
|
||||
2. `Start`
|
||||
3. der bekannte TMDb-Metadaten-Dialog öffnet sich für den ersten Job
|
||||
4. nach erfolgreicher Übernahme plant Ripster den nächsten Job mit Cooldown
|
||||
|
||||
Wichtig:
|
||||
|
||||
- zwischen zwei Jobs liegt bewusst eine Wartezeit von mindestens 10 Sekunden
|
||||
- damit wird die TMDb-API bei Serienmigrationen nicht unnötig belastet
|
||||
|
||||
## Relevante Settings
|
||||
|
||||
- `TMDb Read Access Token`
|
||||
- `Film-Sprache`
|
||||
- `Fallback Sprache`
|
||||
|
||||
Ohne diese Einstellungen ist die Migration nicht sinnvoll nutzbar.
|
||||
@@ -0,0 +1,24 @@
|
||||
# Ripster Handbuch
|
||||
|
||||
Diese Dokumentation ist als vollständiges Benutzerhandbuch aufgebaut: tägliche Bedienung zuerst, technische Referenz danach.
|
||||
|
||||
## Einstieg in 3 Schritten
|
||||
|
||||
1. Installation: [Installation](getting-started/installation.md)
|
||||
2. Betriebskonfiguration: [Ersteinrichtung](getting-started/configuration.md)
|
||||
3. erster End-to-End-Lauf: [Erster Lauf](getting-started/quickstart.md)
|
||||
|
||||
## Was das Handbuch abdeckt
|
||||
|
||||
- alle GUI-Seiten mit Aktionen und Wirkung
|
||||
- vollständige Workflows für Film, Serie und Multipart
|
||||
- Queue-, Job-, Container- und Recovery-Verhalten
|
||||
- detaillierte Settings-Wirkung inklusive Fallbacks
|
||||
|
||||
## Empfohlene Lesereihenfolge
|
||||
|
||||
1. [Benutzerhandbuch Überblick](getting-started/index.md)
|
||||
2. [GUI-Seiten](gui/index.md)
|
||||
3. [Workflows aus Nutzersicht](workflows/index.md)
|
||||
4. [Einstellungsreferenz](configuration/settings-reference.md)
|
||||
5. bei Bedarf technischer Tiefgang im [Anhang](appendix/index.md)
|
||||
@@ -0,0 +1,103 @@
|
||||
# Encode-Planung & Track-Auswahl
|
||||
|
||||
Vor dem eigentlichen Encoding erstellt Ripster einen Encode-Plan und zeigt ihn im Review an.
|
||||
|
||||
---
|
||||
|
||||
## Ablauf
|
||||
|
||||
```text
|
||||
Quelle bestimmen (Disc/RAW)
|
||||
-> HandBrake-Scan (--scan --json)
|
||||
-> Plan erstellen (Titel, Audio, Untertitel)
|
||||
-> Status: Bereit zum Encodieren
|
||||
-> Benutzer bestaetigt Auswahl
|
||||
-> finaler HandBrake-Aufruf
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Review-Inhalt (Status: `Bereit zum Encodieren`)
|
||||
|
||||
- auswählbarer Encode-Titel
|
||||
- Audio-Track-Auswahl
|
||||
- Untertitel-Track-Auswahl inkl. Flags
|
||||
- `burnIn`
|
||||
- `forced`
|
||||
- `defaultTrack`
|
||||
- optionale User-Presets (HandBrake Preset + Extra Args)
|
||||
- optionale Pre-/Post-Skripte und Ketten
|
||||
|
||||
---
|
||||
|
||||
## Bestaetigung (`confirm-encode`)
|
||||
|
||||
Typischer Payload:
|
||||
|
||||
```json
|
||||
{
|
||||
"selectedEncodeTitleId": 1,
|
||||
"selectedTrackSelection": {
|
||||
"1": {
|
||||
"audioTrackIds": [1, 2],
|
||||
"subtitleTrackIds": [3]
|
||||
}
|
||||
},
|
||||
"selectedPreEncodeScriptIds": [1],
|
||||
"selectedPostEncodeScriptIds": [2],
|
||||
"selectedPreEncodeChainIds": [3],
|
||||
"selectedPostEncodeChainIds": [4],
|
||||
"selectedUserPresetId": 5
|
||||
}
|
||||
```
|
||||
|
||||
Die bestätigte Auswahl wird im Job gespeichert und für Neustarts wiederverwendet.
|
||||
|
||||
---
|
||||
|
||||
## HandBrake-Aufruf
|
||||
|
||||
Grundstruktur:
|
||||
|
||||
```bash
|
||||
HandBrakeCLI \
|
||||
-i <input> \
|
||||
-o <output> \
|
||||
-t <titleId> \
|
||||
-Z "<preset>" \
|
||||
<extra-args> \
|
||||
-a <audioTrackIds|none> \
|
||||
-s <subtitleTrackIds|none>
|
||||
```
|
||||
|
||||
Untertitel-Flags werden bei Bedarf ergänzt:
|
||||
|
||||
- `--subtitle-burned=<id>`
|
||||
- `--subtitle-default=<id>`
|
||||
- `--subtitle-forced=<id>` oder `--subtitle-forced`
|
||||
|
||||
---
|
||||
|
||||
## Pre-/Post-Encode-Ausführungen
|
||||
|
||||
- Pre-Encode läuft vor HandBrake
|
||||
- Post-Encode läuft nach HandBrake
|
||||
|
||||
Fehlerverhalten:
|
||||
|
||||
- Pre-Encode-Fehler: Job endet mit Status `Fehler` (Encode startet nicht)
|
||||
- Post-Encode-Fehler: Job kann `Fertig` bleiben, enthält aber Fehlerhinweis/Script-Summary
|
||||
|
||||
---
|
||||
|
||||
## Dateinamen/Ordner
|
||||
|
||||
Der finale Outputpfad wird aus den Templates in den Settings aufgebaut.
|
||||
|
||||
Platzhalter:
|
||||
|
||||
- `${title}`
|
||||
- `${year}`
|
||||
- `${imdbId}`
|
||||
|
||||
Ungültige Dateizeichen werden bereinigt.
|
||||
@@ -0,0 +1,43 @@
|
||||
# Anhang: Pipeline intern
|
||||
|
||||
Dieser Abschnitt beschreibt die technische Pipeline-Logik hinter den UI-Workflows.
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- :material-state-machine: **Workflow & Zustände**
|
||||
|
||||
---
|
||||
|
||||
Zustandsmodell, Übergänge, Queue-Verhalten.
|
||||
|
||||
[:octicons-arrow-right-24: Workflow](workflow.md)
|
||||
|
||||
- :material-film: **Encode-Planung**
|
||||
|
||||
---
|
||||
|
||||
Aufbereitung von Titeln/Tracks und Bestätigungslogik.
|
||||
|
||||
[:octicons-arrow-right-24: Encoding](encoding.md)
|
||||
|
||||
- :material-playlist-check: **Playlist-Analyse**
|
||||
|
||||
---
|
||||
|
||||
Bewertung mehrdeutiger Blu-ray-Playlists.
|
||||
|
||||
[:octicons-arrow-right-24: Playlist-Analyse](playlist-analysis.md)
|
||||
|
||||
- :material-script-text: **Pre-/Post-Encode-Ausführungen**
|
||||
|
||||
---
|
||||
|
||||
Skript- und Kettenlauf vor/nach dem Encoding.
|
||||
|
||||
[:octicons-arrow-right-24: Encode-Skripte](post-encode-scripts.md)
|
||||
|
||||
</div>
|
||||
|
||||
## Zurück zum Handbuch
|
||||
|
||||
- [Workflows aus Nutzersicht](../workflows/index.md)
|
||||
@@ -0,0 +1,68 @@
|
||||
# Playlist-Analyse
|
||||
|
||||
Ripster analysiert bei Blu-ray-ähnlichen Quellen Playlists und fordert bei Mehrdeutigkeit eine manuelle Auswahl an.
|
||||
|
||||
---
|
||||
|
||||
## Ziel
|
||||
|
||||
Erkennen, welche Playlist sehr wahrscheinlich der Hauptfilm ist, statt versehentlich eine Fake-/Dummy-Playlist zu verwenden.
|
||||
|
||||
---
|
||||
|
||||
## Eingabedaten
|
||||
|
||||
Die Analyse basiert auf MakeMKV-Infos (u. a. Playlist-/Segment-Struktur, Laufzeiten, Titelzuordnung).
|
||||
|
||||
---
|
||||
|
||||
## Auswertung (vereinfacht)
|
||||
|
||||
Für Kandidaten werden u. a. berücksichtigt:
|
||||
|
||||
- Laufzeit
|
||||
- Segment-Reihenfolge
|
||||
- Rückwärtssprünge/große Sprünge
|
||||
- Kohärenz linearer Segmentfolgen
|
||||
- Duplikatgruppen mit ähnlicher Laufzeit
|
||||
|
||||
Daraus entstehen intern Kandidatenlisten, Bewertungen und eine Empfehlung.
|
||||
|
||||
---
|
||||
|
||||
## Wann muss der Benutzer entscheiden?
|
||||
|
||||
Wenn nach Filterung mehr als ein relevanter Kandidat übrig bleibt, wechselt der Job in der GUI auf:
|
||||
|
||||
- `Warte auf Auswahl`
|
||||
|
||||
Dann muss eine Playlist bestätigt werden, bevor der Workflow weiterläuft.
|
||||
|
||||
---
|
||||
|
||||
## Konfigurationseinfluss
|
||||
|
||||
| Feld in `Settings` | Wirkung |
|
||||
|---|---|
|
||||
| `Minimale Titellänge (Minuten)` | Mindestlaufzeit für Kandidaten aus MakeMKV/Playlist-Analyse |
|
||||
| `TMDb Runtime-Abzug für Playlistfilter (%)` | lockert bei Bedarf die untere Laufzeitgrenze relativ zur TMDb-Laufzeit, damit leicht kürzere Hauptfassungen Kandidaten bleiben |
|
||||
|
||||
Default ist aktuell `60` Minuten.
|
||||
|
||||
---
|
||||
|
||||
## UI-Verhalten
|
||||
|
||||
Bei manueller Entscheidung zeigt der `Ripper` Kandidaten mit:
|
||||
|
||||
- Playlist-Datei
|
||||
- Titel-ID
|
||||
- Laufzeit
|
||||
- Score
|
||||
- Empfehlung
|
||||
- Segment- und Audio-Vorschau
|
||||
|
||||
Nach Bestätigung:
|
||||
|
||||
- mit vorhandenem RAW -> zurück zu `Mediainfo-Pruefung`
|
||||
- ohne RAW -> Startpfad über `Startbereit` / `Rippen`
|
||||
@@ -0,0 +1,70 @@
|
||||
# Encode-Skripte (Pre & Post)
|
||||
|
||||
Ripster kann Skripte und Skript-Ketten vor und nach dem Encode ausführen.
|
||||
|
||||
---
|
||||
|
||||
## Ablauf
|
||||
|
||||
```text
|
||||
Bereit zum Encodieren
|
||||
-> Pre-Encode Skripte/Ketten
|
||||
-> HandBrake Encoding
|
||||
-> Post-Encode Skripte/Ketten
|
||||
-> Fertig oder Fehler
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Auswahl im Review
|
||||
|
||||
Im Review-Panel kannst du getrennt wählen:
|
||||
|
||||
- `selectedPreEncodeScriptIds`
|
||||
- `selectedPostEncodeScriptIds`
|
||||
- `selectedPreEncodeChainIds`
|
||||
- `selectedPostEncodeChainIds`
|
||||
|
||||
---
|
||||
|
||||
## Fehlerverhalten
|
||||
|
||||
- Pre-Encode-Fehler stoppen die Kette und führen zu `Fehler`.
|
||||
- Post-Encode-Fehler stoppen die restlichen Post-Schritte; Job kann dennoch `Fertig` sein (mit Fehlerzusatz im Status/Log).
|
||||
|
||||
---
|
||||
|
||||
## Verfügbare Umgebungsvariablen
|
||||
|
||||
Beim Script-Run werden gesetzt:
|
||||
|
||||
- `RIPSTER_SCRIPT_RUN_AT`
|
||||
- `RIPSTER_JOB_ID`
|
||||
- `RIPSTER_JOB_TITLE`
|
||||
- `RIPSTER_MODE`
|
||||
- `RIPSTER_INPUT_PATH`
|
||||
- `RIPSTER_OUTPUT_PATH`
|
||||
- `RIPSTER_RAW_PATH`
|
||||
- `RIPSTER_SCRIPT_ID`
|
||||
- `RIPSTER_SCRIPT_NAME`
|
||||
- `RIPSTER_SCRIPT_SOURCE`
|
||||
|
||||
---
|
||||
|
||||
## Skript-Ketten
|
||||
|
||||
Ketten unterstützen zwei Step-Typen:
|
||||
|
||||
- `script` (führt ein hinterlegtes Skript aus)
|
||||
- `wait` (wartet `waitSeconds`)
|
||||
|
||||
Bei Fehler in einem Script-Step wird die Kette abgebrochen.
|
||||
|
||||
---
|
||||
|
||||
## Testläufe
|
||||
|
||||
- Skript testen: `POST /api/settings/scripts/:id/test`
|
||||
- Kette testen: `POST /api/settings/script-chains/:id/test`
|
||||
|
||||
Ergebnisse enthalten Erfolg/Exit-Code, Laufzeit und stdout/stderr.
|
||||
@@ -0,0 +1,101 @@
|
||||
# Workflow & Zustände
|
||||
|
||||
Ripster steuert den Ablauf als Zustandsmaschine.
|
||||
|
||||
---
|
||||
|
||||
## Zustandsdiagramm (vereinfacht)
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[Bereit] --> B[Medium erkannt]
|
||||
B --> C[Analyse]
|
||||
C --> D[Metadatenauswahl]
|
||||
D --> E[Startbereit]
|
||||
E --> F[Rippen]
|
||||
E --> G[Mediainfo-Pruefung]
|
||||
G --> H[Warte auf Auswahl]
|
||||
H --> G
|
||||
G --> I[Bereit zum Encodieren]
|
||||
I --> J[Encodieren]
|
||||
J --> K[Fertig]
|
||||
J --> L[Fehler]
|
||||
F --> L
|
||||
F --> M[Abgebrochen]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Statusliste (GUI-Anzeige)
|
||||
|
||||
| Status in der GUI | Bedeutung |
|
||||
|---|---|
|
||||
| `Bereit` | Wartet auf Disc |
|
||||
| `Medium erkannt` | Disc wurde erkannt |
|
||||
| `Analyse` | MakeMKV-Analyse läuft |
|
||||
| `Metadatenauswahl` | Metadaten müssen bestätigt werden |
|
||||
| `Warte auf Auswahl` | Playlist-Auswahl ist erforderlich |
|
||||
| `Warte auf Auswahl` | auch für RAW-Entscheidung bei vorhandenen Quelldaten genutzt |
|
||||
| `Startbereit` | kurzer Übergang vor Start |
|
||||
| `Rippen` | MakeMKV-Rip läuft |
|
||||
| `Mediainfo-Pruefung` | Titel/Spuren werden ausgewertet |
|
||||
| `Bereit zum Encodieren` | Review ist bereit |
|
||||
| `Encodieren` | HandBrake läuft |
|
||||
| `CD-Metadatenauswahl` | CD-Metadaten müssen bestätigt werden |
|
||||
| `CD-Startbereit` | CD-Job wartet auf Start |
|
||||
| `CD-Analyse` | CD-Track-/Strukturaufbereitung |
|
||||
| `CD-Rippen` | Audio-CD-Rip läuft |
|
||||
| `CD-Encodieren` | CD-Encode läuft |
|
||||
| `Fertig` | erfolgreich abgeschlossen |
|
||||
| `Abgebrochen` | manuell oder technisch abgebrochen |
|
||||
| `Fehler` | fehlgeschlagen |
|
||||
|
||||
---
|
||||
|
||||
## Typische Pfade
|
||||
|
||||
### Standardfall (kein vorhandenes RAW)
|
||||
|
||||
1. Medium erkannt
|
||||
2. Analyse + Metadaten
|
||||
3. Rippen
|
||||
4. Mediainfo-Pruefung
|
||||
5. Bereit zum Encodieren
|
||||
6. Encodieren
|
||||
7. Fertig
|
||||
|
||||
### Vorhandenes RAW
|
||||
|
||||
`Startbereit` springt direkt zu `Mediainfo-Pruefung` (kein neuer Rip).
|
||||
|
||||
### Mehrdeutige Blu-ray-Playlist
|
||||
|
||||
`Mediainfo-Pruefung` -> `Warte auf Auswahl` bis Playlist bestätigt wurde.
|
||||
|
||||
### Vorhandenes RAW mit Nutzerentscheidung
|
||||
|
||||
`Metadatenauswahl` -> `Warte auf Auswahl` bis Entscheidung für Weiterverarbeitung (`continue`) oder Neustart getroffen wurde.
|
||||
|
||||
### CD-Flow
|
||||
|
||||
`CD-Metadatenauswahl` -> `CD-Startbereit` -> `CD-Rippen` -> `CD-Encodieren` -> `Fertig`
|
||||
|
||||
---
|
||||
|
||||
## Queue-Verhalten
|
||||
|
||||
Wenn der Wert `Parallele Jobs` erreicht ist:
|
||||
|
||||
- neue Starts werden als Queue-Einträge abgelegt
|
||||
- die Queue kann zusätzlich Nicht-Job-Einträge enthalten (`Skript`, `Kette`, `Warten`)
|
||||
- Reihenfolge ist per UI/API änderbar
|
||||
|
||||
---
|
||||
|
||||
## Abbruch, Wiederaufnahme, Neustart
|
||||
|
||||
- `Abbrechen`: laufenden Job stoppen oder Queue-Eintrag entfernen
|
||||
- `Retry Rippen`: Fehler-/Abbruch-Job erneut starten
|
||||
- `RAW neu encodieren`: aus vorhandenem RAW neu encodieren
|
||||
- `Review neu starten`: Review aus RAW neu aufbauen
|
||||
- `Encode neu starten`: Encoding mit letzter bestätigter Auswahl neu starten
|
||||
@@ -0,0 +1,150 @@
|
||||
/* Ripster custom styles */
|
||||
|
||||
:root {
|
||||
--md-primary-fg-color: #6a1b9a;
|
||||
--md-accent-fg-color: #ab47bc;
|
||||
}
|
||||
|
||||
/* Cards grid layout */
|
||||
.grid.cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 1rem;
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
|
||||
.grid.cards > * {
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid var(--md-default-fg-color--lightest);
|
||||
padding: 1.25rem;
|
||||
transition: box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.grid.cards > *:hover {
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
/* Status badge colors */
|
||||
.status-idle { color: #78909c; }
|
||||
.status-analyzing { color: #fb8c00; }
|
||||
.status-ripping { color: #1976d2; }
|
||||
.status-encoding { color: #7b1fa2; }
|
||||
.status-finished { color: #388e3c; }
|
||||
.status-error { color: #d32f2f; }
|
||||
|
||||
/* Code blocks */
|
||||
.md-typeset pre > code {
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
/* Mermaid diagrams – standard */
|
||||
.md-typeset .mermaid {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
|
||||
/* Large pipeline flowchart: horizontal scroll + min-height */
|
||||
.pipeline-diagram {
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
margin: 1.5rem 0;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.pipeline-diagram .mermaid {
|
||||
min-width: 900px;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.pipeline-diagram .mermaid svg {
|
||||
min-width: 900px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* Pipeline step track */
|
||||
.pipeline-steps {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
gap: 0;
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
padding: 1rem 0 1.5rem 0;
|
||||
margin: 1.5rem 0;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
.pipeline-step {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
min-width: 110px;
|
||||
flex: 0 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.pipeline-step:not(:last-child)::after {
|
||||
content: '→';
|
||||
position: absolute;
|
||||
right: -14px;
|
||||
top: 22px;
|
||||
font-size: 1.2rem;
|
||||
color: var(--md-default-fg-color--light);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.pipeline-step-badge {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.5rem;
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
.pipeline-step-label {
|
||||
font-size: 0.7rem;
|
||||
text-align: center;
|
||||
line-height: 1.2;
|
||||
max-width: 90px;
|
||||
color: var(--md-default-fg-color);
|
||||
}
|
||||
|
||||
.pipeline-step-sub {
|
||||
font-size: 0.6rem;
|
||||
color: var(--md-default-fg-color--light);
|
||||
text-align: center;
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
|
||||
/* Step colors */
|
||||
.step-idle { background: #eceff1; color: #546e7a; border-color: #90a4ae; }
|
||||
.step-user { background: #e8eaf6; color: #3949ab; border-color: #7986cb; }
|
||||
.step-running { background: #e3f2fd; color: #1565c0; border-color: #42a5f5; }
|
||||
.step-wait { background: #fff8e1; color: #e65100; border-color: #ffa726; }
|
||||
.step-encode { background: #f3e5f5; color: #6a1b9a; border-color: #ab47bc; }
|
||||
.step-done { background: #e8f5e9; color: #2e7d32; border-color: #66bb6a; }
|
||||
.step-error { background: #ffebee; color: #c62828; border-color: #ef5350; }
|
||||
|
||||
/* Table improvements */
|
||||
.md-typeset table:not([class]) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.md-typeset table:not([class]) th {
|
||||
background-color: var(--md-primary-fg-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Admonition tweaks */
|
||||
.md-typeset .admonition.tip {
|
||||
border-color: #00897b;
|
||||
}
|
||||
|
||||
.md-typeset .admonition.tip > .admonition-title {
|
||||
background-color: rgba(0, 137, 123, 0.1);
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
# HandBrake
|
||||
|
||||
Ripster verwendet `HandBrakeCLI` für Scan und Encode.
|
||||
|
||||
---
|
||||
|
||||
## Verwendete Aufrufe
|
||||
|
||||
### Scan (Review-Aufbau)
|
||||
|
||||
```bash
|
||||
HandBrakeCLI --scan --json -i <input> -t 0
|
||||
```
|
||||
|
||||
### Encode (vereinfacht)
|
||||
|
||||
```bash
|
||||
HandBrakeCLI \
|
||||
-i <input> \
|
||||
-o <output> \
|
||||
-t <titleId> \
|
||||
-Z "<preset>" \
|
||||
<extra-args> \
|
||||
-a <audioTrackIds|none> \
|
||||
-s <subtitleTrackIds|none>
|
||||
```
|
||||
|
||||
Optional ergänzt Ripster:
|
||||
|
||||
- `--subtitle-burned=<id>`
|
||||
- `--subtitle-default=<id>`
|
||||
- `--subtitle-forced=<id>` oder `--subtitle-forced`
|
||||
|
||||
---
|
||||
|
||||
## Presets auslesen
|
||||
|
||||
Ripster liest Presets mit:
|
||||
|
||||
```bash
|
||||
HandBrakeCLI -z
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Relevante Felder in `Settings`
|
||||
|
||||
| Feldname in der GUI | Bedeutung |
|
||||
|-----|-----------|
|
||||
| `HandBrake Kommando` | CLI-Binary |
|
||||
| `HandBrake Preset` (Blu-ray/DVD) | profilspezifisches Preset |
|
||||
| `HandBrake Extra Args` (Blu-ray/DVD) | profilspezifische Zusatzargumente |
|
||||
| `Ausgabeformat` (Blu-ray/DVD) | Dateiendung der finalen Datei |
|
||||
| `Encode-Neustart: unvollständige Ausgabe löschen` | unvollständige Ausgabe bei Neustart löschen |
|
||||
|
||||
---
|
||||
|
||||
## Fortschritts-Parsing
|
||||
|
||||
Ripster parst HandBrake-Stderr (Prozent/ETA/Detail) und sendet WebSocket-Progress (`PIPELINE_PROGRESS`).
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- Preset nicht gefunden: Preset-Namen mit `HandBrakeCLI -z` prüfen
|
||||
- sehr langsames Encoding: Preset/Extra-Args prüfen (z. B. `--encoder-preset`)
|
||||
|
||||
Das Produktions-Installer-Script `install.sh` bietet eine Option zur Installation eines gebündelten HandBrakeCLI-Binaries mit NVDEC-Unterstützung (NVIDIA GPU-Dekodierung). Diese Option erscheint interaktiv während der Installation.
|
||||
@@ -0,0 +1,31 @@
|
||||
# Anhang: Externe Tools
|
||||
|
||||
Ripster orchestriert externe CLI-Tools. Dieser Abschnitt erklärt deren Rolle im Gesamtsystem.
|
||||
|
||||
<div class="grid cards" markdown>
|
||||
|
||||
- :material-disc: **MakeMKV**
|
||||
|
||||
---
|
||||
|
||||
Disc-Analyse und Ripping.
|
||||
|
||||
[:octicons-arrow-right-24: MakeMKV](makemkv.md)
|
||||
|
||||
- :material-film: **HandBrake**
|
||||
|
||||
---
|
||||
|
||||
Video-Encoding inklusive Preset-Logik.
|
||||
|
||||
[:octicons-arrow-right-24: HandBrake](handbrake.md)
|
||||
|
||||
- :material-information: **MediaInfo**
|
||||
|
||||
---
|
||||
|
||||
Track-/Containeranalyse für Review und Auswahl.
|
||||
|
||||
[:octicons-arrow-right-24: MediaInfo](mediainfo.md)
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,69 @@
|
||||
# MakeMKV
|
||||
|
||||
Ripster nutzt `makemkvcon` für Disc-Analyse und Rip.
|
||||
|
||||
---
|
||||
|
||||
## Verwendete Aufrufe
|
||||
|
||||
### Analyse
|
||||
|
||||
```bash
|
||||
makemkvcon -r info <source>
|
||||
```
|
||||
|
||||
`<source>` ist typischerweise:
|
||||
|
||||
- `disc:<index>` (Auto-Modus)
|
||||
- `dev:/dev/sr0` (explicit)
|
||||
- `file:<path>` (Datei/Ordner-Analyse)
|
||||
|
||||
### Rip (MKV-Modus)
|
||||
|
||||
```bash
|
||||
makemkvcon mkv <source> <title-or-all> <rawDir> [--minlength=...] [...extraArgs]
|
||||
```
|
||||
|
||||
### Rip (Backup-Modus)
|
||||
|
||||
```bash
|
||||
makemkvcon backup <source> <rawDir> --decrypt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Registrierungsschlüssel (optional)
|
||||
|
||||
Wenn in `Settings` ein `MakeMKV Key` gesetzt ist, synchronisiert Ripster ihn nach:
|
||||
|
||||
```bash
|
||||
~/.MakeMKV/settings.conf
|
||||
```
|
||||
|
||||
Format:
|
||||
|
||||
```ini
|
||||
app_Key = "product-key"
|
||||
```
|
||||
|
||||
Zusätzlich zeigt die UI unterhalb des Feldes den aktuellen Betakey an, der per Button in das Eingabefeld übernommen werden kann.
|
||||
|
||||
---
|
||||
|
||||
## Relevante Felder in `Settings`
|
||||
|
||||
| Feldname in der GUI | Bedeutung |
|
||||
|-----|-----------|
|
||||
| `MakeMKV Kommando` | CLI-Binary |
|
||||
| `MakeMKV Source Index` | Source-Index im Auto-Modus |
|
||||
| `Minimale Titellaenge (Minuten)` | Mindestlaufzeitfilter |
|
||||
| `MakeMKV Rip Modus` (Blu-ray/DVD) | `mkv` oder `backup` |
|
||||
| `MakeMKV Analyze Extra Args` (Blu-ray/DVD) | Zusatzargumente für Analyse |
|
||||
| `MakeMKV Rip Extra Args` (Blu-ray/DVD) | Zusatzargumente für Rip |
|
||||
|
||||
---
|
||||
|
||||
## Hinweise
|
||||
|
||||
- Blu-ray-Backups werden oft für robuste Playlist-Analyse genutzt.
|
||||
- MakeMKV-Ausgaben werden geparst und als `makemkvInfo` im Job gespeichert.
|
||||
@@ -0,0 +1,37 @@
|
||||
# MediaInfo
|
||||
|
||||
Ripster nutzt `mediainfo` zur JSON-Analyse von Medien-Dateien.
|
||||
|
||||
---
|
||||
|
||||
## Aufruf
|
||||
|
||||
```bash
|
||||
mediainfo --Output=JSON <input>
|
||||
```
|
||||
|
||||
Der Input ist typischerweise eine RAW-Datei oder ein vom Workflow gewählter Inputpfad.
|
||||
|
||||
---
|
||||
|
||||
## Verwendung in Ripster
|
||||
|
||||
- Track-/Codec-Metadaten für Review-Plan
|
||||
- Fallback-Informationen in bestimmten Analysepfaden
|
||||
- Persistenz als `mediainfoInfo` im Job
|
||||
|
||||
---
|
||||
|
||||
## Relevante Settings
|
||||
|
||||
| Key | Bedeutung |
|
||||
|-----|-----------|
|
||||
| `mediainfo_command` | CLI-Binary |
|
||||
| `mediainfo_extra_args_bluray` / `_dvd` | profilspezifische Zusatzargumente |
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- JSON-Test: `mediainfo --Output=JSON <datei>`
|
||||
- unbekannte Sprache erscheint oft als `und` (undetermined)
|
||||
@@ -0,0 +1,366 @@
|
||||
# Workflows aus Nutzersicht
|
||||
|
||||
Diese Seite beschreibt die produktiven Abläufe aus Sicht der Benutzer: welche Entscheidung wann anfällt, welche Jobs oder Container entstehen und welche Settings den Ablauf sichtbar beeinflussen.
|
||||
|
||||
## Gemeinsame Grundlagen
|
||||
|
||||
### Typische Statuskette
|
||||
|
||||
`Medium erkannt` -> `Analyse` -> `Metadatenauswahl` -> `Startbereit` -> `Rippen` -> `Mediainfo-Prüfung` -> `Bereit zum Encodieren` -> `Encodieren` -> `Fertig`
|
||||
|
||||
Wichtige Abweichungen:
|
||||
|
||||
- bei vorhandenem RAW: Sprung direkt in RAW-Entscheidung oder Review
|
||||
- bei mehrdeutigen Blu-rays/DVDs: `Warte auf Auswahl` für Playlist- oder Titelauswahl
|
||||
- bei Fehler oder Abbruch: `Fehler` oder `Abgebrochen` mit Folgeaktionen
|
||||
- bei Audio-CDs und Audiobooks: eigener Spezialflow innerhalb derselben Gesamtpipeline
|
||||
|
||||
### Welche Settings fast überall hineinspielen
|
||||
|
||||
Die wichtigsten globalen Einflussfaktoren:
|
||||
|
||||
- `Parallele Jobs`
|
||||
- `Max. parallele Audio CD Jobs`
|
||||
- `Max. Encodes gesamt (medienunabhängig)`
|
||||
- `Audio CDs: Queue-Reihenfolge überspringen`
|
||||
- `PushOver`-Ereignisse
|
||||
- Pfade, Templates und Owner-Felder
|
||||
|
||||
Für Disc-Video zusätzlich:
|
||||
|
||||
- `Minimale Titellänge (Minuten)`
|
||||
- `TMDb Runtime-Abzug für Playlistfilter (%)`
|
||||
- `HandBrake Preset`
|
||||
- `HandBrake Extra Args`
|
||||
- `Review Audio-Sprachen (...)`
|
||||
- `Review UT-Sprachen (...)`
|
||||
- Standard-Zuordnungen aus `Settings -> Encode-Presets`
|
||||
|
||||
## Workflow A: Film von Disc (Blu-ray / DVD)
|
||||
|
||||
### 1. Disc analysieren und TMDb-Metadaten wählen
|
||||
|
||||
1. Im `Ripper` `Analyse starten`
|
||||
2. im Metadaten-Dialog Film auswählen
|
||||
3. `Auswahl übernehmen`
|
||||
|
||||
Wirkung:
|
||||
|
||||
- der Job wird als Film-Workflow geführt
|
||||
- Film-Metadaten, Poster und Fingerprint werden gesetzt
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `TMDb Read Access Token`
|
||||
- `Film-Sprache`
|
||||
- `Fallback Sprache`
|
||||
|
||||
### 2. Duplikatfall entscheiden
|
||||
|
||||
Wenn ein Film mit gleichem Fingerprint bereits existiert:
|
||||
|
||||
1. `Übernahme erzwingen`: neuer unabhängiger Film-Job
|
||||
2. `Multipart movie`: neuer Job wird mit bestehendem Film zu einem Multipart-Container verknüpft
|
||||
|
||||
Bei Multipart gilt:
|
||||
|
||||
- beide Discs brauchen unterschiedliche Disc-Nummern
|
||||
- gleiche Disc-Nummern blockieren den Vorgang
|
||||
|
||||
### 3. RAW-Verzeichnis und RAW-Entscheidung
|
||||
|
||||
Wenn noch kein passendes RAW vorhanden ist:
|
||||
|
||||
- Ripster legt ein neues RAW-Verzeichnis an
|
||||
|
||||
Wenn bereits ein passendes RAW gefunden wird:
|
||||
|
||||
- der Job geht in `Warte auf Auswahl`
|
||||
- du entscheidest, ob das vorhandene RAW weiterverwendet oder neu gerippt wird
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Raw Ausgabeordner (Blu-ray)` und `Raw Ausgabeordner (DVD)`
|
||||
- `Eigentümer Raw-Ordner (Blu-ray)` und `Eigentümer Raw-Ordner (DVD)`
|
||||
|
||||
### 4. Playlist- oder Titelauswahl
|
||||
|
||||
Bei bestimmten Discs ist nach der Metadatenphase eine manuelle Auswahl nötig:
|
||||
|
||||
- Playlist-Auswahl
|
||||
- HandBrake-Titelauswahl
|
||||
- bei Serien-Grenzfällen PlayAll- oder Doppelfolgen-Entscheidung
|
||||
|
||||
Das ist der aktuelle `playlistflow`.
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Minimale Titellänge (Minuten)`
|
||||
- `TMDb Runtime-Abzug für Playlistfilter (%)`
|
||||
- `Bei manueller Auswahl senden`
|
||||
|
||||
Praxis:
|
||||
|
||||
- zu hoher Mindestwert blendet legitime Alternativfassungen aus
|
||||
- ein kleiner Runtime-Abzug hilft bei Discs, deren Hauptfilm minimal unter der TMDb-Laufzeit liegt
|
||||
|
||||
### 5. Review und Encode
|
||||
|
||||
Im Zustand `Bereit zum Encodieren` entscheidest du:
|
||||
|
||||
- welcher Titel encodiert wird
|
||||
- welche Audio-Spuren übernommen werden
|
||||
- welche Untertitel übernommen, erzwungen oder eingebrannt werden
|
||||
- welches Preset gilt
|
||||
- welche Pre-/Post-Encode-Skripte oder Ketten mitlaufen
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `HandBrake Preset`
|
||||
- `HandBrake Extra Args`
|
||||
- `Review Audio-Sprachen (Blu-ray Film)` oder `Review Audio-Sprachen (DVD Film)`
|
||||
- `Review UT-Sprachen (Blu-ray Film)` oder `Review UT-Sprachen (DVD Film)`
|
||||
- `Ausgabeformat`
|
||||
- Standard-Userpreset für Film unter `Settings -> Encode-Presets`
|
||||
|
||||
### 6. Finale Ausgabe
|
||||
|
||||
Finale Ausgabe:
|
||||
|
||||
- Zielordner: `Film Ausgabeordner (Blu-ray)` oder `Film Ausgabeordner (DVD)`
|
||||
- Dateiname und Ordner: `Output Template (Blu-ray)` oder `Output Template (DVD)`
|
||||
|
||||
Optional:
|
||||
|
||||
- `.nfo` direkt nach Encode
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Film Ausgabeordner (Blu-ray)` und `Film Ausgabeordner (DVD)`
|
||||
- `Eigentümer Film-Ordner (Blu-ray)` und `Eigentümer Film-Ordner (DVD)`
|
||||
- `Output Template (Blu-ray)` und `Output Template (DVD)`
|
||||
- `NFO nach Encode erzeugen`
|
||||
|
||||
## Workflow B: Serie von Disc (Blu-ray / DVD)
|
||||
|
||||
### 1. Serienmodus festlegen
|
||||
|
||||
1. Disc analysieren
|
||||
2. im Metadaten-Dialog Serienmetadaten wählen
|
||||
3. `Disc-Nummer` setzen
|
||||
|
||||
Wirkung:
|
||||
|
||||
- Ripster arbeitet als Serien-Workflow
|
||||
- Seriencontainer wird gesucht oder angelegt
|
||||
- der Job wird als Child unter diesem Container geführt
|
||||
|
||||
### 2. Serien-RAW und Staffelkontext
|
||||
|
||||
Für Serien bevorzugt Ripster eigene Serien-RAW-Verzeichnisse:
|
||||
|
||||
- `RAW-Ordner (Blu-ray Serie)`
|
||||
- `RAW-Ordner (DVD Serie)`
|
||||
|
||||
Falls leer:
|
||||
|
||||
- Fallback auf `Raw Ausgabeordner (Blu-ray)` bzw. `Raw Ausgabeordner (DVD)`
|
||||
|
||||
### 3. Episodenprüfung und Multi-Episode-Fälle
|
||||
|
||||
In der Review werden Episoden oder Mehrfachfolgen aufgelöst.
|
||||
|
||||
Ausgabevarianten:
|
||||
|
||||
- Einzel-Episode
|
||||
- Multi-Episode-Datei
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Output Template (Blu-ray Serie, Episode)`
|
||||
- `Output Template (Blu-ray Serie, Multi-Episode)`
|
||||
- `Output Template (DVD Serie, Episode)`
|
||||
- `Output Template (DVD Serie, Multi-Episode)`
|
||||
- `Serien-Ordner (Blu-ray)`
|
||||
- `Serien-Ordner (DVD)`
|
||||
|
||||
### 4. Playlistflow auch bei Serien
|
||||
|
||||
Auch Serien können vor der Review in eine Playlist- oder Titelauswahl laufen.
|
||||
|
||||
Zusätzlich wirken:
|
||||
|
||||
- `Review Audio-Sprachen (Blu-ray Serie)` / `Review Audio-Sprachen (DVD Serie)`
|
||||
- `Review UT-Sprachen (Blu-ray Serie)` / `Review UT-Sprachen (DVD Serie)`
|
||||
- Serien-Default-Presets unter `Settings -> Encode-Presets`
|
||||
|
||||
## Workflow C: Multipart-Film
|
||||
|
||||
### Wann der Flow gedacht ist
|
||||
|
||||
- gleicher Film auf mehreren Discs
|
||||
- die Discs sollen in Historie und Detailansichten zusammengehören
|
||||
|
||||
### Ablauf
|
||||
|
||||
1. Film-Metadaten wählen
|
||||
2. Duplikatdialog `Multipart movie`
|
||||
3. Disc-Nummern für bestehenden und neuen Job festlegen
|
||||
|
||||
Wirkung:
|
||||
|
||||
- `multipart_movie_container` wird angelegt oder wiederverwendet
|
||||
- die Discs werden als Child-Jobs darunter geführt
|
||||
- zusätzlich wird ein Merge-Job vorbereitet
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `mkvmerge_command`
|
||||
- Film-Output-Templates
|
||||
- Queue-Limits, falls mehrere Discs parallel weiterverarbeitet werden
|
||||
|
||||
## Workflow D: Audio-CD
|
||||
|
||||
### 1. TOC lesen und Metadaten wählen
|
||||
|
||||
1. Audio-CD analysieren
|
||||
2. Tracks prüfen
|
||||
3. Metadaten aus MusicBrainz übernehmen oder manuell anpassen
|
||||
|
||||
### 2. Trackauswahl und Format
|
||||
|
||||
Vor dem Start legst du fest:
|
||||
|
||||
- welche Tracks übernommen werden
|
||||
- welches Ausgabeformat gilt
|
||||
- welche Formatoptionen genutzt werden
|
||||
- welche Pre-/Post-Encode-Skripte oder Ketten mitlaufen
|
||||
|
||||
### 3. Rip und Encode
|
||||
|
||||
Die CD läuft anschließend als Track-für-Track-Flow:
|
||||
|
||||
`CD-Metadatenauswahl` -> `CD-Startbereit` -> `CD-Rippen` -> `CD-Encodieren` -> `Fertig`
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `CD RAW-Ordner`
|
||||
- `CD Output-Ordner`
|
||||
- `Eigentümer CD RAW-Ordner`
|
||||
- `Eigentümer CD Output-Ordner`
|
||||
- `CD Output Template`
|
||||
- `cdparanoia Kommando`
|
||||
- `Max. parallele Audio CD Jobs`
|
||||
- `Audio CDs: Queue-Reihenfolge überspringen`
|
||||
|
||||
## Workflow E: Converter
|
||||
|
||||
### 1. Dateien bereitstellen
|
||||
|
||||
Dateien gelangen in den Converter über:
|
||||
|
||||
- Upload
|
||||
- bestehende Ordner im `Converter Raw-Ordner`
|
||||
- manuelle Dateiverwaltung im Explorer
|
||||
|
||||
### 2. Jobs aus Auswahl erzeugen
|
||||
|
||||
- Video und ISO: immer ein Job pro Datei
|
||||
- Audio: ein Job pro Datei oder gemeinsamer Audio-Job
|
||||
|
||||
### 3. Job konfigurieren und starten
|
||||
|
||||
Je nach Medium:
|
||||
|
||||
- Video/ISO: Review mit Track- und Preset-Auswahl
|
||||
- Audio: direkte Format- und Zielkonfiguration
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Erlaubte Datei-Endungen`
|
||||
- `Auto-Scan (Polling)`
|
||||
- `Polling-Intervall (Sekunden)`
|
||||
- `Converter Raw-Ordner`
|
||||
- `Converter Ausgabe (Video)`
|
||||
- `Converter Ausgabe (Audio)`
|
||||
- `Output-Template (Video)`
|
||||
- `Output-Template (Audio)`
|
||||
- globale Queue-Limits
|
||||
|
||||
## Workflow F: Audiobooks
|
||||
|
||||
### 1. AAX hochladen
|
||||
|
||||
1. Datei hochladen
|
||||
2. Metadaten und Kapitel aufbauen lassen
|
||||
3. bei Bedarf Activation Bytes klären
|
||||
|
||||
### 2. Ausgabeformat wählen
|
||||
|
||||
- `m4b`: eine Datei
|
||||
- `mp3`: eine Datei pro Kapitel
|
||||
- `flac`: eine Datei pro Kapitel
|
||||
|
||||
### 3. Kapitel und Skripte prüfen
|
||||
|
||||
Vor dem Start anpassbar:
|
||||
|
||||
- Kapitelnamen
|
||||
- Pre-Encode-Skripte und -Ketten
|
||||
- Post-Encode-Skripte und -Ketten
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Audiobook RAW-Ordner`
|
||||
- `Audiobook Output-Ordner`
|
||||
- `Audiobook RAW Template`
|
||||
- `Output Template (Audiobook)`
|
||||
- `Kapitel Template (Audiobook)`
|
||||
- `FFprobe Kommando`
|
||||
- `FFmpeg Kommando`
|
||||
- globale Queue-Limits
|
||||
|
||||
## Workflow G: Nachbearbeitung in der Historie
|
||||
|
||||
Typische Folgeaktionen:
|
||||
|
||||
- `TMDb neu zuweisen`
|
||||
- `Review neu starten`
|
||||
- `RAW neu encodieren`
|
||||
- `Encode neu starten`
|
||||
- `Retry Rippen`
|
||||
- `Download` als ZIP einreihen
|
||||
|
||||
Besonders wichtig:
|
||||
|
||||
- `Encode neu starten` verwendet den letzten bestätigten Plan
|
||||
- `Encode-Neustart: unvollständige Ausgabe löschen` entscheidet, ob unvollständige Ausgaben vorher gelöscht werden
|
||||
|
||||
## Workflow H: Downloads und Recovery
|
||||
|
||||
### Downloads
|
||||
|
||||
Aus `Historie` können ZIPs für:
|
||||
|
||||
- `RAW`
|
||||
- `Output`
|
||||
|
||||
erstellt werden.
|
||||
|
||||
Relevante Settings:
|
||||
|
||||
- `Download ZIP-Ordner`
|
||||
- `Eigentümer Download ZIP-Ordner`
|
||||
|
||||
### Database (Expert)
|
||||
|
||||
Die Recovery-Seite hilft bei orphan RAW:
|
||||
|
||||
- `RAW prüfen`
|
||||
- `Job anlegen`
|
||||
|
||||
So lassen sich vorhandene RAW-Verzeichnisse wieder in einen normalen Workflow zurückführen.
|
||||
|
||||
### TMDb Migration
|
||||
|
||||
Für ältere Bestandsjobs gibt es die Sonderseite `/tmdb-migration`, um mehrere Jobs nacheinander auf den heutigen TMDb-Stand zu bringen.
|
||||
Reference in New Issue
Block a user