{"config":{"lang":["de"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"],"fields":{"title":{"boost":1000.0},"text":{"boost":1.0},"tags":{"boost":1000000.0}}},"docs":[{"location":"","title":"Ripster Handbuch","text":"

Dieses Dokumentationsset ist als Benutzerhandbuch aufgebaut: erst Bedienung und Alltag, dann Technik im Anhang.

"},{"location":"#schnellstart-in-3-schritten","title":"Schnellstart in 3 Schritten","text":"
  1. Voraussetzungen pr\u00fcfen und installieren: Installation
  2. Grundkonfiguration in der UI setzen: Ersteinrichtung
  3. Ersten vollst\u00e4ndigen Job durchlaufen: Erster Lauf
"},{"location":"#was-du-hier-findest","title":"Was du hier findest","text":""},{"location":"#empfohlene-lesereihenfolge","title":"Empfohlene Lesereihenfolge","text":"
  1. Benutzerhandbuch \u00dcberblick
  2. GUI-Seiten
  3. Workflows aus Nutzersicht
  4. Bei Bedarf: Technischer Anhang
"},{"location":"api/","title":"Anhang: API-Referenz","text":"

REST- und WebSocket-Schnittstellen f\u00fcr Integration, Automatisierung und Debugging.

"},{"location":"api/#basis-url","title":"Basis-URL","text":"
http://localhost:3001\n

API-Prefix: /api

"},{"location":"api/#api-gruppen","title":"API-Gruppen","text":""},{"location":"api/#hinweis","title":"Hinweis","text":"

Ripster hat keine eingebaute Authentifizierung und ist f\u00fcr lokalen, gesch\u00fctzten Betrieb gedacht.

"},{"location":"api/crons/","title":"Cron API","text":"

Ripster enth\u00e4lt ein eingebautes Cron-System f\u00fcr Skripte und Skript-Ketten (sourceType: script|chain).

"},{"location":"api/crons/#get-apicrons","title":"GET /api/crons","text":"

Listet alle Cron-Jobs.

{\n  \"jobs\": [\n    {\n      \"id\": 1,\n      \"name\": \"Nachtlauf Backup\",\n      \"cronExpression\": \"0 2 * * *\",\n      \"sourceType\": \"script\",\n      \"sourceId\": 3,\n      \"sourceName\": \"Backup-Skript\",\n      \"enabled\": true,\n      \"pushoverEnabled\": true,\n      \"lastRunAt\": \"2026-03-10T02:00:00.000Z\",\n      \"lastRunStatus\": \"success\",\n      \"nextRunAt\": \"2026-03-11T02:00:00.000Z\",\n      \"createdAt\": \"2026-03-01T10:00:00.000Z\",\n      \"updatedAt\": \"2026-03-10T02:00:05.000Z\"\n    }\n  ]\n}\n
"},{"location":"api/crons/#post-apicrons","title":"POST /api/crons","text":"

Erstellt Cron-Job.

{\n  \"name\": \"Nachtlauf Backup\",\n  \"cronExpression\": \"0 2 * * *\",\n  \"sourceType\": \"script\",\n  \"sourceId\": 3,\n  \"enabled\": true,\n  \"pushoverEnabled\": true\n}\n

Response: 201 mit { \"job\": { ... } }

"},{"location":"api/crons/#get-apicronsid","title":"GET /api/crons/:id","text":"

Response:

{ \"job\": { \"id\": 1, \"name\": \"...\" } }\n
"},{"location":"api/crons/#put-apicronsid","title":"PUT /api/crons/:id","text":"

Aktualisiert Cron-Job. Felder wie bei POST.

Response:

{ \"job\": { ... } }\n
"},{"location":"api/crons/#delete-apicronsid","title":"DELETE /api/crons/:id","text":"

Response:

{ \"removed\": { \"id\": 1, \"name\": \"Nachtlauf Backup\" } }\n
"},{"location":"api/crons/#get-apicronsidlogs","title":"GET /api/crons/:id/logs","text":"

Liefert Ausf\u00fchrungs-Logs.

Query-Parameter:

Parameter Typ Default Beschreibung limit number 20 Anzahl Eintr\u00e4ge, max. 100

Response:

{\n  \"logs\": [\n    {\n      \"id\": 42,\n      \"cronJobId\": 1,\n      \"startedAt\": \"2026-03-10T02:00:01.000Z\",\n      \"finishedAt\": \"2026-03-10T02:00:05.000Z\",\n      \"status\": \"success\",\n      \"output\": \"Backup abgeschlossen.\",\n      \"errorMessage\": null\n    }\n  ]\n}\n

status: running | success | error

"},{"location":"api/crons/#post-apicronsidrun","title":"POST /api/crons/:id/run","text":"

Triggert Job manuell (asynchron).

Response:

{ \"triggered\": true, \"cronJobId\": 1 }\n

Wenn Job bereits l\u00e4uft: 409.

"},{"location":"api/crons/#post-apicronsvalidate-expression","title":"POST /api/crons/validate-expression","text":"

Validiert 5-Felder-Cron-Ausdruck und berechnet n\u00e4chsten Lauf.

Request:

{ \"cronExpression\": \"*/15 * * * *\" }\n

G\u00fcltige Response:

{\n  \"valid\": true,\n  \"nextRunAt\": \"2026-03-10T14:15:00.000Z\"\n}\n

Ung\u00fcltige Response:

{\n  \"valid\": false,\n  \"error\": \"Cron-Ausdruck muss genau 5 Felder haben (Minute Stunde Tag Monat Wochentag).\",\n  \"nextRunAt\": null\n}\n
"},{"location":"api/crons/#cron-format","title":"Cron-Format","text":"

Ripster unterst\u00fctzt 5 Felder:

Minute Stunde Tag Monat Wochentag\n

Beispiele:

"},{"location":"api/crons/#websocket-events-zu-cron","title":"WebSocket-Events zu Cron","text":""},{"location":"api/history/","title":"History API","text":"

Endpunkte f\u00fcr Job-Historie, Orphan-Import und L\u00f6schoperationen.

"},{"location":"api/history/#get-apihistory","title":"GET /api/history","text":"

Liefert Jobs (optionale Filter).

Query-Parameter:

Parameter Typ Beschreibung status string Filter nach Job-Status search string Suche in Titel-Feldern

Beispiel:

GET /api/history?status=FINISHED&search=Inception\n

Response:

{\n  \"jobs\": [\n    {\n      \"id\": 42,\n      \"status\": \"FINISHED\",\n      \"title\": \"Inception\",\n      \"raw_path\": \"/mnt/raw/Inception - RAW - job-42\",\n      \"output_path\": \"/mnt/movies/Inception (2010)/Inception (2010).mkv\",\n      \"mediaType\": \"bluray\",\n      \"ripSuccessful\": true,\n      \"encodeSuccess\": true,\n      \"created_at\": \"2026-03-10T08:00:00.000Z\",\n      \"updated_at\": \"2026-03-10T10:00:00.000Z\"\n    }\n  ]\n}\n
"},{"location":"api/history/#get-apihistoryid","title":"GET /api/history/:id","text":"

Liefert Job-Detail.

Query-Parameter:

Parameter Typ Standard Beschreibung includeLogs bool false Prozesslog laden includeLiveLog bool false alias-artig ebenfalls Prozesslog laden includeAllLogs bool false vollst\u00e4ndiges Log statt Tail logTailLines number 800 Tail-L\u00e4nge falls nicht includeAllLogs

Response:

{\n  \"job\": {\n    \"id\": 42,\n    \"status\": \"FINISHED\",\n    \"makemkvInfo\": {},\n    \"mediainfoInfo\": {},\n    \"handbrakeInfo\": {},\n    \"encodePlan\": {},\n    \"log\": \"...\",\n    \"log_count\": 1,\n    \"logMeta\": {\n      \"loaded\": true,\n      \"total\": 800,\n      \"returned\": 800,\n      \"truncated\": true\n    }\n  }\n}\n
"},{"location":"api/history/#get-apihistorydatabase","title":"GET /api/history/database","text":"

Debug-Ansicht der DB-Zeilen (angereichert).

Response:

{\n  \"rows\": [\n    {\n      \"id\": 42,\n      \"status\": \"FINISHED\",\n      \"rawFolderName\": \"Inception - RAW - job-42\"\n    }\n  ]\n}\n
"},{"location":"api/history/#get-apihistoryorphan-raw","title":"GET /api/history/orphan-raw","text":"

Sucht RAW-Ordner ohne zugeh\u00f6rigen Job.

Response:

{\n  \"rawDir\": \"/mnt/raw\",\n  \"rawDirs\": [\"/mnt/raw\", \"/mnt/raw-bluray\"],\n  \"rows\": [\n    {\n      \"rawPath\": \"/mnt/raw/Inception (2010) [tt1375666] - RAW - job-99\",\n      \"folderName\": \"Inception (2010) [tt1375666] - RAW - job-99\",\n      \"title\": \"Inception\",\n      \"year\": 2010,\n      \"imdbId\": \"tt1375666\",\n      \"folderJobId\": 99,\n      \"entryCount\": 4,\n      \"hasBlurayStructure\": true,\n      \"lastModifiedAt\": \"2026-03-10T09:00:00.000Z\"\n    }\n  ]\n}\n
"},{"location":"api/history/#post-apihistoryorphan-rawimport","title":"POST /api/history/orphan-raw/import","text":"

Importiert RAW-Ordner als FINISHED-Job.

Request:

{ \"rawPath\": \"/mnt/raw/Inception (2010) [tt1375666] - RAW - job-99\" }\n

Response:

{\n  \"job\": { \"id\": 77, \"status\": \"FINISHED\" },\n  \"uiReset\": { \"reset\": true, \"state\": \"IDLE\" }\n}\n
"},{"location":"api/history/#post-apihistoryidomdbassign","title":"POST /api/history/:id/omdb/assign","text":"

Weist OMDb-/Metadaten nachtr\u00e4glich zu.

Request:

{\n  \"imdbId\": \"tt1375666\",\n  \"title\": \"Inception\",\n  \"year\": 2010,\n  \"poster\": \"https://...\",\n  \"fromOmdb\": true\n}\n

Response:

{ \"job\": { \"id\": 42, \"imdb_id\": \"tt1375666\" } }\n
"},{"location":"api/history/#post-apihistoryiddelete-files","title":"POST /api/history/:id/delete-files","text":"

L\u00f6scht Dateien eines Jobs, beh\u00e4lt DB-Eintrag.

Request:

{ \"target\": \"both\" }\n

target: raw | movie | both

Response:

{\n  \"summary\": {\n    \"target\": \"both\",\n    \"raw\": { \"attempted\": true, \"deleted\": true, \"filesDeleted\": 12, \"dirsRemoved\": 3, \"reason\": null },\n    \"movie\": { \"attempted\": true, \"deleted\": false, \"filesDeleted\": 0, \"dirsRemoved\": 0, \"reason\": \"Movie-Datei/Pfad existiert nicht.\" }\n  },\n  \"job\": { \"id\": 42 }\n}\n
"},{"location":"api/history/#post-apihistoryiddelete","title":"POST /api/history/:id/delete","text":"

L\u00f6scht Job aus DB; optional auch Dateien.

Request:

{ \"target\": \"none\" }\n

target: none | raw | movie | both

Response:

{\n  \"deleted\": true,\n  \"jobId\": 42,\n  \"fileTarget\": \"both\",\n  \"fileSummary\": {\n    \"target\": \"both\",\n    \"raw\": { \"filesDeleted\": 10 },\n    \"movie\": { \"filesDeleted\": 1 }\n  },\n  \"uiReset\": {\n    \"reset\": true,\n    \"state\": \"IDLE\"\n  }\n}\n
"},{"location":"api/history/#hinweise","title":"Hinweise","text":""},{"location":"api/pipeline/","title":"Pipeline API","text":"

Endpunkte zur Steuerung des Pipeline-Workflows.

"},{"location":"api/pipeline/#get-apipipelinestate","title":"GET /api/pipeline/state","text":"

Liefert aktuellen Pipeline- und Hardware-Monitoring-Snapshot.

Response (Beispiel):

{\n  \"pipeline\": {\n    \"state\": \"READY_TO_ENCODE\",\n    \"activeJobId\": 42,\n    \"progress\": 0,\n    \"eta\": null,\n    \"statusText\": \"Mediainfo best\u00e4tigt - Encode manuell starten\",\n    \"context\": {\n      \"jobId\": 42\n    },\n    \"jobProgress\": {\n      \"42\": {\n        \"state\": \"MEDIAINFO_CHECK\",\n        \"progress\": 68.5,\n        \"eta\": null,\n        \"statusText\": \"MEDIAINFO_CHECK 68.50%\"\n      }\n    },\n    \"queue\": {\n      \"maxParallelJobs\": 1,\n      \"runningCount\": 1,\n      \"queuedCount\": 2,\n      \"runningJobs\": [],\n      \"queuedJobs\": []\n    }\n  },\n  \"hardwareMonitoring\": {\n    \"enabled\": true,\n    \"intervalMs\": 5000,\n    \"updatedAt\": \"2026-03-10T09:00:00.000Z\",\n    \"sample\": {\n      \"cpu\": {},\n      \"memory\": {},\n      \"gpu\": {},\n      \"storage\": {}\n    },\n    \"error\": null\n  }\n}\n
"},{"location":"api/pipeline/#post-apipipelineanalyze","title":"POST /api/pipeline/analyze","text":"

Startet Disc-Analyse und legt Job an.

Response:

{\n  \"result\": {\n    \"jobId\": 42,\n    \"detectedTitle\": \"INCEPTION\",\n    \"omdbCandidates\": []\n  }\n}\n
"},{"location":"api/pipeline/#post-apipipelinerescan-disc","title":"POST /api/pipeline/rescan-disc","text":"

Erzwingt erneute Laufwerkspr\u00fcfung.

Response (Beispiel):

{\n  \"result\": {\n    \"present\": true,\n    \"changed\": true,\n    \"emitted\": \"discInserted\",\n    \"device\": {\n      \"path\": \"/dev/sr0\",\n      \"discLabel\": \"INCEPTION\",\n      \"mediaProfile\": \"bluray\"\n    }\n  }\n}\n
"},{"location":"api/pipeline/#get-apipipelineomdbsearchq","title":"GET /api/pipeline/omdb/search?q=

OMDb-Titelsuche.

Response:

{\n  \"results\": [\n    {\n      \"imdbId\": \"tt1375666\",\n      \"title\": \"Inception\",\n      \"year\": \"2010\",\n      \"type\": \"movie\",\n      \"poster\": \"https://...\"\n    }\n  ]\n}\n
","text":""},{"location":"api/pipeline/#post-apipipelineselect-metadata","title":"POST /api/pipeline/select-metadata

Setzt Metadaten (und optional Playlist) f\u00fcr einen Job.

Request:

{\n  \"jobId\": 42,\n  \"title\": \"Inception\",\n  \"year\": 2010,\n  \"imdbId\": \"tt1375666\",\n  \"poster\": \"https://...\",\n  \"fromOmdb\": true,\n  \"selectedPlaylist\": \"00800\"\n}\n

Response:

{ \"job\": { \"id\": 42, \"status\": \"READY_TO_START\" } }\n
","text":""},{"location":"api/pipeline/#post-apipipelinestartjobid","title":"POST /api/pipeline/start/:jobId

Startet vorbereiteten Job oder queued ihn (je nach Parallel-Limit).

M\u00f6gliche Responses:

{ \"result\": { \"started\": true, \"stage\": \"RIPPING\" } }\n
{ \"result\": { \"queued\": true, \"started\": false, \"queuePosition\": 2, \"action\": \"START_PREPARED\" } }\n
","text":""},{"location":"api/pipeline/#post-apipipelineconfirm-encodejobid","title":"POST /api/pipeline/confirm-encode/:jobId

Best\u00e4tigt Review-Auswahl (Tracks, Pre/Post-Skripte/Ketten, User-Preset).

Request (typisch):

{\n  \"selectedEncodeTitleId\": 1,\n  \"selectedTrackSelection\": {\n    \"1\": {\n      \"audioTrackIds\": [1, 2],\n      \"subtitleTrackIds\": [3]\n    }\n  },\n  \"selectedPreEncodeScriptIds\": [1],\n  \"selectedPostEncodeScriptIds\": [2, 7],\n  \"selectedPreEncodeChainIds\": [3],\n  \"selectedPostEncodeChainIds\": [4],\n  \"selectedUserPresetId\": 5,\n  \"skipPipelineStateUpdate\": false\n}\n

Response:

{ \"job\": { \"id\": 42, \"encode_review_confirmed\": 1 } }\n
","text":""},{"location":"api/pipeline/#post-apipipelinecancel","title":"POST /api/pipeline/cancel

Bricht laufenden Job ab oder entfernt Queue-Eintrag.

Request (optional):

{ \"jobId\": 42 }\n

M\u00f6gliche Responses:

{ \"result\": { \"cancelled\": true, \"queuedOnly\": true, \"jobId\": 42 } }\n
{ \"result\": { \"cancelled\": true, \"queuedOnly\": false, \"jobId\": 42 } }\n
{ \"result\": { \"cancelled\": true, \"queuedOnly\": false, \"pending\": true, \"jobId\": 42 } }\n
","text":""},{"location":"api/pipeline/#post-apipipelineretryjobid","title":"POST /api/pipeline/retry/:jobId

Retry f\u00fcr ERROR/CANCELLED-Jobs (oder Queue-Einreihung).

","text":""},{"location":"api/pipeline/#post-apipipelinereencodejobid","title":"POST /api/pipeline/reencode/:jobId

Startet Re-Encode aus bestehendem RAW.

","text":""},{"location":"api/pipeline/#post-apipipelinerestart-reviewjobid","title":"POST /api/pipeline/restart-review/:jobId

Berechnet Review aus RAW neu.

","text":""},{"location":"api/pipeline/#post-apipipelinerestart-encodejobid","title":"POST /api/pipeline/restart-encode/:jobId

Startet Encoding mit letzter best\u00e4tigter Review neu.

","text":""},{"location":"api/pipeline/#post-apipipelineresume-readyjobid","title":"POST /api/pipeline/resume-ready/:jobId

L\u00e4dt READY_TO_ENCODE-Job nach Neustart wieder in aktive Session.

Alle Endpunkte liefern { result: ... } bzw. { job: ... }.

","text":""},{"location":"api/pipeline/#queue-endpunkte","title":"Queue-Endpunkte","text":""},{"location":"api/pipeline/#get-apipipelinequeue","title":"GET /api/pipeline/queue","text":"

Liefert Queue-Snapshot.

{\n  \"queue\": {\n    \"maxParallelJobs\": 1,\n    \"runningCount\": 1,\n    \"queuedCount\": 3,\n    \"runningJobs\": [\n      {\n        \"jobId\": 41,\n        \"title\": \"Inception\",\n        \"status\": \"ENCODING\",\n        \"lastState\": \"ENCODING\"\n      }\n    ],\n    \"queuedJobs\": [\n      {\n        \"entryId\": 11,\n        \"position\": 1,\n        \"type\": \"job\",\n        \"jobId\": 42,\n        \"action\": \"START_PREPARED\",\n        \"actionLabel\": \"Start\",\n        \"title\": \"Matrix\",\n        \"status\": \"READY_TO_ENCODE\",\n        \"lastState\": \"READY_TO_ENCODE\",\n        \"hasScripts\": true,\n        \"hasChains\": false,\n        \"enqueuedAt\": \"2026-03-10T09:00:00.000Z\"\n      },\n      {\n        \"entryId\": 12,\n        \"position\": 2,\n        \"type\": \"wait\",\n        \"waitSeconds\": 30,\n        \"title\": \"Warten 30s\",\n        \"status\": \"QUEUED\",\n        \"enqueuedAt\": \"2026-03-10T09:01:00.000Z\"\n      }\n    ],\n    \"updatedAt\": \"2026-03-10T09:01:02.000Z\"\n  }\n}\n
"},{"location":"api/pipeline/#post-apipipelinequeuereorder","title":"POST /api/pipeline/queue/reorder","text":"

Sortiert Queue-Eintr\u00e4ge neu.

Request:

{\n  \"orderedEntryIds\": [12, 11]\n}\n

Legacy fallback wird akzeptiert:

{\n  \"orderedJobIds\": [42, 43]\n}\n
"},{"location":"api/pipeline/#post-apipipelinequeueentry","title":"POST /api/pipeline/queue/entry","text":"

F\u00fcgt Nicht-Job-Queue-Eintrag hinzu (script, chain, wait).

Request-Beispiele:

{ \"type\": \"script\", \"scriptId\": 3 }\n
{ \"type\": \"chain\", \"chainId\": 2, \"insertAfterEntryId\": 11 }\n
{ \"type\": \"wait\", \"waitSeconds\": 45 }\n

Response:

{\n  \"result\": { \"entryId\": 12, \"type\": \"wait\", \"position\": 2 },\n  \"queue\": { \"...\": \"...\" }\n}\n
"},{"location":"api/pipeline/#delete-apipipelinequeueentryentryid","title":"DELETE /api/pipeline/queue/entry/:entryId","text":"

Entfernt Queue-Eintrag.

Response:

{ \"queue\": { \"...\": \"...\" } }\n
"},{"location":"api/pipeline/#pipeline-zustande","title":"Pipeline-Zust\u00e4nde State Bedeutung IDLE Wartet auf Medium DISC_DETECTED Medium erkannt ANALYZING MakeMKV-Analyse l\u00e4uft METADATA_SELECTION Metadaten-Auswahl WAITING_FOR_USER_DECISION Playlist-Entscheidung erforderlich READY_TO_START \u00dcbergang vor Start RIPPING MakeMKV-Rip l\u00e4uft MEDIAINFO_CHECK Titel-/Track-Auswertung READY_TO_ENCODE Review bereit ENCODING HandBrake-Encoding l\u00e4uft FINISHED Abgeschlossen CANCELLED Abgebrochen ERROR Fehler","text":""},{"location":"api/runtime-activities/","title":"Runtime Activities API","text":"

Ripster verfolgt alle laufenden und k\u00fcrzlich abgeschlossenen Aktivit\u00e4ten (Skripte, Skript-Ketten, Cron-Jobs, interne Tasks) in Echtzeit \u00fcber den RuntimeActivityService.

"},{"location":"api/runtime-activities/#ubersicht","title":"\u00dcbersicht","text":"

Aktivit\u00e4ten entstehen, wenn Ripster intern Aktionen ausf\u00fchrt \u2013 z. B. beim Start eines Cron-Jobs, beim Ausf\u00fchren einer Skript-Kette oder beim Durchlaufen von Pipeline-Schritten. Sie sind nicht persistent (kein DB-Speicher) und werden nur im Arbeitsspeicher gehalten.

\u00c4nderungen werden \u00fcber WebSocket (RUNTIME_ACTIVITY_CHANGED) in Echtzeit gesendet.

"},{"location":"api/runtime-activities/#aktivitats-objekt","title":"Aktivit\u00e4ts-Objekt","text":"
{\n  \"id\": 7,\n  \"type\": \"chain\",\n  \"name\": \"Post-Encode Aufr\u00e4umen\",\n  \"status\": \"running\",\n  \"source\": \"cron\",\n  \"message\": \"Schritt 2 von 3\",\n  \"currentStep\": \"cleanup.sh\",\n  \"currentStepType\": \"script\",\n  \"currentScriptName\": \"cleanup.sh\",\n  \"stepIndex\": 2,\n  \"stepTotal\": 3,\n  \"parentActivityId\": null,\n  \"jobId\": 42,\n  \"cronJobId\": 3,\n  \"chainId\": 5,\n  \"scriptId\": null,\n  \"canCancel\": true,\n  \"canNextStep\": false,\n  \"outcome\": \"running\",\n  \"errorMessage\": null,\n  \"output\": null,\n  \"stdout\": null,\n  \"stderr\": null,\n  \"stdoutTruncated\": false,\n  \"stderrTruncated\": false,\n  \"startedAt\": \"2026-03-10T10:00:00.000Z\",\n  \"finishedAt\": null,\n  \"durationMs\": null,\n  \"exitCode\": null,\n  \"success\": null\n}\n
"},{"location":"api/runtime-activities/#felder","title":"Felder","text":"Feld Typ Beschreibung id number Eindeutige ID (Laufz\u00e4hler, nicht persistent) type string Art der Aktivit\u00e4t: script | chain | cron | task name string \\| null Anzeigename der Aktivit\u00e4t status string Aktueller Status: running | success | error source string \\| null Ausl\u00f6ser (z. B. cron, pipeline, manual) message string \\| null Kurztext zum aktuellen Zustand currentStep string \\| null Name des aktuell ausgef\u00fchrten 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 \u00fcbergeordneten Aktivit\u00e4t jobId number \\| null Verkn\u00fcpfte Job-ID cronJobId number \\| null Verkn\u00fcpfte Cron-Job-ID chainId number \\| null Verkn\u00fcpfte Skript-Ketten-ID scriptId number \\| null Verkn\u00fcpfte Skript-ID canCancel boolean Abbrechen \u00fcber API m\u00f6glich canNextStep boolean N\u00e4chster Schritt \u00fcber API ausl\u00f6sbar 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\u00fcrzt wurde stderrTruncated boolean true, wenn stderr gek\u00fcrzt 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\u00e4t)"},{"location":"api/runtime-activities/#snapshot-objekt","title":"Snapshot-Objekt","text":"

Alle Aktivit\u00e4ts-Endpunkte geben einen Snapshot zur\u00fcck:

{\n  \"active\": [ /* laufende Aktivit\u00e4ten, nach startedAt absteigend */ ],\n  \"recent\": [ /* abgeschlossene Aktivit\u00e4ten, nach finishedAt absteigend, max. 120 */ ],\n  \"updatedAt\": \"2026-03-10T10:05:00.000Z\"\n}\n
"},{"location":"api/runtime-activities/#endpunkte","title":"Endpunkte","text":""},{"location":"api/runtime-activities/#get-apiactivities","title":"GET /api/activities","text":"

Aktuellen Aktivit\u00e4ts-Snapshot abrufen.

Antwort:

{\n  \"active\": [],\n  \"recent\": [\n    {\n      \"id\": 5,\n      \"type\": \"script\",\n      \"name\": \"notify.sh\",\n      \"status\": \"success\",\n      \"outcome\": \"success\",\n      \"startedAt\": \"2026-03-10T09:58:00.000Z\",\n      \"finishedAt\": \"2026-03-10T09:58:02.000Z\",\n      \"durationMs\": 2100,\n      \"exitCode\": 0,\n      \"success\": true,\n      \"canCancel\": false,\n      \"canNextStep\": false\n    }\n  ],\n  \"updatedAt\": \"2026-03-10T10:05:00.000Z\"\n}\n
"},{"location":"api/runtime-activities/#post-apiactivitiesidcancel","title":"POST /api/activities/:id/cancel","text":"

Aktive Aktivit\u00e4t abbrechen (nur wenn canCancel: true).

Parameter:

Name In Typ Beschreibung id path number Aktivit\u00e4ts-ID reason body string Optionaler Abbruchgrund

Request Body:

{ \"reason\": \"Manueller Abbruch durch Benutzer\" }\n

Antwort (Erfolg):

{\n  \"ok\": true,\n  \"action\": null,\n  \"snapshot\": { \"active\": [], \"recent\": [], \"updatedAt\": \"...\" }\n}\n

Fehlercodes:

HTTP Bedeutung 404 Aktivit\u00e4t nicht gefunden oder bereits abgeschlossen 409 Abbrechen wird von dieser Aktivit\u00e4t nicht unterst\u00fctzt"},{"location":"api/runtime-activities/#post-apiactivitiesidnext-step","title":"POST /api/activities/:id/next-step","text":"

N\u00e4chsten Schritt einer Aktivit\u00e4t ausl\u00f6sen (nur wenn canNextStep: true).

Parameter:

Name In Typ Beschreibung id path number Aktivit\u00e4ts-ID

Antwort (Erfolg):

{\n  \"ok\": true,\n  \"action\": null,\n  \"snapshot\": { \"active\": [], \"recent\": [], \"updatedAt\": \"...\" }\n}\n

Fehlercodes:

HTTP Bedeutung 404 Aktivit\u00e4t nicht gefunden 409 N\u00e4chster Schritt wird von dieser Aktivit\u00e4t nicht unterst\u00fctzt"},{"location":"api/runtime-activities/#post-apiactivitiesclear-recent","title":"POST /api/activities/clear-recent","text":"

Alle abgeschlossenen Aktivit\u00e4ten aus recent l\u00f6schen.

Antwort:

{\n  \"ok\": true,\n  \"removed\": 14,\n  \"snapshot\": { \"active\": [], \"recent\": [], \"updatedAt\": \"...\" }\n}\n
"},{"location":"api/runtime-activities/#grenzwerte","title":"Grenzwerte","text":"Wert Limit Maximale recent-Eintr\u00e4ge 120 Maximale L\u00e4nge stdout / stderr / output 12.000 Zeichen Maximale L\u00e4nge errorMessage / message 2.000 Zeichen Maximale L\u00e4nge outcome 40 Zeichen

Gek\u00fcrzte Ausgaben erhalten den Suffix ...[gek\u00fcrzt] (bei Inline-Text) bzw. \\n...[gek\u00fcrzt] (bei mehrzeiligem Output).

"},{"location":"api/runtime-activities/#echtzeit-updates","title":"Echtzeit-Updates","text":"

\u00c4nderungen werden automatisch als RUNTIME_ACTIVITY_CHANGED WebSocket-Event gesendet. Die Frontend-Komponente braucht GET /api/activities nur beim initialen Laden aufzurufen.

"},{"location":"api/settings/","title":"Settings API","text":"

Endpunkte f\u00fcr Einstellungen, Skripte, Skript-Ketten und User-Presets.

"},{"location":"api/settings/#get-apisettings","title":"GET /api/settings","text":"

Liefert alle Einstellungen kategorisiert.

Response (Struktur):

{\n  \"categories\": [\n    {\n      \"category\": \"Pfade\",\n      \"settings\": [\n        {\n          \"key\": \"raw_dir\",\n          \"label\": \"Raw Ausgabeordner\",\n          \"type\": \"path\",\n          \"required\": true,\n          \"description\": \"...\",\n          \"defaultValue\": \"data/output/raw\",\n          \"options\": [],\n          \"validation\": { \"minLength\": 1 },\n          \"value\": \"data/output/raw\",\n          \"orderIndex\": 100\n        }\n      ]\n    }\n  ]\n}\n
"},{"location":"api/settings/#put-apisettingskey","title":"PUT /api/settings/:key","text":"

Aktualisiert eine einzelne Einstellung.

Request:

{ \"value\": \"/mnt/storage/raw\" }\n

Response:

{\n  \"setting\": {\n    \"key\": \"raw_dir\",\n    \"value\": \"/mnt/storage/raw\"\n  },\n  \"reviewRefresh\": {\n    \"triggered\": false,\n    \"reason\": \"not_ready\"\n  }\n}\n

reviewRefresh ist null oder ein Objekt mit Status der optionalen Review-Neuberechnung.

"},{"location":"api/settings/#put-apisettings","title":"PUT /api/settings","text":"

Aktualisiert mehrere Einstellungen atomar.

Request:

{\n  \"settings\": {\n    \"raw_dir\": \"/mnt/storage/raw\",\n    \"movie_dir\": \"/mnt/storage/movies\",\n    \"handbrake_preset_bluray\": \"H.264 MKV 1080p30\"\n  }\n}\n

Response:

{\n  \"changes\": [\n    { \"key\": \"raw_dir\", \"value\": \"/mnt/storage/raw\" },\n    { \"key\": \"movie_dir\", \"value\": \"/mnt/storage/movies\" }\n  ],\n  \"reviewRefresh\": {\n    \"triggered\": true,\n    \"jobId\": 42,\n    \"relevantKeys\": [\"handbrake_preset_bluray\"]\n  }\n}\n

Bei Validierungsfehlern kommt 400 mit error.details[].

"},{"location":"api/settings/#get-apisettingshandbrake-presets","title":"GET /api/settings/handbrake-presets","text":"

Liest Preset-Liste via HandBrakeCLI -z (mit Fallback auf konfigurierte Presets).

Response (Beispiel):

{\n  \"source\": \"handbrake-cli\",\n  \"message\": null,\n  \"options\": [\n    { \"label\": \"General/\", \"value\": \"__group__general\", \"disabled\": true, \"category\": \"General\" },\n    { \"label\": \"   Fast 1080p30\", \"value\": \"Fast 1080p30\", \"category\": \"General\" }\n  ]\n}\n
"},{"location":"api/settings/#post-apisettingspushovertest","title":"POST /api/settings/pushover/test","text":"

Sendet Testnachricht \u00fcber aktuelle PushOver-Settings.

Request (optional):

{\n  \"title\": \"Test\",\n  \"message\": \"Ripster Test\"\n}\n

Response:

{\n  \"result\": {\n    \"sent\": true,\n    \"eventKey\": \"test\",\n    \"requestId\": \"...\"\n  }\n}\n

Wenn PushOver deaktiviert ist oder Credentials fehlen, kommt i. d. R. ebenfalls 200 mit sent: false + reason.

"},{"location":"api/settings/#skripte","title":"Skripte","text":"

Basis: /api/settings/scripts

"},{"location":"api/settings/#get-apisettingsscripts","title":"GET /api/settings/scripts","text":"
{ \"scripts\": [ { \"id\": 1, \"name\": \"...\", \"scriptBody\": \"...\", \"orderIndex\": 1, \"createdAt\": \"...\", \"updatedAt\": \"...\" } ] }\n
"},{"location":"api/settings/#post-apisettingsscripts","title":"POST /api/settings/scripts","text":"
{ \"name\": \"Move\", \"scriptBody\": \"mv \\\"$RIPSTER_OUTPUT_PATH\\\" /mnt/movies/\" }\n

Response: 201 mit { \"script\": { ... } }

"},{"location":"api/settings/#put-apisettingsscriptsid","title":"PUT /api/settings/scripts/:id","text":"

Body wie POST, Response { \"script\": { ... } }.

"},{"location":"api/settings/#delete-apisettingsscriptsid","title":"DELETE /api/settings/scripts/:id","text":"

Response { \"removed\": { ... } }.

"},{"location":"api/settings/#post-apisettingsscriptsreorder","title":"POST /api/settings/scripts/reorder","text":"
{ \"orderedScriptIds\": [3, 1, 2] }\n

Response { \"scripts\": [ ... ] }.

"},{"location":"api/settings/#post-apisettingsscriptsidtest","title":"POST /api/settings/scripts/:id/test","text":"

F\u00fchrt Skript als Testlauf aus.

{\n  \"result\": {\n    \"scriptId\": 1,\n    \"scriptName\": \"Move\",\n    \"success\": true,\n    \"exitCode\": 0,\n    \"signal\": null,\n    \"timedOut\": false,\n    \"durationMs\": 120,\n    \"stdout\": \"...\",\n    \"stderr\": \"...\",\n    \"stdoutTruncated\": false,\n    \"stderrTruncated\": false\n  }\n}\n
"},{"location":"api/settings/#umgebungsvariablen-fur-skripte","title":"Umgebungsvariablen f\u00fcr Skripte","text":"

Diese Variablen werden beim Ausf\u00fchren gesetzt:

"},{"location":"api/settings/#skript-ketten","title":"Skript-Ketten","text":"

Basis: /api/settings/script-chains

Eine Kette hat Schritte vom Typ:

"},{"location":"api/settings/#get-apisettingsscript-chains","title":"GET /api/settings/script-chains","text":"

Response { \"chains\": [ ... ] } (inkl. steps[]).

"},{"location":"api/settings/#get-apisettingsscript-chainsid","title":"GET /api/settings/script-chains/:id","text":"

Response { \"chain\": { ... } }.

"},{"location":"api/settings/#post-apisettingsscript-chains","title":"POST /api/settings/script-chains","text":"
{\n  \"name\": \"After Encode\",\n  \"steps\": [\n    { \"stepType\": \"script\", \"scriptId\": 1 },\n    { \"stepType\": \"wait\", \"waitSeconds\": 15 },\n    { \"stepType\": \"script\", \"scriptId\": 2 }\n  ]\n}\n

Response: 201 mit { \"chain\": { ... } }

"},{"location":"api/settings/#put-apisettingsscript-chainsid","title":"PUT /api/settings/script-chains/:id","text":"

Body wie POST, Response { \"chain\": { ... } }.

"},{"location":"api/settings/#delete-apisettingsscript-chainsid","title":"DELETE /api/settings/script-chains/:id","text":"

Response { \"removed\": { ... } }.

"},{"location":"api/settings/#post-apisettingsscript-chainsreorder","title":"POST /api/settings/script-chains/reorder","text":"
{ \"orderedChainIds\": [2, 1, 3] }\n

Response { \"chains\": [ ... ] }.

"},{"location":"api/settings/#post-apisettingsscript-chainsidtest","title":"POST /api/settings/script-chains/:id/test","text":"

Response:

{\n  \"result\": {\n    \"chainId\": 2,\n    \"chainName\": \"After Encode\",\n    \"steps\": 3,\n    \"succeeded\": 3,\n    \"failed\": 0,\n    \"aborted\": false,\n    \"results\": []\n  }\n}\n
"},{"location":"api/settings/#user-presets","title":"User-Presets","text":"

Basis: /api/settings/user-presets

"},{"location":"api/settings/#get-apisettingsuser-presets","title":"GET /api/settings/user-presets","text":"

Optionaler Query-Parameter: media_type=bluray|dvd|other|all

{\n  \"presets\": [\n    {\n      \"id\": 1,\n      \"name\": \"Blu-ray HQ\",\n      \"mediaType\": \"bluray\",\n      \"handbrakePreset\": \"H.264 MKV 1080p30\",\n      \"extraArgs\": \"--encoder-preset slow\",\n      \"description\": \"...\",\n      \"createdAt\": \"...\",\n      \"updatedAt\": \"...\"\n    }\n  ]\n}\n
"},{"location":"api/settings/#post-apisettingsuser-presets","title":"POST /api/settings/user-presets","text":"
{\n  \"name\": \"Blu-ray HQ\",\n  \"mediaType\": \"bluray\",\n  \"handbrakePreset\": \"H.264 MKV 1080p30\",\n  \"extraArgs\": \"--encoder-preset slow\",\n  \"description\": \"optional\"\n}\n

Response: 201 mit { \"preset\": { ... } }

"},{"location":"api/settings/#put-apisettingsuser-presetsid","title":"PUT /api/settings/user-presets/:id","text":"

Body mit beliebigen Feldern aus POST, Response { \"preset\": { ... } }.

"},{"location":"api/settings/#delete-apisettingsuser-presetsid","title":"DELETE /api/settings/user-presets/:id","text":"

Response { \"removed\": { ... } }.

"},{"location":"api/websocket/","title":"WebSocket Events","text":"

Ripster sendet Echtzeit-Updates \u00fcber /ws.

"},{"location":"api/websocket/#verbindung","title":"Verbindung","text":"
const ws = new WebSocket('ws://localhost:3001/ws');\n\nws.onmessage = (event) => {\n  const msg = JSON.parse(event.data);\n  console.log(msg.type, msg.payload);\n};\n
"},{"location":"api/websocket/#nachrichtenformat","title":"Nachrichtenformat","text":"

Die meisten Broadcasts haben dieses Schema:

{\n  \"type\": \"EVENT_TYPE\",\n  \"payload\": {},\n  \"timestamp\": \"2026-03-10T09:00:00.000Z\"\n}\n

Ausnahme: WS_CONNECTED beim Verbindungsaufbau enth\u00e4lt kein timestamp.

"},{"location":"api/websocket/#event-typen","title":"Event-Typen","text":""},{"location":"api/websocket/#ws_connected","title":"WS_CONNECTED","text":"

Sofort nach erfolgreicher Verbindung.

{\n  \"type\": \"WS_CONNECTED\",\n  \"payload\": {\n    \"connectedAt\": \"2026-03-10T09:00:00.000Z\"\n  }\n}\n
"},{"location":"api/websocket/#pipeline_state_changed","title":"PIPELINE_STATE_CHANGED","text":"

Neuer Pipeline-Snapshot.

{\n  \"type\": \"PIPELINE_STATE_CHANGED\",\n  \"payload\": {\n    \"state\": \"ENCODING\",\n    \"activeJobId\": 42,\n    \"progress\": 62.5,\n    \"eta\": \"00:12:34\",\n    \"statusText\": \"ENCODING 62.50%\",\n    \"context\": {},\n    \"jobProgress\": {\n      \"42\": {\n        \"state\": \"ENCODING\",\n        \"progress\": 62.5,\n        \"eta\": \"00:12:34\",\n        \"statusText\": \"ENCODING 62.50%\"\n      }\n    },\n    \"queue\": {\n      \"maxParallelJobs\": 1,\n      \"runningCount\": 1,\n      \"queuedCount\": 2,\n      \"runningJobs\": [],\n      \"queuedJobs\": []\n    }\n  }\n}\n
"},{"location":"api/websocket/#pipeline_progress","title":"PIPELINE_PROGRESS","text":"

Laufende Fortschrittsupdates.

{\n  \"type\": \"PIPELINE_PROGRESS\",\n  \"payload\": {\n    \"state\": \"ENCODING\",\n    \"activeJobId\": 42,\n    \"progress\": 62.5,\n    \"eta\": \"00:12:34\",\n    \"statusText\": \"ENCODING 62.50%\"\n  }\n}\n
"},{"location":"api/websocket/#pipeline_queue_changed","title":"PIPELINE_QUEUE_CHANGED","text":"

Queue-Snapshot aktualisiert.

"},{"location":"api/websocket/#disc_detected-disc_removed","title":"DISC_DETECTED / DISC_REMOVED","text":"

Disc-Insertion/-Removal.

{\n  \"type\": \"DISC_DETECTED\",\n  \"payload\": {\n    \"device\": {\n      \"path\": \"/dev/sr0\",\n      \"discLabel\": \"INCEPTION\",\n      \"model\": \"ASUS BW-16D1HT\",\n      \"fstype\": \"udf\",\n      \"mountpoint\": null,\n      \"mediaProfile\": \"bluray\"\n    }\n  }\n}\n

mediaProfile: bluray | dvd | other | null

"},{"location":"api/websocket/#hardware_monitor_update","title":"HARDWARE_MONITOR_UPDATE","text":"

Snapshot aus Hardware-Monitoring.

{\n  \"type\": \"HARDWARE_MONITOR_UPDATE\",\n  \"payload\": {\n    \"enabled\": true,\n    \"intervalMs\": 5000,\n    \"updatedAt\": \"2026-03-10T09:00:00.000Z\",\n    \"sample\": {\n      \"cpu\": {},\n      \"memory\": {},\n      \"gpu\": {},\n      \"storage\": {}\n    },\n    \"error\": null\n  }\n}\n
"},{"location":"api/websocket/#pipeline_error","title":"PIPELINE_ERROR","text":"

Fehler bei Disc-Event-Verarbeitung in Pipeline.

"},{"location":"api/websocket/#disk_detection_error","title":"DISK_DETECTION_ERROR","text":"

Fehler in Laufwerkserkennung.

"},{"location":"api/websocket/#settings_updated","title":"SETTINGS_UPDATED","text":"

Einzelnes Setting wurde gespeichert.

"},{"location":"api/websocket/#settings_bulk_updated","title":"SETTINGS_BULK_UPDATED","text":"

Bulk-Settings gespeichert.

{\n  \"type\": \"SETTINGS_BULK_UPDATED\",\n  \"payload\": {\n    \"count\": 3,\n    \"keys\": [\"raw_dir\", \"movie_dir\", \"handbrake_preset_bluray\"]\n  }\n}\n
"},{"location":"api/websocket/#settings_scripts_updated","title":"SETTINGS_SCRIPTS_UPDATED","text":"

Skript ge\u00e4ndert (created|updated|deleted|reordered).

"},{"location":"api/websocket/#settings_script_chains_updated","title":"SETTINGS_SCRIPT_CHAINS_UPDATED","text":"

Skript-Kette ge\u00e4ndert (created|updated|deleted|reordered).

"},{"location":"api/websocket/#user_presets_updated","title":"USER_PRESETS_UPDATED","text":"

User-Preset ge\u00e4ndert (created|updated|deleted).

"},{"location":"api/websocket/#cron_jobs_updated","title":"CRON_JOBS_UPDATED","text":"

Cron-Config ge\u00e4ndert (created|updated|deleted).

"},{"location":"api/websocket/#cron_job_updated","title":"CRON_JOB_UPDATED","text":"

Laufzeitstatus eines Cron-Jobs ge\u00e4ndert.

{\n  \"type\": \"CRON_JOB_UPDATED\",\n  \"payload\": {\n    \"id\": 1,\n    \"lastRunStatus\": \"running\",\n    \"lastRunAt\": \"2026-03-10T10:00:00.000Z\",\n    \"nextRunAt\": null\n  }\n}\n
"},{"location":"api/websocket/#runtime_activity_changed","title":"RUNTIME_ACTIVITY_CHANGED","text":"

Vollst\u00e4ndiger Snapshot aller laufenden und k\u00fcrzlich abgeschlossenen Aktivit\u00e4ten.

Wird ausgel\u00f6st, wenn eine Aktivit\u00e4t gestartet, aktualisiert oder abgeschlossen wird sowie nach clear-recent.

{\n  \"type\": \"RUNTIME_ACTIVITY_CHANGED\",\n  \"payload\": {\n    \"active\": [\n      {\n        \"id\": 7,\n        \"type\": \"chain\",\n        \"name\": \"Post-Encode Aufr\u00e4umen\",\n        \"status\": \"running\",\n        \"source\": \"cron\",\n        \"message\": \"Schritt 2 von 3\",\n        \"currentStep\": \"cleanup.sh\",\n        \"currentStepType\": \"script\",\n        \"stepIndex\": 2,\n        \"stepTotal\": 3,\n        \"canCancel\": true,\n        \"canNextStep\": false,\n        \"outcome\": \"running\",\n        \"startedAt\": \"2026-03-10T10:00:00.000Z\",\n        \"finishedAt\": null,\n        \"durationMs\": null\n      }\n    ],\n    \"recent\": [],\n    \"updatedAt\": \"2026-03-10T10:00:05.000Z\"\n  }\n}\n

Vollst\u00e4ndige Feldbeschreibung: Runtime Activities API.

"},{"location":"api/websocket/#reconnect-verhalten","title":"Reconnect-Verhalten","text":"

useWebSocket verbindet bei Abbruch automatisch neu:

"},{"location":"appendix/","title":"Technischer Anhang","text":"

Dieser Bereich enth\u00e4lt die technische Referenz hinter dem Benutzerhandbuch.

"},{"location":"appendix/#inhalt","title":"Inhalt","text":""},{"location":"appendix/#wann-du-in-den-anhang-wechselst","title":"Wann du in den Anhang wechselst","text":""},{"location":"architecture/","title":"Anhang: Architektur","text":"

Ripster ist eine Client-Server-Anwendung mit REST + WebSocket und externen CLI-Tools.

"},{"location":"architecture/#systemuberblick","title":"System\u00fcberblick","text":"
graph TB\n    subgraph Browser[\"Browser (React)\"]\n        Dashboard[Dashboard]\n        Settings[Einstellungen]\n        History[Historie]\n    end\n\n    subgraph Backend[\"Node.js Backend\"]\n        API[REST API\\nExpress]\n        WS[WebSocket\\n/ws]\n        Pipeline[pipelineService]\n        Cron[cronService]\n        DB[(SQLite)]\n    end\n\n    subgraph Tools[\"Externe Tools\"]\n        MakeMKV[makemkvcon]\n        HandBrake[HandBrakeCLI]\n        MediaInfo[mediainfo]\n    end\n\n    Browser <-->|HTTP| API\n    Browser <-->|WebSocket| WS\n    Pipeline --> MakeMKV\n    Pipeline --> HandBrake\n    Pipeline --> MediaInfo\n    API --> DB\n    Pipeline --> DB\n    Cron --> DB
"},{"location":"architecture/#details","title":"Details","text":""},{"location":"architecture/backend/","title":"Backend-Services","text":"

Das Backend ist in Services aufgeteilt, die von Express-Routen orchestriert werden.

"},{"location":"architecture/backend/#pipelineservicejs","title":"pipelineService.js","text":"

Zentrale Workflow-Orchestrierung.

Aufgaben:

Wichtige Methoden:

"},{"location":"architecture/backend/#diskdetectionservicejs","title":"diskDetectionService.js","text":"

Pollt Laufwerk(e) und emittiert:

Zusatz:

"},{"location":"architecture/backend/#settingsservicejs","title":"settingsService.js","text":"

Settings-Layer mit Validation/Serialisierung.

Features:

"},{"location":"architecture/backend/#historyservicejs","title":"historyService.js","text":"

Historie + Dateioperationen.

Features:

"},{"location":"architecture/backend/#cronservicejs","title":"cronService.js","text":"

Integriertes Cron-System ohne externe Parser-Library.

Features:

"},{"location":"architecture/backend/#runtimeactivityservicejs","title":"runtimeActivityService.js","text":"

In-Memory-Tracking aller laufenden und k\u00fcrzlich abgeschlossenen Aktivit\u00e4ten (Skripte, Ketten, Cron-Jobs, Tasks).

Features:

Limits:

Vollst\u00e4ndige API-Dokumentation: Runtime Activities API

"},{"location":"architecture/backend/#weitere-services","title":"Weitere Services","text":""},{"location":"architecture/backend/#bootstrapping-srcindexjs","title":"Bootstrapping (src/index.js)","text":"

Beim Start:

  1. DB init/migrate
  2. Pipeline-Init
  3. Cron-Init
  4. Express-Routes + Error-Handler
  5. WebSocket-Server auf /ws
  6. Hardware-Monitoring-Init
  7. Disk-Detection-Start
"},{"location":"architecture/database/","title":"Datenbank","text":"

Ripster verwendet SQLite (backend/data/ripster.db).

"},{"location":"architecture/database/#tabellen","title":"Tabellen","text":"
settings_schema\nsettings_values\njobs\npipeline_state\nscripts\nscript_chains\nscript_chain_steps\nuser_presets\ncron_jobs\ncron_run_logs\n
"},{"location":"architecture/database/#jobs","title":"jobs","text":"

Speichert Pipeline-Lifecycle und Artefakte pro Job.

Zentrale Felder:

"},{"location":"architecture/database/#pipeline_state","title":"pipeline_state","text":"

Singleton-Tabelle (id = 1) f\u00fcr aktiven Snapshot:

"},{"location":"architecture/database/#settings_schema-settings_values","title":"settings_schema + settings_values","text":""},{"location":"architecture/database/#scripts-script_chains-script_chain_steps","title":"scripts, script_chains, script_chain_steps","text":""},{"location":"architecture/database/#user_presets","title":"user_presets","text":"

Benannte HandBrake-Preset-Sets:

"},{"location":"architecture/database/#cron_jobs-cron_run_logs","title":"cron_jobs + cron_run_logs","text":""},{"location":"architecture/database/#migrationrecovery","title":"Migration/Recovery","text":"

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
"},{"location":"architecture/database/#direkte-inspektion","title":"Direkte Inspektion","text":"
sqlite3 backend/data/ripster.db\n\n.mode table\nSELECT id, status, title, created_at FROM jobs ORDER BY created_at DESC;\nSELECT key, value FROM settings_values ORDER BY key;\n
"},{"location":"architecture/frontend/","title":"Frontend-Komponenten","text":"

Frontend: React + PrimeReact + Vite.

"},{"location":"architecture/frontend/#hauptseiten","title":"Hauptseiten","text":""},{"location":"architecture/frontend/#dashboardpagejsx","title":"DashboardPage.jsx","text":"

Pipeline-Steuerung:

"},{"location":"architecture/frontend/#settingspagejsx","title":"SettingsPage.jsx","text":"

Konfiguration:

"},{"location":"architecture/frontend/#historypagejsx","title":"HistoryPage.jsx","text":"

Historie:

"},{"location":"architecture/frontend/#wichtige-komponenten","title":"Wichtige Komponenten","text":""},{"location":"architecture/frontend/#api-client-apiclientjs","title":"API-Client (api/client.js)","text":""},{"location":"architecture/frontend/#websocket-hooksusewebsocketjs","title":"WebSocket (hooks/useWebSocket.js)","text":"

In App.jsx werden u. a. verarbeitet:

"},{"location":"architecture/frontend/#buildrun","title":"Build/Run","text":"
# dev\nnpm run dev --prefix frontend\n\n# prod build\nnpm run build --prefix frontend\n
"},{"location":"architecture/overview/","title":"Architektur-\u00dcbersicht","text":""},{"location":"architecture/overview/#kernprinzipien","title":"Kernprinzipien","text":""},{"location":"architecture/overview/#event-getriebene-pipeline","title":"Event-getriebene Pipeline","text":"

pipelineService h\u00e4lt einen Snapshot der State-Machine und broadcastet \u00c4nderungen sofort via WebSocket.

State-\u00c4nderung -> PIPELINE_STATE_CHANGED/PIPELINE_PROGRESS -> Frontend-Update\n
"},{"location":"architecture/overview/#service-layer","title":"Service-Layer","text":"
Route -> Service -> DB/Tool-Execution\n

Routes enthalten kaum Business-Logik.

"},{"location":"architecture/overview/#schema-getriebene-settings","title":"Schema-getriebene Settings","text":"

Settings sind DB-schema-getrieben (settings_schema + settings_values), UI rendert dynamisch aus diesen Daten.

"},{"location":"architecture/overview/#echtzeit-kommunikation","title":"Echtzeit-Kommunikation","text":"

WebSocket l\u00e4uft auf /ws.

Wichtige Events:

"},{"location":"architecture/overview/#prozessausfuhrung","title":"Prozessausf\u00fchrung","text":"

Externe Tools werden als Child-Processes gestartet (processRunner):

"},{"location":"architecture/overview/#persistenz","title":"Persistenz","text":"

SQLite-Datei: backend/data/ripster.db

Kern-Tabellen:

Beim Start werden Schema und Settings-Migrationen automatisch ausgef\u00fchrt.

"},{"location":"architecture/overview/#fehlerbehandlung","title":"Fehlerbehandlung","text":"

Zentrales Error-Handling liefert:

{\n  \"error\": {\n    \"message\": \"...\",\n    \"statusCode\": 400,\n    \"reqId\": \"...\",\n    \"details\": []\n  }\n}\n

Fehlgeschlagene Jobs bleiben in der Historie (Fehler oder Abgebrochen) und k\u00f6nnen erneut gestartet werden.

"},{"location":"architecture/overview/#cors-runtime-konfig","title":"CORS & Runtime-Konfig","text":""},{"location":"configuration/","title":"Anhang: Konfiguration","text":"

Dieser Abschnitt ist die technische Referenz zu allen Konfigurationsarten in Ripster.

"},{"location":"configuration/#inhalte","title":"Inhalte","text":""},{"location":"configuration/#zuruck-zum-handbuch","title":"Zur\u00fcck zum Handbuch","text":""},{"location":"configuration/environment/","title":"Umgebungsvariablen","text":"

Umgebungsvariablen steuern Backend/Vite au\u00dferhalb der DB-basierten UI-Settings.

"},{"location":"configuration/environment/#backend-backendenv","title":"Backend (backend/.env)","text":"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\u00fcr API LOG_LEVEL info debug, info, warn, error

Beispiel:

PORT=3001\nDB_PATH=/var/lib/ripster/ripster.db\nLOG_DIR=/var/log/ripster\nCORS_ORIGIN=http://192.168.1.50:5173\nLOG_LEVEL=info\n

Hinweis: backend/.env.example enth\u00e4lt bewusst dev-freundliche Werte (z. B. lokaler CORS_ORIGIN).

"},{"location":"configuration/environment/#frontend-frontendenv","title":"Frontend (frontend/.env)","text":"Variable Default Beschreibung VITE_API_BASE /api API-Basis f\u00fcr Fetch-Client VITE_WS_URL automatisch aus window.location + /ws Optional explizite WebSocket-URL VITE_PUBLIC_ORIGIN leer \u00d6ffentliche Vite-Origin (Remote-Dev) VITE_ALLOWED_HOSTS true Komma-separierte Hostliste f\u00fcr 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:

# lokal (mit Vite-Proxy)\nVITE_API_BASE=/api\n
# remote dev\nVITE_API_BASE=http://192.168.1.50:3001/api\nVITE_WS_URL=ws://192.168.1.50:3001/ws\nVITE_PUBLIC_ORIGIN=http://192.168.1.50:5173\nVITE_ALLOWED_HOSTS=192.168.1.50,ripster.local\nVITE_HMR_PROTOCOL=ws\nVITE_HMR_HOST=192.168.1.50\nVITE_HMR_CLIENT_PORT=5173\n
"},{"location":"configuration/environment/#prioritat","title":"Priorit\u00e4t","text":"
  1. Prozess-Umgebungsvariablen
  2. .env
  3. Code-Defaults
"},{"location":"configuration/settings-reference/","title":"Einstellungsreferenz","text":"

Diese Seite listet die Felder so, wie sie in der GUI unter Settings angezeigt werden.

Hinweis: Interne Schl\u00fcsselnamen werden hier bewusst nicht verwendet. Falls du sie f\u00fcr Integrationen brauchst, nutze die API-Dokumentation.

"},{"location":"configuration/settings-reference/#profil-system","title":"Profil-System","text":"

Viele Felder sind pro Medientyp getrennt vorhanden:

"},{"location":"configuration/settings-reference/#template-platzhalter","title":"Template-Platzhalter","text":"

Datei-/Ordner-Templates unterst\u00fctzen:

Nicht gesetzte Werte werden zu unknown.

"},{"location":"configuration/settings-reference/#kategorie-pfade","title":"Kategorie: Pfade","text":"Feldname in der GUI Typ Default Raw Ausgabeordner path data/output/raw Raw Ausgabeordner (Blu-ray) path null Raw Ausgabeordner (DVD) path null Raw Ausgabeordner (Sonstiges) path null Eigent\u00fcmer Raw-Ordner (Blu-ray) string null Eigent\u00fcmer Raw-Ordner (DVD) string null Eigent\u00fcmer Raw-Ordner (Sonstiges) string null Film Ausgabeordner path data/output/movies Film Ausgabeordner (Blu-ray) path null Film Ausgabeordner (DVD) path null Film Ausgabeordner (Sonstiges) path null Eigent\u00fcmer Film-Ordner (Blu-ray) string null Eigent\u00fcmer Film-Ordner (DVD) string null Eigent\u00fcmer Film-Ordner (Sonstiges) string null Log Ordner path data/logs"},{"location":"configuration/settings-reference/#kategorie-laufwerk","title":"Kategorie: Laufwerk","text":"Feldname in der GUI Typ Default Hinweis Laufwerksmodus select auto Auto Discovery oder Explizites Device Device Pfad path /dev/sr0 relevant bei Explizites Device MakeMKV Source Index number 0 Disc-Index im Auto-Modus Polling Intervall (ms) number 4000 1000..60000"},{"location":"configuration/settings-reference/#kategorie-monitoring","title":"Kategorie: Monitoring","text":"Feldname in der GUI Typ Default Hardware Monitoring aktiviert boolean true Hardware Monitoring Intervall (ms) number 5000"},{"location":"configuration/settings-reference/#kategorie-tools-global","title":"Kategorie: Tools (global)","text":"Feldname in der GUI Typ Default MakeMKV Kommando string makemkvcon MakeMKV Key string null Mediainfo Kommando string mediainfo Minimale Titellaenge (Minuten) number 60 HandBrake Kommando string HandBrakeCLI Encode-Neustart: unvollst\u00e4ndige Ausgabe l\u00f6schen boolean true Parallele Jobs number 1"},{"location":"configuration/settings-reference/#blu-ray-spezifisch","title":"Blu-ray-spezifisch","text":"Feldname in der GUI Typ Default Mediainfo Extra Args (Blu-ray) string null MakeMKV Rip Modus (Blu-ray) select backup MakeMKV Analyze Extra Args (Blu-ray) string null MakeMKV Rip Extra Args (Blu-ray) string null HandBrake Preset (Blu-ray) string H.264 MKV 1080p30 HandBrake Extra Args (Blu-ray) string null Ausgabeformat (Blu-ray) select mkv Dateiname Template (Blu-ray) string ${title} (${year}) Ordnername Template (Blu-ray) string null"},{"location":"configuration/settings-reference/#dvd-spezifisch","title":"DVD-spezifisch","text":"Feldname in der GUI Typ Default Mediainfo Extra Args (DVD) string null MakeMKV Rip Modus (DVD) select mkv MakeMKV Analyze Extra Args (DVD) string null MakeMKV Rip Extra Args (DVD) string null HandBrake Preset (DVD) string H.264 MKV 480p30 HandBrake Extra Args (DVD) string null Ausgabeformat (DVD) select mkv Dateiname Template (DVD) string ${title} (${year}) Ordnername Template (DVD) string null"},{"location":"configuration/settings-reference/#kategorie-metadaten","title":"Kategorie: Metadaten","text":"Feldname in der GUI Typ Default OMDb API Key string null OMDb Typ select movie"},{"location":"configuration/settings-reference/#kategorie-benachrichtigungen-pushover","title":"Kategorie: Benachrichtigungen (PushOver)","text":"Feldname in der GUI Typ Default PushOver aktiviert boolean false PushOver Token string null PushOver User string null PushOver Device (optional) string null PushOver Titel-Pr\u00e4fix string Ripster PushOver Priority number 0 PushOver Timeout (ms) number 7000 Bei Metadaten-Auswahl senden boolean true Bei Rip-Start senden boolean true Bei Encode-Start senden boolean true Bei Erfolg senden boolean true Bei Fehler senden boolean true Bei Abbruch senden boolean true Bei Re-Encode Start senden boolean true Bei Re-Encode Erfolg senden boolean true"},{"location":"deployment/","title":"Anhang: Deployment","text":"

Technische Betriebsdokumentation f\u00fcr Entwicklung und Produktion.

"},{"location":"deployment/development/","title":"Entwicklungsumgebung","text":""},{"location":"deployment/development/#voraussetzungen","title":"Voraussetzungen","text":""},{"location":"deployment/development/#schnellstart","title":"Schnellstart","text":"
./start.sh\n

Startet:

Stoppen: Ctrl+C.

"},{"location":"deployment/development/#manuell","title":"Manuell","text":""},{"location":"deployment/development/#backend","title":"Backend","text":"
cd backend\nnpm install\nnpm run dev\n
"},{"location":"deployment/development/#frontend","title":"Frontend","text":"
cd frontend\nnpm install\nnpm run dev\n
"},{"location":"deployment/development/#vite-proxy-dev","title":"Vite-Proxy (Dev)","text":"

frontend/vite.config.js proxied standardm\u00e4\u00dfig:

"},{"location":"deployment/development/#remote-dev-optional","title":"Remote-Dev (optional)","text":"

Beispiel frontend/.env.local:

VITE_API_BASE=http://192.168.1.100:3001/api\nVITE_WS_URL=ws://192.168.1.100:3001/ws\nVITE_PUBLIC_ORIGIN=http://192.168.1.100:5173\nVITE_ALLOWED_HOSTS=192.168.1.100,ripster.local\nVITE_HMR_PROTOCOL=ws\nVITE_HMR_HOST=192.168.1.100\nVITE_HMR_CLIENT_PORT=5173\n
"},{"location":"deployment/development/#nutzliche-kommandos","title":"N\u00fctzliche Kommandos","text":"
# Root dev (backend + frontend)\nnpm run dev\n\n# einzeln\nnpm run dev:backend\nnpm run dev:frontend\n\n# Frontend Build\nnpm run build:frontend\n
"},{"location":"deployment/production/","title":"Produktions-Deployment","text":""},{"location":"deployment/production/#automatische-installation-empfohlen","title":"Automatische Installation (empfohlen)","text":"

Das mitgelieferte install.sh richtet Ripster vollautomatisch ein \u2013 inklusive Node.js, MakeMKV, HandBrake, nginx und systemd-Dienst.

Unterst\u00fctzte Systeme laut Script: Debian, Ubuntu, Linux Mint, Pop!_OS Voraussetzung: root-Rechte, Internetzugang

"},{"location":"deployment/production/#schnellstart-via-curl","title":"Schnellstart via curl","text":"
curl -fsSL https://raw.githubusercontent.com/Mboehmlaender/ripster/main/install.sh | sudo bash\n

Oder mit wget:

wget -qO- https://raw.githubusercontent.com/Mboehmlaender/ripster/main/install.sh | sudo bash\n

Optionen nur via Datei

Beim Pipen von curl/wget k\u00f6nnen keine Argumente \u00fcbergeben werden. F\u00fcr benutzerdefinierte Optionen zuerst herunterladen und dann mit sudo bash install.sh [Optionen] ausf\u00fchren.

"},{"location":"deployment/production/#optionen","title":"Optionen","text":"Option Standard Beschreibung --branch <branch> dev Git-Branch f\u00fcr die Installation --dir <pfad> /opt/ripster Installationsverzeichnis --user <benutzer> ripster Systembenutzer f\u00fcr den Dienst --port <port> 3001 Backend-Port --host <hostname> Auto (Maschinen-IP) Hostname/IP f\u00fcr die Weboberfl\u00e4che --no-makemkv \u2013 MakeMKV-Installation \u00fcberspringen --no-handbrake \u2013 HandBrake-Installation \u00fcberspringen --no-nginx \u2013 nginx-Einrichtung \u00fcberspringen --reinstall \u2013 Bestehende Installation aktualisieren (Daten bleiben erhalten) -h, --help \u2013 Hilfe anzeigen"},{"location":"deployment/production/#beispiele","title":"Beispiele","text":"
# Standard-Installation\nsudo bash install.sh\n\n# Anderen Branch und Port verwenden\nsudo bash install.sh --branch dev --port 8080\n\n# Ohne MakeMKV (bereits installiert)\nsudo bash install.sh --no-makemkv\n\n# Bestehende Installation aktualisieren\nsudo bash install.sh --reinstall\n\n# Ohne nginx (eigener Reverse-Proxy)\nsudo bash install.sh --no-nginx --host mein-server.local\n
"},{"location":"deployment/production/#was-das-skript-erledigt","title":"Was das Skript erledigt","text":"
  1. Systempr\u00fcfung \u2013 OS-Erkennung und Root-Check
  2. Systempakete \u2013 curl, wget, git, mediainfo, udev u. a.
  3. Node.js 20 \u2013 via NodeSource, falls noch nicht installiert
  4. MakeMKV \u2013 aktuelle Version wird aus dem offiziellen Forum ermittelt und aus dem Quellcode kompiliert (kann mit --no-makemkv \u00fcbersprungen werden)
  5. HandBrake \u2013 interaktive Auswahl:
  6. Systembenutzer ripster \u2013 ohne Login-Shell und ohne Home-Verzeichnis; Gruppen werden (falls vorhanden) erg\u00e4nzt: cdrom, optical, disk, video, render
  7. Repository \u2013 klont Branch nach --dir (bei --reinstall: sichert backend/data, aktualisiert Repo, stellt Daten wieder her)
  8. Verzeichnisse \u2013 stellt u. a. sicher: backend/data, backend/logs, backend/data/output/raw, backend/data/output/movies, backend/data/logs
  9. npm-Abh\u00e4ngigkeiten \u2013 Root, Backend (nur production), Frontend
  10. Frontend-Build \u2013 npm run build mit relativen API-URLs (nginx-kompatibel)
  11. Backend .env \u2013 wird automatisch generiert (bei --reinstall bleibt bestehende .env erhalten)
  12. Berechtigungen \u2013 zun\u00e4chst 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 \u2013 erstellt bei sudo-Aufruf ~/.MakeMKV f\u00fcr den aufrufenden Benutzer
  14. systemd-Dienst \u2013 ripster-backend.service erstellt, aktiviert und gestartet
  15. nginx \u2013 konfiguriert als Reverse-Proxy f\u00fcr Frontend, /api/ und /ws (kann mit --no-nginx \u00fcbersprungen werden)
"},{"location":"deployment/production/#nach-der-installation","title":"Nach der Installation","text":"
# Status pr\u00fcfen\nsudo systemctl status ripster-backend\n\n# Logs verfolgen\nsudo journalctl -u ripster-backend -f\n\n# Neustart\nsudo systemctl restart ripster-backend\n\n# Aktualisieren\nsudo bash /opt/ripster/install.sh --reinstall\n

Zugriff: http://<Maschinen-IP> (oder der mit --host angegebene Hostname)

"},{"location":"deployment/production/#handbrake-modus-gpunvdec","title":"HandBrake-Modus (GPU/NVDEC)","text":"

Bei nicht-interaktiver Ausf\u00fchrung (Pipe von curl) wird automatisch die Standard-Version gew\u00e4hlt. F\u00fcr die GPU-Version zuerst herunterladen:

curl -fsSL https://raw.githubusercontent.com/Mboehmlaender/ripster/main/install.sh -o install.sh\nsudo bash install.sh\n# \u2192 Interaktive Auswahl: Option 2 f\u00fcr NVDEC\n

Das geb\u00fcndelte Binary liegt unter bin/HandBrakeCLI und wird nach /usr/local/bin/HandBrakeCLI kopiert.

"},{"location":"deployment/production/#manuelle-installation","title":"Manuelle Installation","text":"

Die folgenden Abschnitte beschreiben die einzelnen Schritte f\u00fcr manuelle oder angepasste Setups.

"},{"location":"deployment/production/#empfohlene-architektur","title":"Empfohlene Architektur","text":"
Client\n  -> nginx (Reverse Proxy + statisches Frontend)\n    -> Backend API/WebSocket (Node.js, Port 3001)\n

Wichtig: Das Backend serviert im aktuellen Stand keine frontend/dist-Dateien automatisch.

"},{"location":"deployment/production/#1-frontend-builden","title":"1) Frontend builden","text":"
cd frontend\nnpm install\nnpm run build\n

Artefakte liegen in frontend/dist/.

"},{"location":"deployment/production/#2-backend-als-systemd-service","title":"2) Backend als systemd-Service","text":"

Beispiel /etc/systemd/system/ripster-backend.service:

[Unit]\nDescription=Ripster Backend\nAfter=network.target\n\n[Service]\nType=simple\nUser=ripster\nWorkingDirectory=/opt/ripster/backend\nExecStart=/usr/bin/env node src/index.js\nRestart=on-failure\nRestartSec=5\nEnvironment=NODE_ENV=production\nEnvironment=PORT=3001\nEnvironment=LOG_LEVEL=info\n\n[Install]\nWantedBy=multi-user.target\n

Aktivieren:

sudo systemctl daemon-reload\nsudo systemctl enable --now ripster-backend\nsudo systemctl status ripster-backend\n
"},{"location":"deployment/production/#3-nginx-konfigurieren","title":"3) nginx konfigurieren","text":"

Beispiel /etc/nginx/sites-available/ripster:

server {\n    listen 80;\n    server_name ripster.local;\n\n    root /opt/ripster/frontend/dist;\n    index index.html;\n\n    location / {\n        try_files $uri $uri/ /index.html;\n    }\n\n    location /api/ {\n        proxy_pass http://127.0.0.1:3001;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n    }\n\n    location /ws {\n        proxy_pass http://127.0.0.1:3001;\n        proxy_http_version 1.1;\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection \"upgrade\";\n        proxy_set_header Host $host;\n    }\n}\n

Aktivieren:

sudo ln -s /etc/nginx/sites-available/ripster /etc/nginx/sites-enabled/\nsudo nginx -t\nsudo systemctl reload nginx\n
"},{"location":"deployment/production/#datenbank-backup","title":"Datenbank-Backup","text":"
sqlite3 /opt/ripster/backend/data/ripster.db \\\n  \".backup '/var/backups/ripster-$(date +%Y%m%d).db'\"\n
"},{"location":"deployment/production/#sicherheit","title":"Sicherheit","text":""},{"location":"getting-started/","title":"Benutzerhandbuch \u00dcberblick","text":"

Dieses Kapitel ist f\u00fcr den Betrieb von Ripster im Alltag geschrieben.

"},{"location":"getting-started/#zielgruppe","title":"Zielgruppe","text":""},{"location":"getting-started/#kapitelstruktur","title":"Kapitelstruktur","text":"Kapitel Zweck Voraussetzungen Produktions- vs. Dev-Voraussetzungen klar trennen Installation Ripster aufsetzen und starten Ersteinrichtung Pfade, Tools und Metadaten korrekt setzen Erster Lauf Ein kompletter Job von Disc bis Datei GUI-Seiten Alle Ansichten und Aktionen im Detail Workflows Typische Abl\u00e4ufe und Entscheidungen aus User-Sicht"},{"location":"getting-started/#wenn-du-neu-startest","title":"Wenn du neu startest","text":"
  1. Voraussetzungen
  2. Installation
  3. Ersteinrichtung
  4. Erster Lauf
"},{"location":"getting-started/#wenn-ripster-bereits-lauft","title":"Wenn Ripster bereits l\u00e4uft","text":"
  1. GUI-Seiten
  2. Workflows
  3. Bei Detailfragen: Technischer Anhang
"},{"location":"getting-started/configuration/","title":"Ersteinrichtung","text":"

Nach der Installation erfolgt die t\u00e4gliche Konfiguration fast vollst\u00e4ndig in der GUI unter Settings.

"},{"location":"getting-started/configuration/#ziel","title":"Ziel","text":"

Vor dem ersten echten Job m\u00fcssen Pfade, Tools und Metadatenzugriff sauber gesetzt sein.

"},{"location":"getting-started/configuration/#reihenfolge-empfohlen","title":"Reihenfolge (empfohlen)","text":""},{"location":"getting-started/configuration/#1-settings-tab-konfiguration","title":"1. Settings -> Tab Konfiguration","text":"

Setze zuerst diese Pflichtwerte:

Bereich Wichtige Felder Pfade Raw Ausgabeordner, Film Ausgabeordner, Log Ordner Tools MakeMKV Kommando, HandBrake Kommando, Mediainfo Kommando Metadaten OMDb API Key, optional OMDb Typ

Danach \u00c4nderungen speichern.

"},{"location":"getting-started/configuration/#2-medienprofile-prufen","title":"2. Medienprofile pr\u00fcfen","text":"

Wenn du Blu-ray und DVD unterschiedlich behandeln willst, pflege die profilbezogenen Felder:

Typische Beispiele:

"},{"location":"getting-started/configuration/#3-queue-und-monitoring-festlegen","title":"3. Queue und Monitoring festlegen","text":""},{"location":"getting-started/configuration/#4-optional-push-benachrichtigungen","title":"4. Optional: Push-Benachrichtigungen","text":"

In den Benachrichtigungsfeldern setzen:

Dann \u00fcber PushOver Test direkt pr\u00fcfen.

"},{"location":"getting-started/configuration/#2-minuten-funktionstest","title":"2-Minuten-Funktionstest","text":"
  1. Dashboard \u00f6ffnen
  2. Disc einlegen
  3. Analyse starten
  4. Metadaten \u00fcbernehmen
  5. Bis Bereit zum Encodieren laufen lassen

Wenn diese Schritte funktionieren, ist die Grundkonfiguration korrekt.

"},{"location":"getting-started/configuration/#wenn-werte-nicht-gespeichert-werden","title":"Wenn Werte nicht gespeichert werden","text":""},{"location":"getting-started/configuration/#weiter","title":"Weiter","text":""},{"location":"getting-started/installation/","title":"Installation","text":"

Die empfohlene Installation l\u00e4uft \u00fcber install.sh und richtet Ripster vollst\u00e4ndig ein.

Du musst daf\u00fcr keine Tools manuell vorinstallieren. Das Skript installiert die ben\u00f6tigten Abh\u00e4ngigkeiten automatisch, sofern sie nicht explizit mit --no-* \u00fcbersprungen werden.

"},{"location":"getting-started/installation/#unterstutzte-systeme-und-anforderungen","title":"Unterst\u00fctzte Systeme und Anforderungen","text":""},{"location":"getting-started/installation/#schritt-fur-schritt","title":"Schritt-f\u00fcr-Schritt","text":""},{"location":"getting-started/installation/#1-installationsskript-herunterladen","title":"1. Installationsskript herunterladen","text":"
wget -qO install.sh https://raw.githubusercontent.com/Mboehmlaender/ripster/main/install.sh\n
"},{"location":"getting-started/installation/#2-installation-ausfuhren","title":"2. Installation ausf\u00fchren","text":"
sudo bash install.sh\n

W\u00e4hrend der Installation w\u00e4hlst du den HandBrake-Modus:

"},{"location":"getting-started/installation/#3-dienststatus-prufen","title":"3. Dienststatus pr\u00fcfen","text":"
sudo systemctl status ripster-backend\n
"},{"location":"getting-started/installation/#4-weboberflache-offnen","title":"4. Weboberfl\u00e4che \u00f6ffnen","text":""},{"location":"getting-started/installation/#was-installsh-konkret-einrichtet","title":"Was install.sh konkret einrichtet","text":"
  1. pr\u00fcft Betriebssystem, Root-Rechte und ermittelt Host/IP
  2. aktualisiert Paketquellen und installiert Basispakete (curl, wget, git, mediainfo, udev ...)
  3. installiert Node.js 20 (falls nicht passend vorhanden)
  4. installiert optional MakeMKV (Build aus den offiziellen Quellen)
  5. installiert optional HandBrakeCLI (Standard oder GPU/NVDEC)
  6. installiert optional nginx
  7. legt den Systembenutzer ripster an (ohne Login-Shell, ohne Home) und erg\u00e4nzt Gruppen (cdrom, optical, disk, video, render, falls vorhanden)
  8. klont das Repository nach /opt/ripster (oder aktualisiert bei --reinstall)
  9. legt Verzeichnisse an:
  10. /opt/ripster/backend/data
  11. /opt/ripster/backend/logs
  12. /opt/ripster/backend/data/output/raw
  13. /opt/ripster/backend/data/output/movies
  14. /opt/ripster/backend/data/logs
  15. installiert npm-Abh\u00e4ngigkeiten (Root, Backend, Frontend) und baut das Frontend
  16. erzeugt backend/.env (bei --reinstall bleibt bestehende .env erhalten)
  17. setzt Rechte/Besitz und erstellt bei sudo-Installation zus\u00e4tzlich ~/.MakeMKV f\u00fcr den aufrufenden Benutzer
  18. erzeugt und startet ripster-backend.service
  19. konfiguriert und startet nginx (falls nicht \u00fcbersprungen)
"},{"location":"getting-started/installation/#wichtige-optionen","title":"Wichtige Optionen","text":"Option Default laut Script Zweck --branch <branch> dev Branch f\u00fcr die Installation --dir <pfad> /opt/ripster Installationsverzeichnis --user <benutzer> ripster Service-Benutzer --port <port> 3001 Backend-Port --host <hostname> automatisch ermittelte Host-IP Hostname/IP f\u00fcr Webzugriff/CORS --no-makemkv aus MakeMKV-Installation \u00fcberspringen --no-handbrake aus HandBrake-Installation \u00fcberspringen --no-nginx aus nginx-Setup \u00fcberspringen --reinstall aus bestehende Installation aktualisieren

Beispiele:

sudo bash install.sh --branch dev\nsudo bash install.sh --port 8080 --host ripster.local\nsudo bash install.sh --reinstall\n
"},{"location":"getting-started/installation/#betrieb-im-alltag","title":"Betrieb im Alltag","text":"
# Logs live ansehen\nsudo journalctl -u ripster-backend -f\n\n# Dienst neu starten\nsudo systemctl restart ripster-backend\n\n# Update aus bestehender Installation\nsudo bash /opt/ripster/install.sh --reinstall\n
"},{"location":"getting-started/installation/#haufige-stolperstellen","title":"H\u00e4ufige Stolperstellen","text":""},{"location":"getting-started/installation/#danach-weiter","title":"Danach weiter","text":"
  1. Ersteinrichtung
  2. Erster Lauf
"},{"location":"getting-started/prerequisites/","title":"Voraussetzungen","text":"

Die Voraussetzungen h\u00e4ngen davon ab, wie du Ripster betreibst.

"},{"location":"getting-started/prerequisites/#produktionsbetrieb-mit-installsh-standard","title":"Produktionsbetrieb mit install.sh (Standard)","text":"

F\u00fcr den normalen Betrieb sind nur wenige Punkte vorab n\u00f6tig.

"},{"location":"getting-started/prerequisites/#pflicht","title":"Pflicht","text":"

install.sh installiert die ben\u00f6tigten Tools selbst (u. a. Node.js, MakeMKV, HandBrakeCLI, MediaInfo), sofern sie nicht explizit per --no-* \u00fcbersprungen werden.

"},{"location":"getting-started/prerequisites/#laufwerk-kurz-prufen","title":"Laufwerk kurz pr\u00fcfen","text":"
ls /dev/sr*\nlsblk | grep rom\n

Wenn n\u00f6tig Rechte setzen (Beispiel):

sudo chmod a+rw /dev/sr0\n
"},{"location":"getting-started/prerequisites/#optional-vorab","title":"Optional vorab","text":""},{"location":"getting-started/prerequisites/#entwicklungsmodus-nur-fur-dev","title":"Entwicklungsmodus (nur f\u00fcr Dev)","text":"

Wenn du lokal entwickelst (./start.sh, npm run dev), gelten zus\u00e4tzliche Voraussetzungen:

Details: Entwicklungsumgebung

"},{"location":"getting-started/prerequisites/#abschluss-checkliste","title":"Abschluss-Checkliste","text":""},{"location":"getting-started/quickstart/","title":"Erster Lauf","text":"

Dieser Ablauf zeigt einen vollst\u00e4ndigen Job aus Anwendersicht: von Disc-Erkennung bis fertiger Datei.

"},{"location":"getting-started/quickstart/#1-dashboard-offnen-und-disc-einlegen","title":"1. Dashboard \u00f6ffnen und Disc einlegen","text":"

Erwartung:

Wenn nichts passiert: Laufwerk neu lesen.

"},{"location":"getting-started/quickstart/#2-analyse-starten","title":"2. Analyse starten","text":"

Aktion im Dashboard:

Erwartung:

"},{"location":"getting-started/quickstart/#3-metadaten-auswahlen","title":"3. Metadaten ausw\u00e4hlen","text":"

Im Dialog Metadaten ausw\u00e4hlen:

  1. OMDb-Suche nutzen oder manuell eintragen
  2. passenden Treffer markieren
  3. Auswahl \u00fcbernehmen
"},{"location":"getting-started/quickstart/#4-auf-den-nachsten-zustand-reagieren","title":"4. Auf den n\u00e4chsten Zustand reagieren","text":""},{"location":"getting-started/quickstart/#5-review-in-bereit-zum-encodieren","title":"5. Review in Bereit zum Encodieren","text":"

Im aufgeklappten Job (Pipeline-Status):

Dann Encoding starten.

"},{"location":"getting-started/quickstart/#6-encoding-uberwachen","title":"6. Encoding \u00fcberwachen","text":"

W\u00e4hrend Encodieren:

"},{"location":"getting-started/quickstart/#7-ergebnis-prufen","title":"7. Ergebnis pr\u00fcfen","text":"

Bei Fertig:

  1. Seite Historie \u00f6ffnen
  2. Job in Details \u00f6ffnen
  3. Output-Pfad, Status und Log pr\u00fcfen
"},{"location":"getting-started/quickstart/#typische-folgeaktionen","title":"Typische Folgeaktionen","text":""},{"location":"gui/","title":"GUI-Seiten","text":"

Ripster hat drei Hauptseiten in der Navigation plus eine Expert-Seite.

"},{"location":"gui/#seitenuberblick","title":"Seiten\u00fcberblick","text":"Seite Zweck Dashboard Live-Betrieb: Pipeline, Queue, Aktivit\u00e4ten, Disc-Infos Settings Konfiguration, Skripte, Ketten, Presets, Cronjobs Historie abgeschlossene/laufende Jobs durchsuchen und nachbearbeiten Database (Expert) tabellarische Rohsicht inkl. Orphan-RAW-Import"},{"location":"gui/#empfohlene-nutzung-im-alltag","title":"Empfohlene Nutzung im Alltag","text":"
  1. Start eines neuen Jobs: Dashboard
  2. Regeln/Automatisierung anpassen: Settings
  3. Ergebnisse pr\u00fcfen oder Jobs nachbearbeiten: Historie
  4. Sonderf\u00e4lle/Recovery: Database
"},{"location":"gui/#hinweise-zur-navigation","title":"Hinweise zur Navigation","text":""},{"location":"gui/dashboard/","title":"Dashboard","text":"

Das Dashboard ist die Betriebszentrale f\u00fcr laufende Jobs.

"},{"location":"gui/dashboard/#aufbau-der-seite","title":"Aufbau der Seite","text":"

Die Bereiche erscheinen in dieser Reihenfolge:

  1. Hardware Monitoring
  2. Job Queue
  3. Skript- / Cron-Status
  4. Job \u00dcbersicht
  5. Disk-Information
"},{"location":"gui/dashboard/#1-hardware-monitoring","title":"1) Hardware Monitoring","text":"

Zeigt live:

Wichtig f\u00fcr den Betrieb:

"},{"location":"gui/dashboard/#2-job-queue","title":"2) Job Queue","text":"

Zwei Spalten:

M\u00f6gliche Aktionen:

Hinweis:

"},{"location":"gui/dashboard/#3-skript-cron-status","title":"3) Skript- / Cron-Status","text":"

Zeigt:

M\u00f6gliche Aktionen:

"},{"location":"gui/dashboard/#4-job-ubersicht","title":"4) Job \u00dcbersicht","text":"

Kompakte Jobliste mit Status, Fortschritt, ETA. Klick auf einen Job klappt die Detailsteuerung auf.

Im aufgeklappten Zustand erscheint die Karte Pipeline-Status mit allen zustandsabh\u00e4ngigen Aktionen.

"},{"location":"gui/dashboard/#zustandsabhangige-hauptaktionen","title":"Zustandsabh\u00e4ngige Hauptaktionen","text":"Zustand Typische Aktion Medium erkannt / Bereit Analyse starten Metadatenauswahl Metadaten \u00f6ffnen Warte auf Auswahl Playlist w\u00e4hlen und Playlist \u00fcbernehmen Startbereit Job starten Bereit zum Encodieren Tracks/Skripte pr\u00fcfen, dann Encoding starten laufend (Analyse/Rippen/Encodieren) Abbrechen Fehler / Abgebrochen Retry Rippen, Disk-Analyse neu starten

Zus\u00e4tzlich je nach Job:

"},{"location":"gui/dashboard/#titel-spurprufung-bereit-zum-encodieren","title":"Titel-/Spurpr\u00fcfung (Bereit zum Encodieren)","text":"

Im selben Block siehst du:

"},{"location":"gui/dashboard/#5-disk-information","title":"5) Disk-Information","text":"

Zeigt aktuelles Laufwerk und Disc-Metadaten (Pfad, Modell, Disc-Label, Mount).

Aktionen:

"},{"location":"gui/dashboard/#wichtige-dialoge-im-dashboard","title":"Wichtige Dialoge im Dashboard","text":""},{"location":"gui/dashboard/#metadaten-auswahlen","title":"Metadaten ausw\u00e4hlen","text":""},{"location":"gui/dashboard/#abbruch-bereinigung","title":"Abbruch-Bereinigung","text":"

Nach Abbruch kann Ripster optional fragen, ob erzeugte RAW- oder Movie-Dateien gel\u00f6scht werden sollen.

"},{"location":"gui/dashboard/#queue-eintrag-einfugen","title":"Queue-Eintrag einf\u00fcgen","text":"

Erstellt gezielt einen Skript-, Ketten- oder Warte-Eintrag an einer bestimmten Queue-Position.

"},{"location":"gui/database/","title":"Database (Expert)","text":"

/database ist eine erweiterte Ansicht f\u00fcr Power-User und Recovery-F\u00e4lle.

"},{"location":"gui/database/#zugriff","title":"Zugriff","text":""},{"location":"gui/database/#bereiche","title":"Bereiche","text":""},{"location":"gui/database/#1-historie-datenbank","title":"1) Historie & Datenbank","text":"

Tabellarische Jobansicht mit:

Aktionen im Detaildialog entsprechen weitgehend der Seite Historie (inkl. Re-Encode, Review-Neustart, OMDb-Zuordnung, Dateil\u00f6schung).

"},{"location":"gui/database/#2-raw-ohne-historie","title":"2) RAW ohne Historie","text":"

Listet RAW-Ordner, die keinen zugeh\u00f6rigen Job-Eintrag haben.

Aktionen:

"},{"location":"gui/database/#typischer-einsatz","title":"Typischer Einsatz","text":""},{"location":"gui/database/#vorsicht","title":"Vorsicht","text":"

Diese Seite erlaubt Eingriffe mit direkter Auswirkung auf Datenbestand und Historie. Vor L\u00f6sch- oder Importaktionen Pfade und Zieljob sorgf\u00e4ltig pr\u00fcfen.

"},{"location":"gui/history/","title":"Historie","text":"

Die Seite Historie ist f\u00fcr Suche, Pr\u00fcfung und Nachbearbeitung bestehender Jobs.

"},{"location":"gui/history/#hauptansicht","title":"Hauptansicht","text":"

Filter und Werkzeuge:

Jeder Eintrag zeigt:

Klick auf einen Eintrag \u00f6ffnet die Detailansicht.

"},{"location":"gui/history/#job-detaildialog","title":"Job-Detaildialog","text":"

Bereiche:

"},{"location":"gui/history/#typische-aktionen-im-detaildialog","title":"Typische Aktionen im Detaildialog","text":""},{"location":"gui/history/#wann-welche-aktion","title":"Wann welche Aktion?","text":"Ziel Aktion Metadaten korrigieren OMDb neu zuordnen mit gleicher best\u00e4tigter Auswahl neu encodieren Encode neu starten Titel-/Spurpr\u00fcfung komplett neu berechnen Review neu starten aus vorhandenem RAW erneut encodieren RAW neu encodieren Speicher freigeben Dateil\u00f6schaktionen"},{"location":"gui/history/#logs","title":"Logs","text":""},{"location":"gui/settings/","title":"Settings","text":"

Die Seite Settings steuert Konfiguration und Automatisierung.

"},{"location":"gui/settings/#tabs-im-uberblick","title":"Tabs im \u00dcberblick","text":"Tab Zweck Konfiguration alle Kernsettings (Pfade, Tools, Monitoring, Metadaten, Queue, Benachrichtigungen) Scripte einzelne Bash-Skripte verwalten und testen Skriptketten Sequenzen aus Skript- und Warte-Schritten bauen Encode-Presets benutzerdefinierte Presets f\u00fcr das Review im Dashboard Cronjobs zeitgesteuerte Skript-/Kettenausf\u00fchrung"},{"location":"gui/settings/#tab-konfiguration","title":"Tab Konfiguration","text":"

Wichtiges Bedienmuster:

  1. Werte \u00e4ndern
  2. \u00c4nderungen speichern
  3. bei Bedarf \u00c4nderungen verwerfen oder Neu laden

Zus\u00e4tzlich:

"},{"location":"gui/settings/#tab-scripte","title":"Tab Scripte","text":"

Funktionen:

Praxis:

"},{"location":"gui/settings/#tab-skriptketten","title":"Tab Skriptketten","text":"

Funktionen:

Im Ketten-Editor:

"},{"location":"gui/settings/#tab-encode-presets","title":"Tab Encode-Presets","text":"

Ein Preset b\u00fcndelt:

Verwendung:

"},{"location":"gui/settings/#tab-cronjobs","title":"Tab Cronjobs","text":"

Funktionen:

Hilfen:

"},{"location":"gui/settings/#empfehlung-fur-stabile-nutzung","title":"Empfehlung f\u00fcr stabile Nutzung","text":"
  1. Erst Konfiguration sauber setzen
  2. dann Skripte/Ketten testen
  3. danach Cronjobs aktivieren
"},{"location":"pipeline/","title":"Anhang: Pipeline intern","text":"

Dieser Abschnitt beschreibt die technische Pipeline-Logik hinter den UI-Workflows.

"},{"location":"pipeline/#zuruck-zum-handbuch","title":"Zur\u00fcck zum Handbuch","text":""},{"location":"pipeline/encoding/","title":"Encode-Planung & Track-Auswahl","text":"

Vor dem eigentlichen Encoding erstellt Ripster einen Encode-Plan und zeigt ihn im Review an.

"},{"location":"pipeline/encoding/#ablauf","title":"Ablauf","text":"
Quelle bestimmen (Disc/RAW)\n  -> HandBrake-Scan (--scan --json)\n  -> Plan erstellen (Titel, Audio, Untertitel)\n  -> Status: Bereit zum Encodieren\n  -> Benutzer bestaetigt Auswahl\n  -> finaler HandBrake-Aufruf\n
"},{"location":"pipeline/encoding/#review-inhalt-status-bereit-zum-encodieren","title":"Review-Inhalt (Status: Bereit zum Encodieren)","text":""},{"location":"pipeline/encoding/#bestaetigung-confirm-encode","title":"Bestaetigung (confirm-encode)","text":"

Typischer Payload:

{\n  \"selectedEncodeTitleId\": 1,\n  \"selectedTrackSelection\": {\n    \"1\": {\n      \"audioTrackIds\": [1, 2],\n      \"subtitleTrackIds\": [3]\n    }\n  },\n  \"selectedPreEncodeScriptIds\": [1],\n  \"selectedPostEncodeScriptIds\": [2],\n  \"selectedPreEncodeChainIds\": [3],\n  \"selectedPostEncodeChainIds\": [4],\n  \"selectedUserPresetId\": 5\n}\n

Die best\u00e4tigte Auswahl wird im Job gespeichert und f\u00fcr Neustarts wiederverwendet.

"},{"location":"pipeline/encoding/#handbrake-aufruf","title":"HandBrake-Aufruf","text":"

Grundstruktur:

HandBrakeCLI \\\n  -i <input> \\\n  -o <output> \\\n  -t <titleId> \\\n  -Z \"<preset>\" \\\n  <extra-args> \\\n  -a <audioTrackIds|none> \\\n  -s <subtitleTrackIds|none>\n

Untertitel-Flags werden bei Bedarf erg\u00e4nzt:

"},{"location":"pipeline/encoding/#pre-post-encode-ausfuhrungen","title":"Pre-/Post-Encode-Ausf\u00fchrungen","text":"

Fehlerverhalten:

"},{"location":"pipeline/encoding/#dateinamenordner","title":"Dateinamen/Ordner","text":"

Der finale Outputpfad wird aus den Templates in den Settings aufgebaut.

Platzhalter:

Ung\u00fcltige Dateizeichen werden bereinigt.

"},{"location":"pipeline/playlist-analysis/","title":"Playlist-Analyse","text":"

Ripster analysiert bei Blu-ray-\u00e4hnlichen Quellen Playlists und fordert bei Mehrdeutigkeit eine manuelle Auswahl an.

"},{"location":"pipeline/playlist-analysis/#ziel","title":"Ziel","text":"

Erkennen, welche Playlist sehr wahrscheinlich der Hauptfilm ist, statt versehentlich eine Fake-/Dummy-Playlist zu verwenden.

"},{"location":"pipeline/playlist-analysis/#eingabedaten","title":"Eingabedaten","text":"

Die Analyse basiert auf MakeMKV-Infos (u. a. Playlist-/Segment-Struktur, Laufzeiten, Titelzuordnung).

"},{"location":"pipeline/playlist-analysis/#auswertung-vereinfacht","title":"Auswertung (vereinfacht)","text":"

F\u00fcr Kandidaten werden u. a. ber\u00fccksichtigt:

Daraus entstehen intern Kandidatenlisten, Bewertungen und eine Empfehlung.

"},{"location":"pipeline/playlist-analysis/#wann-muss-der-benutzer-entscheiden","title":"Wann muss der Benutzer entscheiden?","text":"

Wenn nach Filterung mehr als ein relevanter Kandidat \u00fcbrig bleibt, wechselt der Job in der GUI auf:

Dann muss eine Playlist best\u00e4tigt werden, bevor der Workflow weiterl\u00e4uft.

"},{"location":"pipeline/playlist-analysis/#konfigurationseinfluss","title":"Konfigurationseinfluss","text":"Feld in Settings Wirkung Minimale Titellaenge (Minuten) Mindestlaufzeit f\u00fcr Kandidaten

Default ist aktuell 60 Minuten.

"},{"location":"pipeline/playlist-analysis/#ui-verhalten","title":"UI-Verhalten","text":"

Bei manueller Entscheidung zeigt das Dashboard Kandidaten inkl. Score/Bewertung und markiert eine Empfehlung.

Nach Best\u00e4tigung:

"},{"location":"pipeline/post-encode-scripts/","title":"Encode-Skripte (Pre & Post)","text":"

Ripster kann Skripte und Skript-Ketten vor und nach dem Encode ausf\u00fchren.

"},{"location":"pipeline/post-encode-scripts/#ablauf","title":"Ablauf","text":"
Bereit zum Encodieren\n  -> Pre-Encode Skripte/Ketten\n  -> HandBrake Encoding\n  -> Post-Encode Skripte/Ketten\n  -> Fertig oder Fehler\n
"},{"location":"pipeline/post-encode-scripts/#auswahl-im-review","title":"Auswahl im Review","text":"

Im Review-Panel kannst du getrennt w\u00e4hlen:

"},{"location":"pipeline/post-encode-scripts/#fehlerverhalten","title":"Fehlerverhalten","text":""},{"location":"pipeline/post-encode-scripts/#verfugbare-umgebungsvariablen","title":"Verf\u00fcgbare Umgebungsvariablen","text":"

Beim Script-Run werden gesetzt:

"},{"location":"pipeline/post-encode-scripts/#skript-ketten","title":"Skript-Ketten","text":"

Ketten unterst\u00fctzen zwei Step-Typen:

Bei Fehler in einem Script-Step wird die Kette abgebrochen.

"},{"location":"pipeline/post-encode-scripts/#testlaufe","title":"Testl\u00e4ufe","text":"

Ergebnisse enthalten Erfolg/Exit-Code, Laufzeit und stdout/stderr.

"},{"location":"pipeline/workflow/","title":"Workflow & Zust\u00e4nde","text":"

Ripster steuert den Ablauf als Zustandsmaschine.

"},{"location":"pipeline/workflow/#zustandsdiagramm-vereinfacht","title":"Zustandsdiagramm (vereinfacht)","text":"
flowchart LR\n    A[Bereit] --> B[Medium erkannt]\n    B --> C[Analyse]\n    C --> D[Metadatenauswahl]\n    D --> E[Startbereit]\n    E --> F[Rippen]\n    E --> G[Mediainfo-Pruefung]\n    G --> H[Warte auf Auswahl]\n    H --> G\n    G --> I[Bereit zum Encodieren]\n    I --> J[Encodieren]\n    J --> K[Fertig]\n    J --> L[Fehler]\n    F --> L\n    F --> M[Abgebrochen]
"},{"location":"pipeline/workflow/#statusliste-gui-anzeige","title":"Statusliste (GUI-Anzeige)","text":"Status in der GUI Bedeutung Bereit Wartet auf Disc Medium erkannt Disc wurde erkannt Analyse MakeMKV-Analyse l\u00e4uft Metadatenauswahl Metadaten m\u00fcssen best\u00e4tigt werden Warte auf Auswahl Playlist-Auswahl ist erforderlich Startbereit kurzer \u00dcbergang vor Start Rippen MakeMKV-Rip l\u00e4uft Mediainfo-Pruefung Titel/Spuren werden ausgewertet Bereit zum Encodieren Review ist bereit Encodieren HandBrake l\u00e4uft Fertig erfolgreich abgeschlossen Abgebrochen manuell oder technisch abgebrochen Fehler fehlgeschlagen"},{"location":"pipeline/workflow/#typische-pfade","title":"Typische Pfade","text":""},{"location":"pipeline/workflow/#standardfall-kein-vorhandenes-raw","title":"Standardfall (kein vorhandenes RAW)","text":"
  1. Medium erkannt
  2. Analyse + Metadaten
  3. Rippen
  4. Mediainfo-Pruefung
  5. Bereit zum Encodieren
  6. Encodieren
  7. Fertig
"},{"location":"pipeline/workflow/#vorhandenes-raw","title":"Vorhandenes RAW","text":"

Startbereit springt direkt zu Mediainfo-Pruefung (kein neuer Rip).

"},{"location":"pipeline/workflow/#mehrdeutige-blu-ray-playlist","title":"Mehrdeutige Blu-ray-Playlist","text":"

Mediainfo-Pruefung -> Warte auf Auswahl bis Playlist best\u00e4tigt wurde.

"},{"location":"pipeline/workflow/#queue-verhalten","title":"Queue-Verhalten","text":"

Wenn der Wert Parallele Jobs erreicht ist:

"},{"location":"pipeline/workflow/#abbruch-wiederaufnahme-neustart","title":"Abbruch, Wiederaufnahme, Neustart","text":""},{"location":"tools/","title":"Anhang: Externe Tools","text":"

Ripster orchestriert externe CLI-Tools. Dieser Abschnitt erkl\u00e4rt deren Rolle im Gesamtsystem.

"},{"location":"tools/handbrake/","title":"HandBrake","text":"

Ripster verwendet HandBrakeCLI f\u00fcr Scan und Encode.

"},{"location":"tools/handbrake/#verwendete-aufrufe","title":"Verwendete Aufrufe","text":""},{"location":"tools/handbrake/#scan-review-aufbau","title":"Scan (Review-Aufbau)","text":"
HandBrakeCLI --scan --json -i <input> -t 0\n
"},{"location":"tools/handbrake/#encode-vereinfacht","title":"Encode (vereinfacht)","text":"
HandBrakeCLI \\\n  -i <input> \\\n  -o <output> \\\n  -t <titleId> \\\n  -Z \"<preset>\" \\\n  <extra-args> \\\n  -a <audioTrackIds|none> \\\n  -s <subtitleTrackIds|none>\n

Optional erg\u00e4nzt Ripster:

"},{"location":"tools/handbrake/#presets-auslesen","title":"Presets auslesen","text":"

Ripster liest Presets mit:

HandBrakeCLI -z\n
"},{"location":"tools/handbrake/#relevante-felder-in-settings","title":"Relevante Felder in Settings","text":"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\u00e4ndige Ausgabe l\u00f6schen unvollst\u00e4ndige Ausgabe bei Neustart l\u00f6schen"},{"location":"tools/handbrake/#fortschritts-parsing","title":"Fortschritts-Parsing","text":"

Ripster parst HandBrake-Stderr (Prozent/ETA/Detail) und sendet WebSocket-Progress (PIPELINE_PROGRESS).

"},{"location":"tools/handbrake/#troubleshooting","title":"Troubleshooting","text":"

Das Produktions-Installer-Script install.sh bietet eine Option zur Installation eines geb\u00fcndelten HandBrakeCLI-Binaries mit NVDEC-Unterst\u00fctzung (NVIDIA GPU-Dekodierung). Diese Option erscheint interaktiv w\u00e4hrend der Installation.

"},{"location":"tools/makemkv/","title":"MakeMKV","text":"

Ripster nutzt makemkvcon f\u00fcr Disc-Analyse und Rip.

"},{"location":"tools/makemkv/#verwendete-aufrufe","title":"Verwendete Aufrufe","text":""},{"location":"tools/makemkv/#analyse","title":"Analyse","text":"
makemkvcon -r info <source>\n

<source> ist typischerweise:

"},{"location":"tools/makemkv/#rip-mkv-modus","title":"Rip (MKV-Modus)","text":"
makemkvcon mkv <source> <title-or-all> <rawDir> [--minlength=...] [...extraArgs]\n
"},{"location":"tools/makemkv/#rip-backup-modus","title":"Rip (Backup-Modus)","text":"
makemkvcon backup <source> <rawDir> --decrypt\n
"},{"location":"tools/makemkv/#registrierungsschlussel-optional","title":"Registrierungsschl\u00fcssel (optional)","text":"

Wenn in Settings ein MakeMKV Key gesetzt ist, f\u00fchrt Ripster vor Analyse/Rip aus:

makemkvcon reg <key>\n
"},{"location":"tools/makemkv/#relevante-felder-in-settings","title":"Relevante Felder in Settings","text":"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\u00fcr Analyse MakeMKV Rip Extra Args (Blu-ray/DVD) Zusatzargumente f\u00fcr Rip"},{"location":"tools/makemkv/#hinweise","title":"Hinweise","text":""},{"location":"tools/mediainfo/","title":"MediaInfo","text":"

Ripster nutzt mediainfo zur JSON-Analyse von Medien-Dateien.

"},{"location":"tools/mediainfo/#aufruf","title":"Aufruf","text":"
mediainfo --Output=JSON <input>\n

Der Input ist typischerweise eine RAW-Datei oder ein vom Workflow gew\u00e4hlter Inputpfad.

"},{"location":"tools/mediainfo/#verwendung-in-ripster","title":"Verwendung in Ripster","text":""},{"location":"tools/mediainfo/#relevante-settings","title":"Relevante Settings","text":"Key Bedeutung mediainfo_command CLI-Binary mediainfo_extra_args_bluray / _dvd profilspezifische Zusatzargumente"},{"location":"tools/mediainfo/#troubleshooting","title":"Troubleshooting","text":""},{"location":"workflows/","title":"Workflows aus Nutzersicht","text":"

Diese Seite beschreibt typische Abl\u00e4ufe mit den passenden UI-Aktionen.

"},{"location":"workflows/#workflow-1-standardlauf-disc-fertige-datei","title":"Workflow 1: Standardlauf (Disc -> fertige Datei)","text":"
  1. Dashboard: Disc einlegen, Analyse starten
  2. Metadaten im Dialog \u00fcbernehmen
  3. bei Bereit zum Encodieren Titel/Tracks pr\u00fcfen
  4. Encoding starten
  5. Ergebnis in Historie kontrollieren
"},{"location":"workflows/#workflow-2-playlist-entscheidung-bei-blu-ray","title":"Workflow 2: Playlist-Entscheidung bei Blu-ray","text":"
  1. Job landet in Warte auf Auswahl
  2. im Pipeline-Status Playlist-Kandidaten vergleichen
  3. gew\u00fcnschte Playlist ausw\u00e4hlen
  4. Playlist \u00fcbernehmen
  5. danach normal weiter bis Bereit zum Encodieren
"},{"location":"workflows/#workflow-3-mehrere-jobs-mit-queue","title":"Workflow 3: Mehrere Jobs mit Queue","text":"
  1. Parallel-Limit in Settings \u00fcber Parallele Jobs setzen
  2. neue Jobs starten; \u00fcbersch\u00fcssige Starts gehen in Job Queue
  3. Reihenfolge per Drag-and-Drop anpassen
  4. bei Bedarf Skript/Kette/Warten als Queue-Eintrag erg\u00e4nzen
"},{"location":"workflows/#workflow-4-nachbearbeitung-eines-bestehenden-jobs","title":"Workflow 4: Nachbearbeitung eines bestehenden Jobs","text":"

In Historie -> Detaildialog:

"},{"location":"workflows/#workflow-5-automatisierung-mit-skripten-und-cron","title":"Workflow 5: Automatisierung mit Skripten und Cron","text":"
  1. Settings -> Scripte: Skripte anlegen und testen
  2. Settings -> Skriptketten: Ketten bauen und testen
  3. im Dashboard-Review Pre-/Post-Ausf\u00fchrungen pro Job ausw\u00e4hlen
  4. Settings -> Cronjobs: zeitgesteuerte Ausf\u00fchrung konfigurieren
  5. Status im Dashboard (Skript- / Cron-Status) \u00fcberwachen
"},{"location":"workflows/#workflow-6-abbruch-und-recovery","title":"Workflow 6: Abbruch und Recovery","text":""},{"location":"workflows/#fall-a-job-wurde-abgebrochen","title":"Fall A: Job wurde abgebrochen","text":""},{"location":"workflows/#fall-b-job-steht-in-bereit-zum-encodieren-ist-aber-nicht-aktive-session","title":"Fall B: Job steht in Bereit zum Encodieren, ist aber nicht aktive Session","text":""},{"location":"workflows/#fall-c-raw-ohne-historieneintrag","title":"Fall C: RAW ohne Historieneintrag","text":""}]}