sudo bash install.sh --branch dev
diff --git a/site/getting-started/prerequisites/index.html b/site/getting-started/prerequisites/index.html
index 97065b0..64fc256 100644
--- a/site/getting-started/prerequisites/index.html
+++ b/site/getting-started/prerequisites/index.html
@@ -1,8 +1,4 @@
- Voraussetzungen - Ripster
Voraussetzungen Diese Seite ist die praktische Checkliste vor der Installation.
1) System Punkt Mindestwert Empfehlung Betriebssystem Linux oder macOS Ubuntu 22.04+ Node.js 20.19.0 20.x LTS RAM 4 GB 8 GB+ Freier Speicher 50 GB 500 GB+
Node-Version prüfen:
Ripster benötigt folgende CLI-Tools im PATH:
makemkvcon HandBrakeCLI mediainfo Schnell prüfen:
makemkvcon --version
- HandBrakeCLI --version
- mediainfo --Version
- 3) Optisches Laufwerk Für Disc-Betrieb muss ein DVD/Blu-ray-Laufwerk erreichbar sein.
ls /dev/sr*
- lsblk | grep rom
- Wenn nötig Rechte setzen (Beispiel):
sudo chmod a+rw /dev/sr0
- 4) OMDb API-Key Für automatische Metadaten (Titel, Poster, IMDb-ID):
Key unter omdbapi.com anlegen in den Settings als omdb_api_key eintragen 5) Optional: PushOver Für Push-Nachrichten bei Erfolg/Fehler:
Account/App auf pushover.net pushover_token und pushover_user später in den Settings setzen Abschluss-Checkliste [ ] Node.js 20.x verfügbar [ ] makemkvcon, HandBrakeCLI, mediainfo ausführbar [ ] Laufwerk erkannt [ ] OMDb Key bereit Zurück zum Seitenanfang
\ No newline at end of file
+ Voraussetzungen - Ripster
Voraussetzungen Die Voraussetzungen hängen davon ab, wie du Ripster betreibst.
Produktionsbetrieb mit install.sh (Standard) Für den normalen Betrieb sind nur wenige Punkte vorab nötig.
Pflicht unterstütztes Linux-System (Debian/Ubuntu) root-Rechte Internetzugang während der Installation optisches Laufwerk für Disc-Betrieb install.sh installiert die benötigten Tools selbst (u. a. Node.js, MakeMKV, HandBrakeCLI, MediaInfo), sofern sie nicht explizit per --no-* übersprungen werden.
Laufwerk kurz prüfen ls /dev/sr*
+ lsblk | grep rom
+ Wenn nötig Rechte setzen (Beispiel):
sudo chmod a+rw /dev/sr0
+ Optional vorab OMDb API-Key (kann auch nach Installation in den Settings gesetzt werden) PushOver-Zugangsdaten (optional) Entwicklungsmodus (nur für Dev) 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
Abschluss-Checkliste [ ] Produktionsbetrieb: Linux + root + Internet + Laufwerk vorhanden [ ] Dev-Modus (nur falls benötigt): Node.js und CLI-Tools verfügbar Zurück zum Seitenanfang
\ No newline at end of file
diff --git a/site/search/search_index.json b/site/search/search_index.json
index 06dd2c9..35b6759 100644
--- a/site/search/search_index.json
+++ b/site/search/search_index.json
@@ -1 +1 @@
-{"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":" Voraussetzungen pr\u00fcfen und installieren: Installation Grundkonfiguration in der UI setzen: Ersteinrichtung Ersten vollst\u00e4ndigen Job durchlaufen: Erster Lauf "},{"location":"#was-du-hier-findest","title":"Was du hier findest","text":" Benutzerhandbuch Installation GUI-Seiten im Detail (Dashboard, Settings, Historie, Database) typische Arbeitsabl\u00e4ufe aus Anwendersicht Technischer Anhang vollst\u00e4ndige Einstellungsreferenz Pipeline-/API-/Architekturdetails Deployment und Tool-Hintergr\u00fcnde "},{"location":"#empfohlene-lesereihenfolge","title":"Empfohlene Lesereihenfolge","text":" Benutzerhandbuch \u00dcberblick GUI-Seiten Workflows aus Nutzersicht 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":" Health
Service-Liveness.
GET /api/health
Pipeline API
Analyse, Start/Retry/Cancel, Queue, Re-Encode.
Pipeline API
Settings API
Einstellungen, Skripte/Ketten, User-Presets.
Settings API
History API
Job-Historie, Orphan-Import, L\u00f6schoperationen.
History API
Cron API
Zeitgesteuerte Skript-/Kettenausf\u00fchrung.
Cron API
WebSocket Events
Pipeline-, Queue-, Disk-, Settings-, Cron- und Monitoring-Events.
WebSocket
"},{"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:
0 2 * * * t\u00e4glich 02:00 */15 * * * * alle 15 Minuten 0 6 * * 1-5 Mo-Fr 06:00 "},{"location":"api/crons/#websocket-events-zu-cron","title":"WebSocket-Events zu Cron","text":" CRON_JOBS_UPDATED bei Create/Update/Delete CRON_JOB_UPDATED bei Laufzeitstatus (running -> success|error) "},{"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":" Ein aktiver Pipeline-Job kann nicht gel\u00f6scht werden (409). Alle L\u00f6schoperationen sind irreversibel. "},{"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.
Aktive Aktivit\u00e4ten (active): Laufen gerade. Letzte Aktivit\u00e4ten (recent): Abgeschlossen, max. 120 Eintr\u00e4ge. \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:
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 "},{"location":"api/settings/#skript-ketten","title":"Skript-Ketten","text":"Basis: /api/settings/script-chains
Eine Kette hat Schritte vom Typ:
script (scriptId erforderlich) wait (waitSeconds 1..3600) "},{"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:
Retry-Intervall: 1500ms Wiederverbindung bis Komponente unmounted wird "},{"location":"appendix/","title":"Technischer Anhang","text":"Dieser Bereich enth\u00e4lt die technische Referenz hinter dem Benutzerhandbuch.
"},{"location":"appendix/#inhalt","title":"Inhalt","text":" Konfiguration komplette Feldreferenz Umgebungsvariablen Pipeline intern Zustandsmodell Encode-Planung Playlist-Analyse Pre-/Post-Encode-Ausf\u00fchrungen API-Referenz REST-Endpunkte WebSocket-Events Architektur Backend-/Frontend-Aufbau Datenbank Deployment Betrieb in Entwicklung und Produktion Externe Tools MakeMKV, HandBrake, MediaInfo "},{"location":"appendix/#wann-du-in-den-anhang-wechselst","title":"Wann du in den Anhang wechselst","text":" du integrierst Ripster mit anderen Systemen du betreibst mehrere Instanzen oder willst tiefer debuggen du brauchst Feld-/API-/Schema-Details f\u00fcr Automatisierung "},{"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":" \u00dcbersicht Backend-Services Frontend-Komponenten Datenbank "},{"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:
Pipeline-State-Machine + Persistenz (pipeline_state) Disc-Analyse/Rip/Review/Encode Queue-Management (Jobs + script|chain|wait Eintr\u00e4ge) Retry/Re-Encode/Restart-Flows WebSocket-Broadcasts f\u00fcr State/Progress/Queue Wichtige Methoden:
analyzeDisc() selectMetadata() startPreparedJob() confirmEncodeReview() cancel() retry() reencodeFromRaw() restartReviewFromRaw() restartEncodeWithLastSettings() resumeReadyToEncodeJob() enqueueNonJobEntry(), reorderQueue(), removeQueueEntry() "},{"location":"architecture/backend/#diskdetectionservicejs","title":"diskDetectionService.js","text":"Pollt Laufwerk(e) und emittiert:
discInserted discRemoved error Zusatz:
Modus auto oder explicit heuristische mediaProfile-Erkennung (bluray/dvd/other) rescanAndEmit() f\u00fcr manuellen Trigger "},{"location":"architecture/backend/#settingsservicejs","title":"settingsService.js","text":"Settings-Layer mit Validation/Serialisierung.
Features:
getCategorizedSettings() f\u00fcr UI-Form setSettingValue() / setSettingsBulk() profilspezifische Aufl\u00f6sung (resolveEffectiveToolSettings) CLI-Config-Building f\u00fcr MakeMKV/HandBrake/MediaInfo HandBrake-Preset-Liste via HandBrakeCLI -z MakeMKV-Registration-Command aus makemkv_registration_key "},{"location":"architecture/backend/#historyservicejs","title":"historyService.js","text":"Historie + Dateioperationen.
Features:
Job-Liste/Detail inkl. Log-Tail Orphan-RAW-Erkennung und Import OMDb-Nachzuweisung Dateil\u00f6schung (raw|movie|both) Job-L\u00f6schung (none|raw|movie|both) "},{"location":"architecture/backend/#cronservicejs","title":"cronService.js","text":"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 "},{"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:
startActivity(type, payload) \u2192 Aktivit\u00e4t registrieren, ID zur\u00fcckgeben updateActivity(id, patch) \u2192 Laufende Aktivit\u00e4t aktualisieren completeActivity(id, payload) \u2192 Aktivit\u00e4t abschlie\u00dfen und in recent verschieben setControls(id, { cancel, nextStep }) \u2192 Steuer-Handler registrieren (f\u00fcr canCancel/canNextStep) requestCancel(id) / requestNextStep(id) \u2192 Steuer-Handler aufrufen clearRecent() \u2192 Abgeschlossene Aktivit\u00e4ten l\u00f6schen getSnapshot() \u2192 Snapshot mit active + recent + updatedAt Broadcasts RUNTIME_ACTIVITY_CHANGED \u00fcber WebSocket bei jeder \u00c4nderung Limits:
recent max. 120 Eintr\u00e4ge stdout/stderr/output max. 12.000 Zeichen message/errorMessage max. 2.000 Zeichen Vollst\u00e4ndige API-Dokumentation: Runtime Activities API
"},{"location":"architecture/backend/#weitere-services","title":"Weitere Services","text":" scriptService.js (CRUD + Test + Wrapper-Ausf\u00fchrung) scriptChainService.js (CRUD + Step-Execution) userPresetService.js (HandBrake User-Presets) hardwareMonitorService.js (CPU/RAM/GPU/Storage) websocketService.js (Client-Registry + Broadcast) notificationService.js (PushOver) logger.js (rotierende Datei-Logs) "},{"location":"architecture/backend/#bootstrapping-srcindexjs","title":"Bootstrapping (src/index.js)","text":"Beim Start:
DB init/migrate Pipeline-Init Cron-Init Express-Routes + Error-Handler WebSocket-Server auf /ws Hardware-Monitoring-Init 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:
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 Audit: created_at, updated_at "},{"location":"architecture/database/#pipeline_state","title":"pipeline_state","text":"Singleton-Tabelle (id = 1) f\u00fcr aktiven Snapshot:
state active_job_id progress eta status_text context_json updated_at "},{"location":"architecture/database/#settings_schema-settings_values","title":"settings_schema + settings_values","text":" settings_schema: Definition (Typ, Default, Validation, Reihenfolge) settings_values: aktueller Wert pro Key "},{"location":"architecture/database/#scripts-script_chains-script_chain_steps","title":"scripts, script_chains, script_chain_steps","text":" 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 "},{"location":"architecture/database/#user_presets","title":"user_presets","text":"Benannte HandBrake-Preset-Sets:
name media_type (bluray|dvd|other|all) handbrake_preset extra_args description "},{"location":"architecture/database/#cron_jobs-cron_run_logs","title":"cron_jobs + cron_run_logs","text":" cron_jobs: Zeitplan + Status cron_run_logs: einzelne L\u00e4ufe status: running|success|error output error_message "},{"location":"architecture/database/#migrationrecovery","title":"Migration/Recovery","text":"Beim Start werden Schema und Settings-Metadaten automatisch abgeglichen.
Bei korruptem SQLite-File:
Datei wird nach backend/data/corrupt-backups/ verschoben neue DB wird initialisiert 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:
Status/Progress/ETA Metadaten-Dialog Playlist-Entscheidung Review-Panel Queue-Interaktion (reorder/add/remove) Job-Aktionen (Start/Cancel/Retry/Re-Encode) Hardware-Monitoring-Anzeige "},{"location":"architecture/frontend/#settingspagejsx","title":"SettingsPage.jsx","text":"Konfiguration:
dynamisches Settings-Formular (DynamicSettingsForm) Skripte/Ketten inkl. Reorder/Test User-Presets Cron-Jobs (CronJobsTab) "},{"location":"architecture/frontend/#historypagejsx","title":"HistoryPage.jsx","text":"Historie:
Job-Liste/Filter Job-Details + Logs OMDb-Nachzuweisung Re-Encode/Restart-Workflows "},{"location":"architecture/frontend/#wichtige-komponenten","title":"Wichtige Komponenten","text":" PipelineStatusCard.jsx MetadataSelectionDialog.jsx MediaInfoReviewPanel.jsx JobDetailDialog.jsx CronJobsTab.jsx "},{"location":"architecture/frontend/#api-client-apiclientjs","title":"API-Client (api/client.js)","text":" zentraler request() mit JSON-Handling Fehlerobjekt aus API wird auf Error(message) gemappt VITE_API_BASE default /api "},{"location":"architecture/frontend/#websocket-hooksusewebsocketjs","title":"WebSocket (hooks/useWebSocket.js)","text":" 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 DISC_DETECTED / DISC_REMOVED HARDWARE_MONITOR_UPDATE "},{"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:
PIPELINE_STATE_CHANGED, PIPELINE_PROGRESS, PIPELINE_QUEUE_CHANGED DISC_DETECTED, DISC_REMOVED 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 "},{"location":"architecture/overview/#prozessausfuhrung","title":"Prozessausf\u00fchrung","text":"Externe Tools werden als Child-Processes gestartet (processRunner):
Streaming von stdout/stderr Progress-Parsing (progressParsers.js) kontrollierter Abbruch (SIGINT/SIGKILL-Fallback) "},{"location":"architecture/overview/#persistenz","title":"Persistenz","text":"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\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 (ERROR oder CANCELLED) und k\u00f6nnen erneut gestartet werden.
"},{"location":"architecture/overview/#cors-runtime-konfig","title":"CORS & Runtime-Konfig","text":" CORS_ORIGIN default: * LOG_LEVEL default: info DB-/Log-Pfade \u00fcber DB_PATH/LOG_DIR konfigurierbar "},{"location":"configuration/","title":"Anhang: Konfiguration","text":"Dieser Abschnitt ist die technische Referenz zu allen Konfigurationsarten in Ripster.
"},{"location":"configuration/#inhalte","title":"Inhalte","text":" Einstellungsreferenz
Vollst\u00e4ndige Liste aller UI-Settings (Typ, Default, Hinweise).
Einstellungsreferenz
Umgebungsvariablen
backend/.env und frontend/.env inkl. Priorit\u00e4ten.
Umgebungsvariablen
"},{"location":"configuration/#zuruck-zum-handbuch","title":"Zur\u00fcck zum Handbuch","text":" Benutzerhandbuch \u00dcberblick "},{"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":" Prozess-Umgebungsvariablen .env Code-Defaults "},{"location":"configuration/settings-reference/","title":"Einstellungsreferenz","text":"Alle Settings liegen in settings_schema/settings_values und werden \u00fcber die UI verwaltet.
"},{"location":"configuration/settings-reference/#profil-system","title":"Profil-System","text":"Ripster arbeitet mit Media-Profilen:
Viele Tool-/Pfad-Settings existieren als Profil-Varianten (*_bluray, *_dvd, *_other).
Wichtig:
F\u00fcr raw_dir, movie_dir und die zugeh\u00f6rigen *_owner-Keys gibt es kein Cross-Profil-Fallback. F\u00fcr viele Tool-Keys werden profilspezifische Varianten bevorzugt. "},{"location":"configuration/settings-reference/#template-platzhalter","title":"Template-Platzhalter","text":"Datei-/Ordner-Templates unterst\u00fctzen:
${title} ${year} ${imdbId} Nicht gesetzte Werte werden zu unknown.
"},{"location":"configuration/settings-reference/#kategorie-pfade","title":"Kategorie: Pfade","text":"Key Typ Default raw_dir path data/output/raw raw_dir_bluray path null raw_dir_dvd path null raw_dir_other path null raw_dir_bluray_owner string null raw_dir_dvd_owner string null raw_dir_other_owner string null movie_dir path data/output/movies movie_dir_bluray path null movie_dir_dvd path null movie_dir_other path null movie_dir_bluray_owner string null movie_dir_dvd_owner string null movie_dir_other_owner string null log_dir path data/logs"},{"location":"configuration/settings-reference/#kategorie-laufwerk","title":"Kategorie: Laufwerk","text":"Key Typ Default Hinweis drive_mode select auto auto oder explicit drive_device path /dev/sr0 bei explicit relevant makemkv_source_index number 0 MakeMKV Source-Index disc_poll_interval_ms number 4000 1000..60000"},{"location":"configuration/settings-reference/#kategorie-monitoring","title":"Kategorie: Monitoring","text":"Key Typ Default hardware_monitoring_enabled boolean true hardware_monitoring_interval_ms number 5000"},{"location":"configuration/settings-reference/#kategorie-tools-global","title":"Kategorie: Tools (global)","text":"Key Typ Default makemkv_command string makemkvcon makemkv_registration_key string null mediainfo_command string mediainfo makemkv_min_length_minutes number 60 handbrake_command string HandBrakeCLI handbrake_restart_delete_incomplete_output boolean true pipeline_max_parallel_jobs number 1"},{"location":"configuration/settings-reference/#blu-ray-spezifisch","title":"Blu-ray-spezifisch","text":"Key Typ Default mediainfo_extra_args_bluray string null makemkv_rip_mode_bluray select backup makemkv_analyze_extra_args_bluray string null makemkv_rip_extra_args_bluray string null handbrake_preset_bluray string H.264 MKV 1080p30 handbrake_extra_args_bluray string null output_extension_bluray select mkv filename_template_bluray string ${title} (${year}) output_folder_template_bluray string null"},{"location":"configuration/settings-reference/#dvd-spezifisch","title":"DVD-spezifisch","text":"Key Typ Default mediainfo_extra_args_dvd string null makemkv_rip_mode_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 output_extension_dvd select mkv filename_template_dvd string ${title} (${year}) output_folder_template_dvd string null"},{"location":"configuration/settings-reference/#kategorie-metadaten","title":"Kategorie: Metadaten","text":"Key Typ Default omdb_api_key string null omdb_default_type select movie"},{"location":"configuration/settings-reference/#kategorie-benachrichtigungen-pushover","title":"Kategorie: Benachrichtigungen (PushOver)","text":"Key Typ Default pushover_enabled boolean false pushover_token string null pushover_user string null pushover_device string null pushover_title_prefix string Ripster pushover_priority number 0 pushover_timeout_ms number 7000 pushover_notify_metadata_ready boolean true pushover_notify_rip_started boolean true pushover_notify_encoding_started boolean true pushover_notify_job_finished boolean true pushover_notify_job_error boolean true pushover_notify_job_cancelled boolean true pushover_notify_reencode_started boolean true pushover_notify_reencode_finished boolean true"},{"location":"configuration/settings-reference/#entfernte-legacy-keys","title":"Entfernte Legacy-Keys","text":"Diese Legacy-Keys werden bei Migration entfernt und sollten nicht mehr genutzt werden:
makemkv_backup_mode mediainfo_extra_args makemkv_rip_mode makemkv_analyze_extra_args makemkv_rip_extra_args handbrake_preset handbrake_extra_args output_extension filename_template output_folder_template pushover_notify_disc_detected "},{"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":" Node.js >= 20.19.0 externe Tools installiert (makemkvcon, HandBrakeCLI, mediainfo) "},{"location":"deployment/development/#schnellstart","title":"Schnellstart","text":"./start.sh\n Startet:
Backend (http://localhost:3001, mit nodemon) Frontend (http://localhost:5173, mit Vite HMR) 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:
/api -> http://127.0.0.1:3001 /ws -> ws://127.0.0.1:3001 "},{"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 auf Debian/Ubuntu ein \u2013 inklusive Node.js, MakeMKV, HandBrake, nginx und systemd-Dienst.
Unterst\u00fctzte Systeme: Debian 11/12, Ubuntu 22.04/24.04 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> main 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":" Systempr\u00fcfung \u2013 OS-Erkennung und Root-Check Systempakete \u2013 curl, wget, git, mediainfo, udev u. a. Node.js 20 \u2013 via NodeSource, falls noch nicht installiert MakeMKV \u2013 aktuelle Version wird aus dem offiziellen Forum ermittelt und aus dem Quellcode kompiliert (kann mit --no-makemkv \u00fcbersprungen werden) HandBrake \u2013 interaktive Auswahl: Option 1: Standard (apt install handbrake-cli) Option 2: Geb\u00fcndelte GPU-Version mit NVDEC aus bin/HandBrakeCLI Systembenutzer ripster \u2013 ohne Login-Shell, Gruppen: cdrom, optical, disk, video, render Repository \u2013 klont Branch nach --dir (bei --reinstall: sichert DB, pullt, stellt DB wieder her) npm-Abh\u00e4ngigkeiten \u2013 Root, Backend (nur production), Frontend Frontend-Build \u2013 npm run build mit relativen API-URLs (nginx-kompatibel) Backend .env \u2013 wird automatisch generiert (bei --reinstall bleibt bestehende erhalten) Berechtigungen \u2013 ripster:ripster auf Installationsverzeichnis, 600 auf .env systemd-Dienst \u2013 ripster-backend.service erstellt, aktiviert und gestartet 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":" Ripster hat keine eingebaute Authentifizierung. F\u00fcr externen Zugriff mindestens Basic Auth + TLS + Netzwerksegmentierung/VPN einsetzen. Secrets nicht ins Repo committen (.env, Settings-Felder). "},{"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":" Anwender, die Discs verarbeiten wollen Betreiber, die den t\u00e4glichen Ablauf stabil fahren m\u00f6chten Power-User, die Queue/Skripte/Cron im UI steuern m\u00f6chten "},{"location":"getting-started/#kapitelstruktur","title":"Kapitelstruktur","text":"Kapitel Zweck Voraussetzungen Pr\u00fcfen, ob System und Tools bereit sind 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":" Voraussetzungen Installation Ersteinrichtung Erster Lauf "},{"location":"getting-started/#wenn-ripster-bereits-lauft","title":"Wenn Ripster bereits l\u00e4uft","text":" GUI-Seiten Workflows 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_dir, movie_dir, log_dir Tools makemkv_command, handbrake_command, mediainfo_command Metadaten omdb_api_key, optional omdb_default_type 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:
*_bluray *_dvd optional *_other Typische Beispiele:
handbrake_preset_bluray und handbrake_preset_dvd raw_dir_bluray und raw_dir_dvd filename_template_bluray und filename_template_dvd "},{"location":"getting-started/configuration/#3-queue-und-monitoring-festlegen","title":"3. Queue und Monitoring festlegen","text":" pipeline_max_parallel_jobs f\u00fcr parallele Jobs hardware_monitoring_enabled und Intervall f\u00fcr Live-Metriken im Dashboard "},{"location":"getting-started/configuration/#4-optional-push-benachrichtigungen","title":"4. Optional: Push-Benachrichtigungen","text":"In den Benachrichtigungsfeldern setzen:
pushover_enabled pushover_token pushover_user Dann \u00fcber PushOver Test direkt pr\u00fcfen.
"},{"location":"getting-started/configuration/#2-minuten-funktionstest","title":"2-Minuten-Funktionstest","text":" Dashboard \u00f6ffnen Disc einlegen Analyse starten Metadaten \u00fcbernehmen Bis READY_TO_ENCODE 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":" Feld mit Fehler markieren lassen (rote Validierung im Formular) Pfadangaben und numerische Werte pr\u00fcfen bei Tool-Pfaden direkt CLI-Aufruf im Terminal testen "},{"location":"getting-started/configuration/#weiter","title":"Weiter","text":" Erster Lauf GUI-Seiten im Detail "},{"location":"getting-started/installation/","title":"Installation","text":"Die empfohlene Installation l\u00e4uft \u00fcber install.sh und richtet Ripster vollst\u00e4ndig ein.
"},{"location":"getting-started/installation/#zielbild-nach-der-installation","title":"Zielbild nach der Installation","text":" Ripster-Backend als systemd-Dienst Frontend \u00fcber nginx erreichbar UI auf http://<Server-IP> "},{"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 wirst du nach dem HandBrake-Modus gefragt:
1 Standard (apt) 2 GPU/NVDEC (geb\u00fcndeltes Binary) "},{"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":" Mit nginx: http://<Server-IP> Ohne nginx (--no-nginx): API auf http://<Server-IP>:3001/api "},{"location":"getting-started/installation/#wichtige-optionen","title":"Wichtige Optionen","text":"Option Zweck --branch <branch> anderen Branch installieren --dir <pfad> Installationsverzeichnis \u00e4ndern --port <port> Backend-Port setzen --host <hostname> Hostname/IP f\u00fcr nginx/CORS --no-makemkv MakeMKV nicht installieren --no-handbrake HandBrake nicht installieren --no-nginx nginx-Konfiguration \u00fcberspringen --reinstall Update einer bestehenden Installation 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":" Permission denied am Laufwerk: Laufwerksrechte/Gruppen pr\u00fcfen Tools nicht gefunden: makemkvcon, HandBrakeCLI, mediainfo im PATH pr\u00fcfen UI nicht erreichbar: nginx-Status und Port/Firewall pr\u00fcfen "},{"location":"getting-started/installation/#danach-weiter","title":"Danach weiter","text":" Ersteinrichtung Erster Lauf "},{"location":"getting-started/prerequisites/","title":"Voraussetzungen","text":"Diese Seite ist die praktische Checkliste vor der Installation.
"},{"location":"getting-started/prerequisites/#1-system","title":"1) System","text":"Punkt Mindestwert Empfehlung Betriebssystem Linux oder macOS Ubuntu 22.04+ Node.js 20.19.0 20.x LTS RAM 4 GB 8 GB+ Freier Speicher 50 GB 500 GB+ Node-Version pr\u00fcfen:
node --version\n "},{"location":"getting-started/prerequisites/#2-externe-tools","title":"2) Externe Tools","text":"Ripster ben\u00f6tigt folgende CLI-Tools im PATH:
makemkvcon HandBrakeCLI mediainfo Schnell pr\u00fcfen:
makemkvcon --version\nHandBrakeCLI --version\nmediainfo --Version\n "},{"location":"getting-started/prerequisites/#3-optisches-laufwerk","title":"3) Optisches Laufwerk","text":"F\u00fcr Disc-Betrieb muss ein DVD/Blu-ray-Laufwerk erreichbar sein.
ls /dev/sr*\nlsblk | grep rom\n Wenn n\u00f6tig Rechte setzen (Beispiel):
sudo chmod a+rw /dev/sr0\n "},{"location":"getting-started/prerequisites/#4-omdb-api-key","title":"4) OMDb API-Key","text":"F\u00fcr automatische Metadaten (Titel, Poster, IMDb-ID):
Key unter omdbapi.com anlegen in den Settings als omdb_api_key eintragen "},{"location":"getting-started/prerequisites/#5-optional-pushover","title":"5) Optional: PushOver","text":"F\u00fcr Push-Nachrichten bei Erfolg/Fehler:
Account/App auf pushover.net pushover_token und pushover_user sp\u00e4ter in den Settings setzen "},{"location":"getting-started/prerequisites/#abschluss-checkliste","title":"Abschluss-Checkliste","text":" [ ] Node.js 20.x verf\u00fcgbar [ ] makemkvcon, HandBrakeCLI, mediainfo ausf\u00fchrbar [ ] Laufwerk erkannt [ ] OMDb Key bereit "},{"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:
Status wechselt auf DISC_DETECTED bzw. Medium erkannt im Bereich Disk-Information sind Laufwerksdaten sichtbar Wenn nichts passiert: Laufwerk neu lesen.
"},{"location":"getting-started/quickstart/#2-analyse-starten","title":"2. Analyse starten","text":"Aktion im Dashboard:
Erwartung:
Status ANALYZING danach Metadaten-Dialog "},{"location":"getting-started/quickstart/#3-metadaten-auswahlen","title":"3. Metadaten ausw\u00e4hlen","text":"Im Dialog Metadaten ausw\u00e4hlen:
OMDb-Suche nutzen oder manuell eintragen passenden Treffer markieren Auswahl \u00fcbernehmen "},{"location":"getting-started/quickstart/#4-auf-den-nachsten-zustand-reagieren","title":"4. Auf den n\u00e4chsten Zustand reagieren","text":" Normalfall ohne vorhandenes RAW: RIPPING -> MEDIAINFO_CHECK -> READY_TO_ENCODE bei vorhandenem RAW: direkt MEDIAINFO_CHECK -> READY_TO_ENCODE bei unklarer Blu-ray-Playlist: WAITING_FOR_USER_DECISION (Playlist ausw\u00e4hlen und \u00fcbernehmen) "},{"location":"getting-started/quickstart/#5-review-in-ready_to_encode","title":"5. Review in READY_TO_ENCODE","text":"Im aufgeklappten Job (Pipeline-Status):
Encode-Titel w\u00e4hlen Audio-/Subtitle-Spuren pr\u00fcfen optional User-Preset ausw\u00e4hlen optional Pre-/Post-Skripte bzw. Ketten hinzuf\u00fcgen Dann Encoding starten.
"},{"location":"getting-started/quickstart/#6-encoding-uberwachen","title":"6. Encoding \u00fcberwachen","text":"W\u00e4hrend ENCODING:
Fortschritt + ETA im Dashboard Live-Log im Pipeline-Status Queue- und Skript/Cron-Status parallel beobachtbar "},{"location":"getting-started/quickstart/#7-ergebnis-prufen","title":"7. Ergebnis pr\u00fcfen","text":"Bei FINISHED:
Seite Historie \u00f6ffnen Job in Details \u00f6ffnen Output-Pfad, Status und Log pr\u00fcfen "},{"location":"getting-started/quickstart/#typische-folgeaktionen","title":"Typische Folgeaktionen","text":" Falsches OMDb-Match: in Historie -> OMDb neu zuordnen Neue Encodierung aus RAW: RAW neu encodieren Pr\u00fcfung komplett neu aufbauen: Review neu starten "},{"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":" Start eines neuen Jobs: Dashboard Regeln/Automatisierung anpassen: Settings Ergebnisse pr\u00fcfen oder Jobs nachbearbeiten: Historie Sonderf\u00e4lle/Recovery: Database "},{"location":"gui/#hinweise-zur-navigation","title":"Hinweise zur Navigation","text":" Dashboard, Settings, Historie sind direkt in der Kopfnavigation. Database ist als Expert-Route verf\u00fcgbar: /database. "},{"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:
Hardware Monitoring Job Queue Skript- / Cron-Status Job \u00dcbersicht Disk-Information "},{"location":"gui/dashboard/#1-hardware-monitoring","title":"1) Hardware Monitoring","text":"Zeigt live:
CPU (gesamt + optional pro Kern) RAM GPU-Auslastung/Temperatur/VRAM freien Speicher in den konfigurierten Pfaden Wichtig f\u00fcr den Betrieb:
Hohe Speicherauslastung oder fast volle Zielpfade fr\u00fch erkennen \u00fcber Settings aktivierbar/deaktivierbar (hardware_monitoring_*) "},{"location":"gui/dashboard/#2-job-queue","title":"2) Job Queue","text":"Zwei Spalten:
Laufende Jobs Warteschlange M\u00f6gliche Aktionen:
Queue per Drag-and-Drop umsortieren Queue-Job entfernen (X) zus\u00e4tzliche Queue-Elemente einf\u00fcgen (+): Skript Skriptkette Wartezeit Hinweis:
Parallel zeigt das aktuell konfigurierte Parallel-Limit (pipeline_max_parallel_jobs). "},{"location":"gui/dashboard/#3-skript-cron-status","title":"3) Skript- / Cron-Status","text":"Zeigt:
aktive Ausf\u00fchrungen (Skripte, Ketten, Cron) zuletzt abgeschlossene Ausf\u00fchrungen M\u00f6gliche Aktionen:
laufende Ketten: N\u00e4chster Schritt laufende Eintr\u00e4ge: Abbrechen Historie der Aktivit\u00e4ten: Liste leeren "},{"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 DISC_DETECTED / IDLE Analyse starten METADATA_SELECTION Metadaten \u00f6ffnen WAITING_FOR_USER_DECISION Playlist w\u00e4hlen und Playlist \u00fcbernehmen READY_TO_START Job starten READY_TO_ENCODE Tracks/Skripte pr\u00fcfen, dann Encoding starten laufend (ANALYZING/RIPPING/ENCODING) Abbrechen ERROR / CANCELLED Retry Rippen, Disk-Analyse neu starten Zus\u00e4tzlich je nach Job:
Review neu starten Encode neu starten Aus Queue l\u00f6schen "},{"location":"gui/dashboard/#titel-spurprufung-ready_to_encode","title":"Titel-/Spurpr\u00fcfung (READY_TO_ENCODE)","text":"Im selben Block siehst du:
Auswahl des Encode-Titels Audio-/Subtitle-Trackauswahl User-Preset-Auswahl Pre-/Post-Encode-Skripte und Ketten Preview des finalen HandBrakeCLI-Befehls "},{"location":"gui/dashboard/#5-disk-information","title":"5) Disk-Information","text":"Zeigt aktuelles Laufwerk und Disc-Metadaten (Pfad, Modell, Disc-Label, Mount).
Aktionen:
Laufwerk neu lesen Disk neu analysieren Metadaten-Modal \u00f6ffnen "},{"location":"gui/dashboard/#wichtige-dialoge-im-dashboard","title":"Wichtige Dialoge im Dashboard","text":""},{"location":"gui/dashboard/#metadaten-auswahlen","title":"Metadaten ausw\u00e4hlen","text":" OMDb-Suche + Ergebnisliste manuelle Eingabe als Fallback Auswahl \u00fcbernehmen startet den n\u00e4chsten Pipeline-Schritt "},{"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":" Route direkt aufrufen: /database nicht Teil der Standard-Navigation "},{"location":"gui/database/#bereiche","title":"Bereiche","text":""},{"location":"gui/database/#1-historie-datenbank","title":"1) Historie & Datenbank","text":"Tabellarische Jobansicht mit:
ID, Poster, Medium, Titel Status Start/Ende 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:
RAW pr\u00fcfen (Scan der konfigurierten RAW-Pfade) Job anlegen (Orphan-RAW in Historie importieren) "},{"location":"gui/database/#typischer-einsatz","title":"Typischer Einsatz","text":" nach manuellen Dateioperationen nach Migrationen oder Recovery wenn RAW-Dateien vorhanden sind, aber kein Historieneintrag existiert "},{"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:
Suche (Titel/IMDb) Status-Filter Medium-Filter (Blu-ray, DVD, Sonstiges) Sortierung Listen-/Grid-Layout Jeder Eintrag zeigt:
Poster, Titel, Jahr, IMDb Medium-Indikator Status Start/Ende Verf\u00fcgbarkeit von RAW/Movie Ratings (wenn OMDb-Daten vorhanden) Klick auf einen Eintrag \u00f6ffnet die Detailansicht.
"},{"location":"gui/history/#job-detaildialog","title":"Job-Detaildialog","text":"Bereiche:
Film-Infos + OMDb-Details Job-Infos (Status, Pfade, Erfolgsflags, Fehler) hinterlegte Encode-Auswahl ausgef\u00fchrter HandBrake-Befehl strukturierte JSON-Bl\u00f6cke (OMDb/MakeMKV/MediaInfo/EncodePlan/HandBrake) Log-Ladefunktionen (Tail, Vollst\u00e4ndig) "},{"location":"gui/history/#typische-aktionen-im-detaildialog","title":"Typische Aktionen im Detaildialog","text":" OMDb neu zuordnen Encode neu starten Review neu starten RAW neu encodieren RAW l\u00f6schen, Movie l\u00f6schen, Beides l\u00f6schen Historieneintrag l\u00f6schen bei Queue-Lock: Aus Queue l\u00f6schen "},{"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":" Tail laden (800) f\u00fcr schnelle Fehleranalyse Vollst\u00e4ndiges Log laden f\u00fcr vollst\u00e4ndige Nachverfolgung "},{"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:
Werte \u00e4ndern \u00c4nderungen speichern bei Bedarf \u00c4nderungen verwerfen oder Neu laden Zus\u00e4tzlich:
PushOver Test sendet eine Testnachricht \u00c4nderungen werden erst nach Speichern wirksam Tool-Preset-Felder bieten HandBrake-Presetauswahl direkt im Formular "},{"location":"gui/settings/#tab-scripte","title":"Tab Scripte","text":"Funktionen:
Skript anlegen, bearbeiten, l\u00f6schen Skript testen (Test) Reihenfolge per Drag-and-Drop Praxis:
Reihenfolge ist wichtig, weil ausgew\u00e4hlte Skripte sp\u00e4ter sequentiell abgearbeitet werden. Testresultate zeigen Exit-Code, Dauer und stdout/stderr. "},{"location":"gui/settings/#tab-skriptketten","title":"Tab Skriptketten","text":"Funktionen:
Kette anlegen/bearbeiten/l\u00f6schen Kette testen Reihenfolge der Ketten per Drag-and-Drop Im Ketten-Editor:
Bausteine links (Warten, vorhandene Skripte) Schritte rechts per Klick oder Drag-and-Drop hinzuf\u00fcgen Schrittreihenfolge im Canvas \u00e4ndern "},{"location":"gui/settings/#tab-encode-presets","title":"Tab Encode-Presets","text":"Ein Preset b\u00fcndelt:
optional HandBrake-Preset (-Z) optionale Extra-Args Medientyp (Universell, Blu-ray, DVD, Sonstiges) Verwendung:
Diese Presets erscheinen sp\u00e4ter im Dashboard im Review (READY_TO_ENCODE). "},{"location":"gui/settings/#tab-cronjobs","title":"Tab Cronjobs","text":"Funktionen:
Cronjob anlegen und bearbeiten Quelle w\u00e4hlen: Skript oder Skriptkette Cron-Ausdruck validieren Jetzt ausf\u00fchren Logs je Cronjob anzeigen Aktiviert und Pushover toggeln Hilfen:
Beispiele f\u00fcr Cron-Ausdr\u00fccke direkt im Dialog Link zu crontab.guru im Editor "},{"location":"gui/settings/#empfehlung-fur-stabile-nutzung","title":"Empfehlung f\u00fcr stabile Nutzung","text":" Erst Konfiguration sauber setzen dann Skripte/Ketten testen danach Cronjobs aktivieren "},{"location":"pipeline/","title":"Anhang: Pipeline intern","text":"Dieser Abschnitt beschreibt die technische Pipeline-Logik hinter den UI-Workflows.
Workflow & Zust\u00e4nde
Zustandsmodell, \u00dcberg\u00e4nge, Queue-Verhalten.
Workflow
Encode-Planung
Aufbereitung von Titeln/Tracks und Best\u00e4tigungslogik.
Encoding
Playlist-Analyse
Bewertung mehrdeutiger Blu-ray-Playlists.
Playlist-Analyse
Pre-/Post-Encode-Ausf\u00fchrungen
Skript- und Kettenlauf vor/nach dem Encoding.
Encode-Skripte
"},{"location":"pipeline/#zuruck-zum-handbuch","title":"Zur\u00fcck zum Handbuch","text":" Workflows aus Nutzersicht "},{"location":"pipeline/encoding/","title":"Encode-Planung & Track-Auswahl","text":"Ripster erzeugt vor dem Encode einen encodePlan und l\u00e4sst ihn im Review-Panel best\u00e4tigen.
"},{"location":"pipeline/encoding/#ablauf","title":"Ablauf","text":"Quelle bestimmen (Disc/RAW)\n -> HandBrake-Scan (--scan --json)\n -> Plan erstellen (Titel, Audio, Untertitel)\n -> READY_TO_ENCODE\n -> Benutzer best\u00e4tigt Auswahl\n -> finaler HandBrake-Aufruf\n "},{"location":"pipeline/encoding/#review-inhalt-ready_to_encode","title":"Review-Inhalt (READY_TO_ENCODE)","text":" ausw\u00e4hlbarer Encode-Titel Audio-Track-Selektion Untertitel-Track-Selektion inkl. Flags burnIn forced defaultTrack optionale User-Presets (HandBrake-Preset + Extra-Args) optionale Pre-/Post-Skripte und Ketten "},{"location":"pipeline/encoding/#bestatigung-confirm-encode","title":"Best\u00e4tigung (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 Ripster speichert die best\u00e4tigte Auswahl in jobs.encode_plan_json und markiert encode_review_confirmed = 1.
"},{"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:
--subtitle-burned=<id> --subtitle-default=<id> --subtitle-forced=<id> oder --subtitle-forced "},{"location":"pipeline/encoding/#pre-post-encode-ausfuhrungen","title":"Pre-/Post-Encode-Ausf\u00fchrungen","text":" Pre-Encode l\u00e4uft vor HandBrake Post-Encode l\u00e4uft nach HandBrake Verhalten bei Fehlern:
Pre-Encode-Fehler: Job wird als ERROR beendet (Encode startet nicht) Post-Encode-Fehler: Job kann FINISHED bleiben, enth\u00e4lt aber Fehlerhinweis/Script-Summary "},{"location":"pipeline/encoding/#dateinamenordner","title":"Dateinamen/Ordner","text":"Der finale Outputpfad wird aus Settings-Templates aufgebaut.
Platzhalter:
${title} ${year} ${imdbId} Ung\u00fcltige Dateizeichen werden sanitisiert.
"},{"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 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:
Laufzeit Segment-Reihenfolge R\u00fcckw\u00e4rtsspr\u00fcnge/gro\u00dfe Spr\u00fcnge Koh\u00e4renz linearer Segmentfolgen Duplikatgruppen mit \u00e4hnlicher Laufzeit Daraus entstehen:
candidates evaluatedCandidates (inkl. Score/Label) recommendation manualDecisionRequired "},{"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, setzt Ripster manualDecisionRequired = true und wechselt auf:
WAITING_FOR_USER_DECISION Dann muss eine Playlist best\u00e4tigt werden, bevor der Workflow weiterl\u00e4uft.
"},{"location":"pipeline/playlist-analysis/#konfigurationseinfluss","title":"Konfigurationseinfluss","text":"Key Wirkung makemkv_min_length_minutes 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:
mit vorhandenem RAW -> zur\u00fcck zu MEDIAINFO_CHECK ohne RAW -> Startpfad \u00fcber READY_TO_START/RIPPING "},{"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":"READY_TO_ENCODE\n -> Pre-Encode Skripte/Ketten\n -> HandBrake Encoding\n -> Post-Encode Skripte/Ketten\n -> FINISHED oder ERROR\n "},{"location":"pipeline/post-encode-scripts/#auswahl-im-review","title":"Auswahl im Review","text":"Im Review-Panel kannst du getrennt w\u00e4hlen:
selectedPreEncodeScriptIds selectedPostEncodeScriptIds selectedPreEncodeChainIds selectedPostEncodeChainIds "},{"location":"pipeline/post-encode-scripts/#fehlerverhalten","title":"Fehlerverhalten","text":" Pre-Encode-Fehler stoppen die Kette und f\u00fchren zu ERROR. Post-Encode-Fehler stoppen die restlichen Post-Schritte; Job kann dennoch FINISHED sein (mit Fehlerzusatz im Status/Log). "},{"location":"pipeline/post-encode-scripts/#verfugbare-umgebungsvariablen","title":"Verf\u00fcgbare Umgebungsvariablen","text":"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 "},{"location":"pipeline/post-encode-scripts/#skript-ketten","title":"Skript-Ketten","text":"Ketten unterst\u00fctzen zwei Step-Typen:
script (f\u00fchrt ein hinterlegtes Skript aus) wait (wartet waitSeconds) Bei Fehler in einem Script-Step wird die Kette abgebrochen.
"},{"location":"pipeline/post-encode-scripts/#testlaufe","title":"Testl\u00e4ufe","text":" 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.
"},{"location":"pipeline/workflow/","title":"Workflow & Zust\u00e4nde","text":"Ripster steuert den Ablauf als State-Machine im pipelineService.
"},{"location":"pipeline/workflow/#zustandsdiagramm-vereinfacht","title":"Zustandsdiagramm (vereinfacht)","text":"flowchart LR\n IDLE --> DISC_DETECTED\n DISC_DETECTED --> ANALYZING\n ANALYZING --> METADATA_SELECTION\n METADATA_SELECTION --> READY_TO_START\n READY_TO_START --> RIPPING\n READY_TO_START --> MEDIAINFO_CHECK\n MEDIAINFO_CHECK --> WAITING_FOR_USER_DECISION\n WAITING_FOR_USER_DECISION --> MEDIAINFO_CHECK\n MEDIAINFO_CHECK --> READY_TO_ENCODE\n READY_TO_ENCODE --> ENCODING\n ENCODING --> FINISHED\n ENCODING --> ERROR\n RIPPING --> ERROR\n RIPPING --> CANCELLED "},{"location":"pipeline/workflow/#state-liste","title":"State-Liste","text":"State Bedeutung IDLE Wartet auf Disc DISC_DETECTED Disc erkannt ANALYZING MakeMKV-Analyse l\u00e4uft METADATA_SELECTION Benutzer w\u00e4hlt Metadaten WAITING_FOR_USER_DECISION Playlist-Auswahl n\u00f6tig READY_TO_START \u00dcbergangszustand vor Start RIPPING MakeMKV-Rip l\u00e4uft MEDIAINFO_CHECK Quelle/Tracks werden ausgewertet READY_TO_ENCODE Review ist bereit ENCODING HandBrake l\u00e4uft FINISHED erfolgreich abgeschlossen CANCELLED abgebrochen ERROR fehlgeschlagen"},{"location":"pipeline/workflow/#typische-pfade","title":"Typische Pfade","text":""},{"location":"pipeline/workflow/#standardfall-kein-vorhandenes-raw","title":"Standardfall (kein vorhandenes RAW)","text":" Disc erkannt Analyse + Metadaten RIPPING MEDIAINFO_CHECK READY_TO_ENCODE ENCODING FINISHED "},{"location":"pipeline/workflow/#vorhandenes-raw","title":"Vorhandenes RAW","text":"READY_TO_START springt direkt zu MEDIAINFO_CHECK (kein neuer Rip).
"},{"location":"pipeline/workflow/#mehrdeutige-blu-ray-playlist","title":"Mehrdeutige Blu-ray-Playlist","text":"MEDIAINFO_CHECK -> WAITING_FOR_USER_DECISION bis Benutzer Playlist best\u00e4tigt.
"},{"location":"pipeline/workflow/#queue-verhalten","title":"Queue-Verhalten","text":"Wenn pipeline_max_parallel_jobs erreicht ist:
Job-Aktionen werden als Queue-Eintr\u00e4ge abgelegt Queue kann zus\u00e4tzlich Nicht-Job-Eintr\u00e4ge enthalten (script, chain, wait) Reihenfolge ist per API/UI \u00e4nderbar "},{"location":"pipeline/workflow/#abbruch-retry-restart","title":"Abbruch, Retry, Restart","text":" cancel: laufenden Job abbrechen oder Queue-Eintrag entfernen retry: Fehler-/Abbruch-Job neu starten reencode: aus vorhandenem RAW neu encodieren restart-review: Review aus RAW neu aufbauen restart-encode: Encoding mit letzter best\u00e4tigter Auswahl neu starten "},{"location":"tools/","title":"Anhang: Externe Tools","text":"Ripster orchestriert externe CLI-Tools. Dieser Abschnitt erkl\u00e4rt deren Rolle im Gesamtsystem.
MakeMKV
Disc-Analyse und Ripping.
MakeMKV
HandBrake
Video-Encoding inklusive Preset-Logik.
HandBrake
MediaInfo
Track-/Containeranalyse f\u00fcr Review und Auswahl.
MediaInfo
"},{"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:
--subtitle-burned=<id> --subtitle-default=<id> --subtitle-forced=<id> oder --subtitle-forced "},{"location":"tools/handbrake/#presets-auslesen","title":"Presets auslesen","text":"Ripster liest Presets mit:
HandBrakeCLI -z\n "},{"location":"tools/handbrake/#relevante-settings","title":"Relevante Settings","text":"Key Bedeutung handbrake_command CLI-Binary handbrake_preset_bluray / handbrake_preset_dvd profilspezifisches Preset handbrake_extra_args_bluray / handbrake_extra_args_dvd profilspezifische Zusatzargumente output_extension_bluray / output_extension_dvd Ausgabeformat handbrake_restart_delete_incomplete_output 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":" Preset nicht gefunden: Preset-Namen mit HandBrakeCLI -z pr\u00fcfen sehr langsames Encoding: Preset/Extra-Args pr\u00fcfen (z. B. --encoder-preset) 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:
disc:<index> (Auto-Modus) dev:/dev/sr0 (explicit) file:<path> (Datei/Ordner-Analyse) "},{"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 makemkv_registration_key gesetzt ist, f\u00fchrt Ripster vor Analyse/Rip aus:
makemkvcon reg <key>\n "},{"location":"tools/makemkv/#relevante-settings","title":"Relevante Settings","text":"Key Bedeutung makemkv_command CLI-Binary makemkv_source_index Source-Index im Auto-Modus makemkv_min_length_minutes Mindestlaufzeitfilter makemkv_rip_mode_bluray / makemkv_rip_mode_dvd mkv oder backup makemkv_analyze_extra_args_bluray / _dvd Zusatzargs Analyse makemkv_rip_extra_args_bluray / _dvd Zusatzargs Rip"},{"location":"tools/makemkv/#hinweise","title":"Hinweise","text":" Blu-ray-Backups werden oft f\u00fcr robuste Playlist-Analyse genutzt. MakeMKV-Ausgaben werden geparst und als makemkvInfo im Job gespeichert. "},{"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":" Track-/Codec-Metadaten f\u00fcr Review-Plan Fallback-Informationen in bestimmten Analysepfaden Persistenz als mediainfoInfo im Job "},{"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":" JSON-Test: mediainfo --Output=JSON <datei> unbekannte Sprache erscheint oft als und (undetermined) "},{"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":" Dashboard: Disc einlegen, Analyse starten Metadaten im Dialog \u00fcbernehmen bei READY_TO_ENCODE Titel/Tracks pr\u00fcfen Encoding starten Ergebnis in Historie kontrollieren "},{"location":"workflows/#workflow-2-playlist-entscheidung-bei-blu-ray","title":"Workflow 2: Playlist-Entscheidung bei Blu-ray","text":" Job landet in WAITING_FOR_USER_DECISION im Pipeline-Status Playlist-Kandidaten vergleichen gew\u00fcnschte Playlist ausw\u00e4hlen Playlist \u00fcbernehmen danach normal weiter bis READY_TO_ENCODE "},{"location":"workflows/#workflow-3-mehrere-jobs-mit-queue","title":"Workflow 3: Mehrere Jobs mit Queue","text":" Parallel-Limit in Settings setzen (pipeline_max_parallel_jobs) neue Jobs starten; \u00fcbersch\u00fcssige Starts gehen in Job Queue Reihenfolge per Drag-and-Drop anpassen 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:
Metadaten korrigieren: OMDb neu zuordnen gleiche Einstellungen erneut nutzen: Encode neu starten Analyse neu aufbauen: Review neu starten aus RAW erneut encodieren: RAW neu encodieren "},{"location":"workflows/#workflow-5-automatisierung-mit-skripten-und-cron","title":"Workflow 5: Automatisierung mit Skripten und Cron","text":" Settings -> Scripte: Skripte anlegen und testen Settings -> Skriptketten: Ketten bauen und testen im Dashboard-Review Pre-/Post-Ausf\u00fchrungen pro Job ausw\u00e4hlen Settings -> Cronjobs: zeitgesteuerte Ausf\u00fchrung konfigurieren 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":" im Dashboard optional erzeugte RAW/Movie-Datei bereinigen anschlie\u00dfend je nach Ziel: Retry Rippen oder Disk-Analyse neu starten "},{"location":"workflows/#fall-b-job-steht-in-ready_to_encode-ist-aber-nicht-aktive-session","title":"Fall B: Job steht in READY_TO_ENCODE, ist aber nicht aktive Session","text":" in Historie oder Database: Im Dashboard \u00f6ffnen im Dashboard Review erneut pr\u00fcfen und starten "},{"location":"workflows/#fall-c-raw-ohne-historieneintrag","title":"Fall C: RAW ohne Historieneintrag","text":" /database \u00f6ffnen Bereich RAW ohne Historie Job anlegen "}]}
\ No newline at end of file
+{"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":" Voraussetzungen pr\u00fcfen und installieren: Installation Grundkonfiguration in der UI setzen: Ersteinrichtung Ersten vollst\u00e4ndigen Job durchlaufen: Erster Lauf "},{"location":"#was-du-hier-findest","title":"Was du hier findest","text":" Benutzerhandbuch Installation GUI-Seiten im Detail (Dashboard, Settings, Historie, Database) typische Arbeitsabl\u00e4ufe aus Anwendersicht Technischer Anhang vollst\u00e4ndige Einstellungsreferenz Pipeline-/API-/Architekturdetails Deployment und Tool-Hintergr\u00fcnde "},{"location":"#empfohlene-lesereihenfolge","title":"Empfohlene Lesereihenfolge","text":" Benutzerhandbuch \u00dcberblick GUI-Seiten Workflows aus Nutzersicht 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":" Health
Service-Liveness.
GET /api/health
Pipeline API
Analyse, Start/Retry/Cancel, Queue, Re-Encode.
Pipeline API
Settings API
Einstellungen, Skripte/Ketten, User-Presets.
Settings API
History API
Job-Historie, Orphan-Import, L\u00f6schoperationen.
History API
Cron API
Zeitgesteuerte Skript-/Kettenausf\u00fchrung.
Cron API
WebSocket Events
Pipeline-, Queue-, Disk-, Settings-, Cron- und Monitoring-Events.
WebSocket
"},{"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:
0 2 * * * t\u00e4glich 02:00 */15 * * * * alle 15 Minuten 0 6 * * 1-5 Mo-Fr 06:00 "},{"location":"api/crons/#websocket-events-zu-cron","title":"WebSocket-Events zu Cron","text":" CRON_JOBS_UPDATED bei Create/Update/Delete CRON_JOB_UPDATED bei Laufzeitstatus (running -> success|error) "},{"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":" Ein aktiver Pipeline-Job kann nicht gel\u00f6scht werden (409). Alle L\u00f6schoperationen sind irreversibel. "},{"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.
Aktive Aktivit\u00e4ten (active): Laufen gerade. Letzte Aktivit\u00e4ten (recent): Abgeschlossen, max. 120 Eintr\u00e4ge. \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:
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 "},{"location":"api/settings/#skript-ketten","title":"Skript-Ketten","text":"Basis: /api/settings/script-chains
Eine Kette hat Schritte vom Typ:
script (scriptId erforderlich) wait (waitSeconds 1..3600) "},{"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:
Retry-Intervall: 1500ms Wiederverbindung bis Komponente unmounted wird "},{"location":"appendix/","title":"Technischer Anhang","text":"Dieser Bereich enth\u00e4lt die technische Referenz hinter dem Benutzerhandbuch.
"},{"location":"appendix/#inhalt","title":"Inhalt","text":" Konfiguration komplette Feldreferenz Umgebungsvariablen Pipeline intern Zustandsmodell Encode-Planung Playlist-Analyse Pre-/Post-Encode-Ausf\u00fchrungen API-Referenz REST-Endpunkte WebSocket-Events Architektur Backend-/Frontend-Aufbau Datenbank Deployment Betrieb in Entwicklung und Produktion Externe Tools MakeMKV, HandBrake, MediaInfo "},{"location":"appendix/#wann-du-in-den-anhang-wechselst","title":"Wann du in den Anhang wechselst","text":" du integrierst Ripster mit anderen Systemen du betreibst mehrere Instanzen oder willst tiefer debuggen du brauchst Feld-/API-/Schema-Details f\u00fcr Automatisierung "},{"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":" \u00dcbersicht Backend-Services Frontend-Komponenten Datenbank "},{"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:
Pipeline-State-Machine + Persistenz (pipeline_state) Disc-Analyse/Rip/Review/Encode Queue-Management (Jobs + script|chain|wait Eintr\u00e4ge) Retry/Re-Encode/Restart-Flows WebSocket-Broadcasts f\u00fcr State/Progress/Queue Wichtige Methoden:
analyzeDisc() selectMetadata() startPreparedJob() confirmEncodeReview() cancel() retry() reencodeFromRaw() restartReviewFromRaw() restartEncodeWithLastSettings() resumeReadyToEncodeJob() enqueueNonJobEntry(), reorderQueue(), removeQueueEntry() "},{"location":"architecture/backend/#diskdetectionservicejs","title":"diskDetectionService.js","text":"Pollt Laufwerk(e) und emittiert:
discInserted discRemoved error Zusatz:
Modus auto oder explicit heuristische mediaProfile-Erkennung (bluray/dvd/other) rescanAndEmit() f\u00fcr manuellen Trigger "},{"location":"architecture/backend/#settingsservicejs","title":"settingsService.js","text":"Settings-Layer mit Validation/Serialisierung.
Features:
getCategorizedSettings() f\u00fcr UI-Form setSettingValue() / setSettingsBulk() profilspezifische Aufl\u00f6sung (resolveEffectiveToolSettings) CLI-Config-Building f\u00fcr MakeMKV/HandBrake/MediaInfo HandBrake-Preset-Liste via HandBrakeCLI -z MakeMKV-Registration-Command aus makemkv_registration_key "},{"location":"architecture/backend/#historyservicejs","title":"historyService.js","text":"Historie + Dateioperationen.
Features:
Job-Liste/Detail inkl. Log-Tail Orphan-RAW-Erkennung und Import OMDb-Nachzuweisung Dateil\u00f6schung (raw|movie|both) Job-L\u00f6schung (none|raw|movie|both) "},{"location":"architecture/backend/#cronservicejs","title":"cronService.js","text":"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 "},{"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:
startActivity(type, payload) \u2192 Aktivit\u00e4t registrieren, ID zur\u00fcckgeben updateActivity(id, patch) \u2192 Laufende Aktivit\u00e4t aktualisieren completeActivity(id, payload) \u2192 Aktivit\u00e4t abschlie\u00dfen und in recent verschieben setControls(id, { cancel, nextStep }) \u2192 Steuer-Handler registrieren (f\u00fcr canCancel/canNextStep) requestCancel(id) / requestNextStep(id) \u2192 Steuer-Handler aufrufen clearRecent() \u2192 Abgeschlossene Aktivit\u00e4ten l\u00f6schen getSnapshot() \u2192 Snapshot mit active + recent + updatedAt Broadcasts RUNTIME_ACTIVITY_CHANGED \u00fcber WebSocket bei jeder \u00c4nderung Limits:
recent max. 120 Eintr\u00e4ge stdout/stderr/output max. 12.000 Zeichen message/errorMessage max. 2.000 Zeichen Vollst\u00e4ndige API-Dokumentation: Runtime Activities API
"},{"location":"architecture/backend/#weitere-services","title":"Weitere Services","text":" scriptService.js (CRUD + Test + Wrapper-Ausf\u00fchrung) scriptChainService.js (CRUD + Step-Execution) userPresetService.js (HandBrake User-Presets) hardwareMonitorService.js (CPU/RAM/GPU/Storage) websocketService.js (Client-Registry + Broadcast) notificationService.js (PushOver) logger.js (rotierende Datei-Logs) "},{"location":"architecture/backend/#bootstrapping-srcindexjs","title":"Bootstrapping (src/index.js)","text":"Beim Start:
DB init/migrate Pipeline-Init Cron-Init Express-Routes + Error-Handler WebSocket-Server auf /ws Hardware-Monitoring-Init 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:
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 Audit: created_at, updated_at "},{"location":"architecture/database/#pipeline_state","title":"pipeline_state","text":"Singleton-Tabelle (id = 1) f\u00fcr aktiven Snapshot:
state active_job_id progress eta status_text context_json updated_at "},{"location":"architecture/database/#settings_schema-settings_values","title":"settings_schema + settings_values","text":" settings_schema: Definition (Typ, Default, Validation, Reihenfolge) settings_values: aktueller Wert pro Key "},{"location":"architecture/database/#scripts-script_chains-script_chain_steps","title":"scripts, script_chains, script_chain_steps","text":" 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 "},{"location":"architecture/database/#user_presets","title":"user_presets","text":"Benannte HandBrake-Preset-Sets:
name media_type (bluray|dvd|other|all) handbrake_preset extra_args description "},{"location":"architecture/database/#cron_jobs-cron_run_logs","title":"cron_jobs + cron_run_logs","text":" cron_jobs: Zeitplan + Status cron_run_logs: einzelne L\u00e4ufe status: running|success|error output error_message "},{"location":"architecture/database/#migrationrecovery","title":"Migration/Recovery","text":"Beim Start werden Schema und Settings-Metadaten automatisch abgeglichen.
Bei korruptem SQLite-File:
Datei wird nach backend/data/corrupt-backups/ verschoben neue DB wird initialisiert 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:
Status/Progress/ETA Metadaten-Dialog Playlist-Entscheidung Review-Panel Queue-Interaktion (reorder/add/remove) Job-Aktionen (Start/Cancel/Retry/Re-Encode) Hardware-Monitoring-Anzeige "},{"location":"architecture/frontend/#settingspagejsx","title":"SettingsPage.jsx","text":"Konfiguration:
dynamisches Settings-Formular (DynamicSettingsForm) Skripte/Ketten inkl. Reorder/Test User-Presets Cron-Jobs (CronJobsTab) "},{"location":"architecture/frontend/#historypagejsx","title":"HistoryPage.jsx","text":"Historie:
Job-Liste/Filter Job-Details + Logs OMDb-Nachzuweisung Re-Encode/Restart-Workflows "},{"location":"architecture/frontend/#wichtige-komponenten","title":"Wichtige Komponenten","text":" PipelineStatusCard.jsx MetadataSelectionDialog.jsx MediaInfoReviewPanel.jsx JobDetailDialog.jsx CronJobsTab.jsx "},{"location":"architecture/frontend/#api-client-apiclientjs","title":"API-Client (api/client.js)","text":" zentraler request() mit JSON-Handling Fehlerobjekt aus API wird auf Error(message) gemappt VITE_API_BASE default /api "},{"location":"architecture/frontend/#websocket-hooksusewebsocketjs","title":"WebSocket (hooks/useWebSocket.js)","text":" 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 DISC_DETECTED / DISC_REMOVED HARDWARE_MONITOR_UPDATE "},{"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:
PIPELINE_STATE_CHANGED, PIPELINE_PROGRESS, PIPELINE_QUEUE_CHANGED DISC_DETECTED, DISC_REMOVED 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 "},{"location":"architecture/overview/#prozessausfuhrung","title":"Prozessausf\u00fchrung","text":"Externe Tools werden als Child-Processes gestartet (processRunner):
Streaming von stdout/stderr Progress-Parsing (progressParsers.js) kontrollierter Abbruch (SIGINT/SIGKILL-Fallback) "},{"location":"architecture/overview/#persistenz","title":"Persistenz","text":"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\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 (ERROR oder CANCELLED) und k\u00f6nnen erneut gestartet werden.
"},{"location":"architecture/overview/#cors-runtime-konfig","title":"CORS & Runtime-Konfig","text":" CORS_ORIGIN default: * LOG_LEVEL default: info DB-/Log-Pfade \u00fcber DB_PATH/LOG_DIR konfigurierbar "},{"location":"configuration/","title":"Anhang: Konfiguration","text":"Dieser Abschnitt ist die technische Referenz zu allen Konfigurationsarten in Ripster.
"},{"location":"configuration/#inhalte","title":"Inhalte","text":" Einstellungsreferenz
Vollst\u00e4ndige Liste aller UI-Settings (Typ, Default, Hinweise).
Einstellungsreferenz
Umgebungsvariablen
backend/.env und frontend/.env inkl. Priorit\u00e4ten.
Umgebungsvariablen
"},{"location":"configuration/#zuruck-zum-handbuch","title":"Zur\u00fcck zum Handbuch","text":" Benutzerhandbuch \u00dcberblick "},{"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":" Prozess-Umgebungsvariablen .env Code-Defaults "},{"location":"configuration/settings-reference/","title":"Einstellungsreferenz","text":"Alle Settings liegen in settings_schema/settings_values und werden \u00fcber die UI verwaltet.
"},{"location":"configuration/settings-reference/#profil-system","title":"Profil-System","text":"Ripster arbeitet mit Media-Profilen:
Viele Tool-/Pfad-Settings existieren als Profil-Varianten (*_bluray, *_dvd, *_other).
Wichtig:
F\u00fcr raw_dir, movie_dir und die zugeh\u00f6rigen *_owner-Keys gibt es kein Cross-Profil-Fallback. F\u00fcr viele Tool-Keys werden profilspezifische Varianten bevorzugt. "},{"location":"configuration/settings-reference/#template-platzhalter","title":"Template-Platzhalter","text":"Datei-/Ordner-Templates unterst\u00fctzen:
${title} ${year} ${imdbId} Nicht gesetzte Werte werden zu unknown.
"},{"location":"configuration/settings-reference/#kategorie-pfade","title":"Kategorie: Pfade","text":"Key Typ Default raw_dir path data/output/raw raw_dir_bluray path null raw_dir_dvd path null raw_dir_other path null raw_dir_bluray_owner string null raw_dir_dvd_owner string null raw_dir_other_owner string null movie_dir path data/output/movies movie_dir_bluray path null movie_dir_dvd path null movie_dir_other path null movie_dir_bluray_owner string null movie_dir_dvd_owner string null movie_dir_other_owner string null log_dir path data/logs"},{"location":"configuration/settings-reference/#kategorie-laufwerk","title":"Kategorie: Laufwerk","text":"Key Typ Default Hinweis drive_mode select auto auto oder explicit drive_device path /dev/sr0 bei explicit relevant makemkv_source_index number 0 MakeMKV Source-Index disc_poll_interval_ms number 4000 1000..60000"},{"location":"configuration/settings-reference/#kategorie-monitoring","title":"Kategorie: Monitoring","text":"Key Typ Default hardware_monitoring_enabled boolean true hardware_monitoring_interval_ms number 5000"},{"location":"configuration/settings-reference/#kategorie-tools-global","title":"Kategorie: Tools (global)","text":"Key Typ Default makemkv_command string makemkvcon makemkv_registration_key string null mediainfo_command string mediainfo makemkv_min_length_minutes number 60 handbrake_command string HandBrakeCLI handbrake_restart_delete_incomplete_output boolean true pipeline_max_parallel_jobs number 1"},{"location":"configuration/settings-reference/#blu-ray-spezifisch","title":"Blu-ray-spezifisch","text":"Key Typ Default mediainfo_extra_args_bluray string null makemkv_rip_mode_bluray select backup makemkv_analyze_extra_args_bluray string null makemkv_rip_extra_args_bluray string null handbrake_preset_bluray string H.264 MKV 1080p30 handbrake_extra_args_bluray string null output_extension_bluray select mkv filename_template_bluray string ${title} (${year}) output_folder_template_bluray string null"},{"location":"configuration/settings-reference/#dvd-spezifisch","title":"DVD-spezifisch","text":"Key Typ Default mediainfo_extra_args_dvd string null makemkv_rip_mode_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 output_extension_dvd select mkv filename_template_dvd string ${title} (${year}) output_folder_template_dvd string null"},{"location":"configuration/settings-reference/#kategorie-metadaten","title":"Kategorie: Metadaten","text":"Key Typ Default omdb_api_key string null omdb_default_type select movie"},{"location":"configuration/settings-reference/#kategorie-benachrichtigungen-pushover","title":"Kategorie: Benachrichtigungen (PushOver)","text":"Key Typ Default pushover_enabled boolean false pushover_token string null pushover_user string null pushover_device string null pushover_title_prefix string Ripster pushover_priority number 0 pushover_timeout_ms number 7000 pushover_notify_metadata_ready boolean true pushover_notify_rip_started boolean true pushover_notify_encoding_started boolean true pushover_notify_job_finished boolean true pushover_notify_job_error boolean true pushover_notify_job_cancelled boolean true pushover_notify_reencode_started boolean true pushover_notify_reencode_finished boolean true"},{"location":"configuration/settings-reference/#entfernte-legacy-keys","title":"Entfernte Legacy-Keys","text":"Diese Legacy-Keys werden bei Migration entfernt und sollten nicht mehr genutzt werden:
makemkv_backup_mode mediainfo_extra_args makemkv_rip_mode makemkv_analyze_extra_args makemkv_rip_extra_args handbrake_preset handbrake_extra_args output_extension filename_template output_folder_template pushover_notify_disc_detected "},{"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":" Node.js >= 20.19.0 externe Tools installiert (makemkvcon, HandBrakeCLI, mediainfo) "},{"location":"deployment/development/#schnellstart","title":"Schnellstart","text":"./start.sh\n Startet:
Backend (http://localhost:3001, mit nodemon) Frontend (http://localhost:5173, mit Vite HMR) 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:
/api -> http://127.0.0.1:3001 /ws -> ws://127.0.0.1:3001 "},{"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 auf Debian/Ubuntu ein \u2013 inklusive Node.js, MakeMKV, HandBrake, nginx und systemd-Dienst.
Unterst\u00fctzte Systeme: Debian 11/12, Ubuntu 22.04/24.04 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> main 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":" Systempr\u00fcfung \u2013 OS-Erkennung und Root-Check Systempakete \u2013 curl, wget, git, mediainfo, udev u. a. Node.js 20 \u2013 via NodeSource, falls noch nicht installiert MakeMKV \u2013 aktuelle Version wird aus dem offiziellen Forum ermittelt und aus dem Quellcode kompiliert (kann mit --no-makemkv \u00fcbersprungen werden) HandBrake \u2013 interaktive Auswahl: Option 1: Standard (apt install handbrake-cli) Option 2: Geb\u00fcndelte GPU-Version mit NVDEC aus bin/HandBrakeCLI Systembenutzer ripster \u2013 ohne Login-Shell, Gruppen: cdrom, optical, disk, video, render Repository \u2013 klont Branch nach --dir (bei --reinstall: sichert DB, pullt, stellt DB wieder her) npm-Abh\u00e4ngigkeiten \u2013 Root, Backend (nur production), Frontend Frontend-Build \u2013 npm run build mit relativen API-URLs (nginx-kompatibel) Backend .env \u2013 wird automatisch generiert (bei --reinstall bleibt bestehende erhalten) Berechtigungen \u2013 ripster:ripster auf Installationsverzeichnis, 600 auf .env systemd-Dienst \u2013 ripster-backend.service erstellt, aktiviert und gestartet 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":" Ripster hat keine eingebaute Authentifizierung. F\u00fcr externen Zugriff mindestens Basic Auth + TLS + Netzwerksegmentierung/VPN einsetzen. Secrets nicht ins Repo committen (.env, Settings-Felder). "},{"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":" Anwender, die Discs verarbeiten wollen Betreiber, die den t\u00e4glichen Ablauf stabil fahren m\u00f6chten Power-User, die Queue/Skripte/Cron im UI steuern m\u00f6chten "},{"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":" Voraussetzungen Installation Ersteinrichtung Erster Lauf "},{"location":"getting-started/#wenn-ripster-bereits-lauft","title":"Wenn Ripster bereits l\u00e4uft","text":" GUI-Seiten Workflows 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_dir, movie_dir, log_dir Tools makemkv_command, handbrake_command, mediainfo_command Metadaten omdb_api_key, optional omdb_default_type 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:
*_bluray *_dvd optional *_other Typische Beispiele:
handbrake_preset_bluray und handbrake_preset_dvd raw_dir_bluray und raw_dir_dvd filename_template_bluray und filename_template_dvd "},{"location":"getting-started/configuration/#3-queue-und-monitoring-festlegen","title":"3. Queue und Monitoring festlegen","text":" pipeline_max_parallel_jobs f\u00fcr parallele Jobs hardware_monitoring_enabled und Intervall f\u00fcr Live-Metriken im Dashboard "},{"location":"getting-started/configuration/#4-optional-push-benachrichtigungen","title":"4. Optional: Push-Benachrichtigungen","text":"In den Benachrichtigungsfeldern setzen:
pushover_enabled pushover_token pushover_user Dann \u00fcber PushOver Test direkt pr\u00fcfen.
"},{"location":"getting-started/configuration/#2-minuten-funktionstest","title":"2-Minuten-Funktionstest","text":" Dashboard \u00f6ffnen Disc einlegen Analyse starten Metadaten \u00fcbernehmen Bis READY_TO_ENCODE 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":" Feld mit Fehler markieren lassen (rote Validierung im Formular) Pfadangaben und numerische Werte pr\u00fcfen bei Tool-Pfaden direkt CLI-Aufruf im Terminal testen "},{"location":"getting-started/configuration/#weiter","title":"Weiter","text":" Erster Lauf GUI-Seiten im Detail "},{"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. install.sh installiert die ben\u00f6tigten Abh\u00e4ngigkeiten automatisch (au\u00dfer du \u00fcberspringst sie mit --no-*).
"},{"location":"getting-started/installation/#zielbild-nach-der-installation","title":"Zielbild nach der Installation","text":" Ripster-Backend als systemd-Dienst Frontend \u00fcber nginx erreichbar UI auf http://<Server-IP> "},{"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 wirst du nach dem HandBrake-Modus gefragt:
1 Standard (apt) 2 GPU/NVDEC (geb\u00fcndeltes Binary) "},{"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":" Mit nginx: http://<Server-IP> Ohne nginx (--no-nginx): API auf http://<Server-IP>:3001/api "},{"location":"getting-started/installation/#wichtige-optionen","title":"Wichtige Optionen","text":"Option Zweck --branch <branch> anderen Branch installieren --dir <pfad> Installationsverzeichnis \u00e4ndern --port <port> Backend-Port setzen --host <hostname> Hostname/IP f\u00fcr nginx/CORS --no-makemkv MakeMKV nicht installieren --no-handbrake HandBrake nicht installieren --no-nginx nginx-Konfiguration \u00fcberspringen --reinstall Update einer bestehenden Installation 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":" Permission denied am Laufwerk: Laufwerksrechte/Gruppen pr\u00fcfen Tools nicht gefunden: makemkvcon, HandBrakeCLI, mediainfo im PATH pr\u00fcfen UI nicht erreichbar: nginx-Status und Port/Firewall pr\u00fcfen "},{"location":"getting-started/installation/#danach-weiter","title":"Danach weiter","text":" Ersteinrichtung 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":" unterst\u00fctztes Linux-System (Debian/Ubuntu) root-Rechte Internetzugang w\u00e4hrend der Installation optisches Laufwerk f\u00fcr Disc-Betrieb 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":" OMDb API-Key (kann auch nach Installation in den Settings gesetzt werden) PushOver-Zugangsdaten (optional) "},{"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:
Node.js >= 20.19.0 makemkvcon, HandBrakeCLI, mediainfo im PATH Details: Entwicklungsumgebung
"},{"location":"getting-started/prerequisites/#abschluss-checkliste","title":"Abschluss-Checkliste","text":" [ ] Produktionsbetrieb: Linux + root + Internet + Laufwerk vorhanden [ ] Dev-Modus (nur falls ben\u00f6tigt): Node.js und CLI-Tools verf\u00fcgbar "},{"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:
Status wechselt auf DISC_DETECTED bzw. Medium erkannt im Bereich Disk-Information sind Laufwerksdaten sichtbar Wenn nichts passiert: Laufwerk neu lesen.
"},{"location":"getting-started/quickstart/#2-analyse-starten","title":"2. Analyse starten","text":"Aktion im Dashboard:
Erwartung:
Status ANALYZING danach Metadaten-Dialog "},{"location":"getting-started/quickstart/#3-metadaten-auswahlen","title":"3. Metadaten ausw\u00e4hlen","text":"Im Dialog Metadaten ausw\u00e4hlen:
OMDb-Suche nutzen oder manuell eintragen passenden Treffer markieren Auswahl \u00fcbernehmen "},{"location":"getting-started/quickstart/#4-auf-den-nachsten-zustand-reagieren","title":"4. Auf den n\u00e4chsten Zustand reagieren","text":" Normalfall ohne vorhandenes RAW: RIPPING -> MEDIAINFO_CHECK -> READY_TO_ENCODE bei vorhandenem RAW: direkt MEDIAINFO_CHECK -> READY_TO_ENCODE bei unklarer Blu-ray-Playlist: WAITING_FOR_USER_DECISION (Playlist ausw\u00e4hlen und \u00fcbernehmen) "},{"location":"getting-started/quickstart/#5-review-in-ready_to_encode","title":"5. Review in READY_TO_ENCODE","text":"Im aufgeklappten Job (Pipeline-Status):
Encode-Titel w\u00e4hlen Audio-/Subtitle-Spuren pr\u00fcfen optional User-Preset ausw\u00e4hlen optional Pre-/Post-Skripte bzw. Ketten hinzuf\u00fcgen Dann Encoding starten.
"},{"location":"getting-started/quickstart/#6-encoding-uberwachen","title":"6. Encoding \u00fcberwachen","text":"W\u00e4hrend ENCODING:
Fortschritt + ETA im Dashboard Live-Log im Pipeline-Status Queue- und Skript/Cron-Status parallel beobachtbar "},{"location":"getting-started/quickstart/#7-ergebnis-prufen","title":"7. Ergebnis pr\u00fcfen","text":"Bei FINISHED:
Seite Historie \u00f6ffnen Job in Details \u00f6ffnen Output-Pfad, Status und Log pr\u00fcfen "},{"location":"getting-started/quickstart/#typische-folgeaktionen","title":"Typische Folgeaktionen","text":" Falsches OMDb-Match: in Historie -> OMDb neu zuordnen Neue Encodierung aus RAW: RAW neu encodieren Pr\u00fcfung komplett neu aufbauen: Review neu starten "},{"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":" Start eines neuen Jobs: Dashboard Regeln/Automatisierung anpassen: Settings Ergebnisse pr\u00fcfen oder Jobs nachbearbeiten: Historie Sonderf\u00e4lle/Recovery: Database "},{"location":"gui/#hinweise-zur-navigation","title":"Hinweise zur Navigation","text":" Dashboard, Settings, Historie sind direkt in der Kopfnavigation. Database ist als Expert-Route verf\u00fcgbar: /database. "},{"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:
Hardware Monitoring Job Queue Skript- / Cron-Status Job \u00dcbersicht Disk-Information "},{"location":"gui/dashboard/#1-hardware-monitoring","title":"1) Hardware Monitoring","text":"Zeigt live:
CPU (gesamt + optional pro Kern) RAM GPU-Auslastung/Temperatur/VRAM freien Speicher in den konfigurierten Pfaden Wichtig f\u00fcr den Betrieb:
Hohe Speicherauslastung oder fast volle Zielpfade fr\u00fch erkennen \u00fcber Settings aktivierbar/deaktivierbar (hardware_monitoring_*) "},{"location":"gui/dashboard/#2-job-queue","title":"2) Job Queue","text":"Zwei Spalten:
Laufende Jobs Warteschlange M\u00f6gliche Aktionen:
Queue per Drag-and-Drop umsortieren Queue-Job entfernen (X) zus\u00e4tzliche Queue-Elemente einf\u00fcgen (+): Skript Skriptkette Wartezeit Hinweis:
Parallel zeigt das aktuell konfigurierte Parallel-Limit (pipeline_max_parallel_jobs). "},{"location":"gui/dashboard/#3-skript-cron-status","title":"3) Skript- / Cron-Status","text":"Zeigt:
aktive Ausf\u00fchrungen (Skripte, Ketten, Cron) zuletzt abgeschlossene Ausf\u00fchrungen M\u00f6gliche Aktionen:
laufende Ketten: N\u00e4chster Schritt laufende Eintr\u00e4ge: Abbrechen Historie der Aktivit\u00e4ten: Liste leeren "},{"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 DISC_DETECTED / IDLE Analyse starten METADATA_SELECTION Metadaten \u00f6ffnen WAITING_FOR_USER_DECISION Playlist w\u00e4hlen und Playlist \u00fcbernehmen READY_TO_START Job starten READY_TO_ENCODE Tracks/Skripte pr\u00fcfen, dann Encoding starten laufend (ANALYZING/RIPPING/ENCODING) Abbrechen ERROR / CANCELLED Retry Rippen, Disk-Analyse neu starten Zus\u00e4tzlich je nach Job:
Review neu starten Encode neu starten Aus Queue l\u00f6schen "},{"location":"gui/dashboard/#titel-spurprufung-ready_to_encode","title":"Titel-/Spurpr\u00fcfung (READY_TO_ENCODE)","text":"Im selben Block siehst du:
Auswahl des Encode-Titels Audio-/Subtitle-Trackauswahl User-Preset-Auswahl Pre-/Post-Encode-Skripte und Ketten Preview des finalen HandBrakeCLI-Befehls "},{"location":"gui/dashboard/#5-disk-information","title":"5) Disk-Information","text":"Zeigt aktuelles Laufwerk und Disc-Metadaten (Pfad, Modell, Disc-Label, Mount).
Aktionen:
Laufwerk neu lesen Disk neu analysieren Metadaten-Modal \u00f6ffnen "},{"location":"gui/dashboard/#wichtige-dialoge-im-dashboard","title":"Wichtige Dialoge im Dashboard","text":""},{"location":"gui/dashboard/#metadaten-auswahlen","title":"Metadaten ausw\u00e4hlen","text":" OMDb-Suche + Ergebnisliste manuelle Eingabe als Fallback Auswahl \u00fcbernehmen startet den n\u00e4chsten Pipeline-Schritt "},{"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":" Route direkt aufrufen: /database nicht Teil der Standard-Navigation "},{"location":"gui/database/#bereiche","title":"Bereiche","text":""},{"location":"gui/database/#1-historie-datenbank","title":"1) Historie & Datenbank","text":"Tabellarische Jobansicht mit:
ID, Poster, Medium, Titel Status Start/Ende 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:
RAW pr\u00fcfen (Scan der konfigurierten RAW-Pfade) Job anlegen (Orphan-RAW in Historie importieren) "},{"location":"gui/database/#typischer-einsatz","title":"Typischer Einsatz","text":" nach manuellen Dateioperationen nach Migrationen oder Recovery wenn RAW-Dateien vorhanden sind, aber kein Historieneintrag existiert "},{"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:
Suche (Titel/IMDb) Status-Filter Medium-Filter (Blu-ray, DVD, Sonstiges) Sortierung Listen-/Grid-Layout Jeder Eintrag zeigt:
Poster, Titel, Jahr, IMDb Medium-Indikator Status Start/Ende Verf\u00fcgbarkeit von RAW/Movie Ratings (wenn OMDb-Daten vorhanden) Klick auf einen Eintrag \u00f6ffnet die Detailansicht.
"},{"location":"gui/history/#job-detaildialog","title":"Job-Detaildialog","text":"Bereiche:
Film-Infos + OMDb-Details Job-Infos (Status, Pfade, Erfolgsflags, Fehler) hinterlegte Encode-Auswahl ausgef\u00fchrter HandBrake-Befehl strukturierte JSON-Bl\u00f6cke (OMDb/MakeMKV/MediaInfo/EncodePlan/HandBrake) Log-Ladefunktionen (Tail, Vollst\u00e4ndig) "},{"location":"gui/history/#typische-aktionen-im-detaildialog","title":"Typische Aktionen im Detaildialog","text":" OMDb neu zuordnen Encode neu starten Review neu starten RAW neu encodieren RAW l\u00f6schen, Movie l\u00f6schen, Beides l\u00f6schen Historieneintrag l\u00f6schen bei Queue-Lock: Aus Queue l\u00f6schen "},{"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":" Tail laden (800) f\u00fcr schnelle Fehleranalyse Vollst\u00e4ndiges Log laden f\u00fcr vollst\u00e4ndige Nachverfolgung "},{"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:
Werte \u00e4ndern \u00c4nderungen speichern bei Bedarf \u00c4nderungen verwerfen oder Neu laden Zus\u00e4tzlich:
PushOver Test sendet eine Testnachricht \u00c4nderungen werden erst nach Speichern wirksam Tool-Preset-Felder bieten HandBrake-Presetauswahl direkt im Formular "},{"location":"gui/settings/#tab-scripte","title":"Tab Scripte","text":"Funktionen:
Skript anlegen, bearbeiten, l\u00f6schen Skript testen (Test) Reihenfolge per Drag-and-Drop Praxis:
Reihenfolge ist wichtig, weil ausgew\u00e4hlte Skripte sp\u00e4ter sequentiell abgearbeitet werden. Testresultate zeigen Exit-Code, Dauer und stdout/stderr. "},{"location":"gui/settings/#tab-skriptketten","title":"Tab Skriptketten","text":"Funktionen:
Kette anlegen/bearbeiten/l\u00f6schen Kette testen Reihenfolge der Ketten per Drag-and-Drop Im Ketten-Editor:
Bausteine links (Warten, vorhandene Skripte) Schritte rechts per Klick oder Drag-and-Drop hinzuf\u00fcgen Schrittreihenfolge im Canvas \u00e4ndern "},{"location":"gui/settings/#tab-encode-presets","title":"Tab Encode-Presets","text":"Ein Preset b\u00fcndelt:
optional HandBrake-Preset (-Z) optionale Extra-Args Medientyp (Universell, Blu-ray, DVD, Sonstiges) Verwendung:
Diese Presets erscheinen sp\u00e4ter im Dashboard im Review (READY_TO_ENCODE). "},{"location":"gui/settings/#tab-cronjobs","title":"Tab Cronjobs","text":"Funktionen:
Cronjob anlegen und bearbeiten Quelle w\u00e4hlen: Skript oder Skriptkette Cron-Ausdruck validieren Jetzt ausf\u00fchren Logs je Cronjob anzeigen Aktiviert und Pushover toggeln Hilfen:
Beispiele f\u00fcr Cron-Ausdr\u00fccke direkt im Dialog Link zu crontab.guru im Editor "},{"location":"gui/settings/#empfehlung-fur-stabile-nutzung","title":"Empfehlung f\u00fcr stabile Nutzung","text":" Erst Konfiguration sauber setzen dann Skripte/Ketten testen danach Cronjobs aktivieren "},{"location":"pipeline/","title":"Anhang: Pipeline intern","text":"Dieser Abschnitt beschreibt die technische Pipeline-Logik hinter den UI-Workflows.
Workflow & Zust\u00e4nde
Zustandsmodell, \u00dcberg\u00e4nge, Queue-Verhalten.
Workflow
Encode-Planung
Aufbereitung von Titeln/Tracks und Best\u00e4tigungslogik.
Encoding
Playlist-Analyse
Bewertung mehrdeutiger Blu-ray-Playlists.
Playlist-Analyse
Pre-/Post-Encode-Ausf\u00fchrungen
Skript- und Kettenlauf vor/nach dem Encoding.
Encode-Skripte
"},{"location":"pipeline/#zuruck-zum-handbuch","title":"Zur\u00fcck zum Handbuch","text":" Workflows aus Nutzersicht "},{"location":"pipeline/encoding/","title":"Encode-Planung & Track-Auswahl","text":"Ripster erzeugt vor dem Encode einen encodePlan und l\u00e4sst ihn im Review-Panel best\u00e4tigen.
"},{"location":"pipeline/encoding/#ablauf","title":"Ablauf","text":"Quelle bestimmen (Disc/RAW)\n -> HandBrake-Scan (--scan --json)\n -> Plan erstellen (Titel, Audio, Untertitel)\n -> READY_TO_ENCODE\n -> Benutzer best\u00e4tigt Auswahl\n -> finaler HandBrake-Aufruf\n "},{"location":"pipeline/encoding/#review-inhalt-ready_to_encode","title":"Review-Inhalt (READY_TO_ENCODE)","text":" ausw\u00e4hlbarer Encode-Titel Audio-Track-Selektion Untertitel-Track-Selektion inkl. Flags burnIn forced defaultTrack optionale User-Presets (HandBrake-Preset + Extra-Args) optionale Pre-/Post-Skripte und Ketten "},{"location":"pipeline/encoding/#bestatigung-confirm-encode","title":"Best\u00e4tigung (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 Ripster speichert die best\u00e4tigte Auswahl in jobs.encode_plan_json und markiert encode_review_confirmed = 1.
"},{"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:
--subtitle-burned=<id> --subtitle-default=<id> --subtitle-forced=<id> oder --subtitle-forced "},{"location":"pipeline/encoding/#pre-post-encode-ausfuhrungen","title":"Pre-/Post-Encode-Ausf\u00fchrungen","text":" Pre-Encode l\u00e4uft vor HandBrake Post-Encode l\u00e4uft nach HandBrake Verhalten bei Fehlern:
Pre-Encode-Fehler: Job wird als ERROR beendet (Encode startet nicht) Post-Encode-Fehler: Job kann FINISHED bleiben, enth\u00e4lt aber Fehlerhinweis/Script-Summary "},{"location":"pipeline/encoding/#dateinamenordner","title":"Dateinamen/Ordner","text":"Der finale Outputpfad wird aus Settings-Templates aufgebaut.
Platzhalter:
${title} ${year} ${imdbId} Ung\u00fcltige Dateizeichen werden sanitisiert.
"},{"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 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:
Laufzeit Segment-Reihenfolge R\u00fcckw\u00e4rtsspr\u00fcnge/gro\u00dfe Spr\u00fcnge Koh\u00e4renz linearer Segmentfolgen Duplikatgruppen mit \u00e4hnlicher Laufzeit Daraus entstehen:
candidates evaluatedCandidates (inkl. Score/Label) recommendation manualDecisionRequired "},{"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, setzt Ripster manualDecisionRequired = true und wechselt auf:
WAITING_FOR_USER_DECISION Dann muss eine Playlist best\u00e4tigt werden, bevor der Workflow weiterl\u00e4uft.
"},{"location":"pipeline/playlist-analysis/#konfigurationseinfluss","title":"Konfigurationseinfluss","text":"Key Wirkung makemkv_min_length_minutes 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:
mit vorhandenem RAW -> zur\u00fcck zu MEDIAINFO_CHECK ohne RAW -> Startpfad \u00fcber READY_TO_START/RIPPING "},{"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":"READY_TO_ENCODE\n -> Pre-Encode Skripte/Ketten\n -> HandBrake Encoding\n -> Post-Encode Skripte/Ketten\n -> FINISHED oder ERROR\n "},{"location":"pipeline/post-encode-scripts/#auswahl-im-review","title":"Auswahl im Review","text":"Im Review-Panel kannst du getrennt w\u00e4hlen:
selectedPreEncodeScriptIds selectedPostEncodeScriptIds selectedPreEncodeChainIds selectedPostEncodeChainIds "},{"location":"pipeline/post-encode-scripts/#fehlerverhalten","title":"Fehlerverhalten","text":" Pre-Encode-Fehler stoppen die Kette und f\u00fchren zu ERROR. Post-Encode-Fehler stoppen die restlichen Post-Schritte; Job kann dennoch FINISHED sein (mit Fehlerzusatz im Status/Log). "},{"location":"pipeline/post-encode-scripts/#verfugbare-umgebungsvariablen","title":"Verf\u00fcgbare Umgebungsvariablen","text":"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 "},{"location":"pipeline/post-encode-scripts/#skript-ketten","title":"Skript-Ketten","text":"Ketten unterst\u00fctzen zwei Step-Typen:
script (f\u00fchrt ein hinterlegtes Skript aus) wait (wartet waitSeconds) Bei Fehler in einem Script-Step wird die Kette abgebrochen.
"},{"location":"pipeline/post-encode-scripts/#testlaufe","title":"Testl\u00e4ufe","text":" 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.
"},{"location":"pipeline/workflow/","title":"Workflow & Zust\u00e4nde","text":"Ripster steuert den Ablauf als State-Machine im pipelineService.
"},{"location":"pipeline/workflow/#zustandsdiagramm-vereinfacht","title":"Zustandsdiagramm (vereinfacht)","text":"flowchart LR\n IDLE --> DISC_DETECTED\n DISC_DETECTED --> ANALYZING\n ANALYZING --> METADATA_SELECTION\n METADATA_SELECTION --> READY_TO_START\n READY_TO_START --> RIPPING\n READY_TO_START --> MEDIAINFO_CHECK\n MEDIAINFO_CHECK --> WAITING_FOR_USER_DECISION\n WAITING_FOR_USER_DECISION --> MEDIAINFO_CHECK\n MEDIAINFO_CHECK --> READY_TO_ENCODE\n READY_TO_ENCODE --> ENCODING\n ENCODING --> FINISHED\n ENCODING --> ERROR\n RIPPING --> ERROR\n RIPPING --> CANCELLED "},{"location":"pipeline/workflow/#state-liste","title":"State-Liste","text":"State Bedeutung IDLE Wartet auf Disc DISC_DETECTED Disc erkannt ANALYZING MakeMKV-Analyse l\u00e4uft METADATA_SELECTION Benutzer w\u00e4hlt Metadaten WAITING_FOR_USER_DECISION Playlist-Auswahl n\u00f6tig READY_TO_START \u00dcbergangszustand vor Start RIPPING MakeMKV-Rip l\u00e4uft MEDIAINFO_CHECK Quelle/Tracks werden ausgewertet READY_TO_ENCODE Review ist bereit ENCODING HandBrake l\u00e4uft FINISHED erfolgreich abgeschlossen CANCELLED abgebrochen ERROR fehlgeschlagen"},{"location":"pipeline/workflow/#typische-pfade","title":"Typische Pfade","text":""},{"location":"pipeline/workflow/#standardfall-kein-vorhandenes-raw","title":"Standardfall (kein vorhandenes RAW)","text":" Disc erkannt Analyse + Metadaten RIPPING MEDIAINFO_CHECK READY_TO_ENCODE ENCODING FINISHED "},{"location":"pipeline/workflow/#vorhandenes-raw","title":"Vorhandenes RAW","text":"READY_TO_START springt direkt zu MEDIAINFO_CHECK (kein neuer Rip).
"},{"location":"pipeline/workflow/#mehrdeutige-blu-ray-playlist","title":"Mehrdeutige Blu-ray-Playlist","text":"MEDIAINFO_CHECK -> WAITING_FOR_USER_DECISION bis Benutzer Playlist best\u00e4tigt.
"},{"location":"pipeline/workflow/#queue-verhalten","title":"Queue-Verhalten","text":"Wenn pipeline_max_parallel_jobs erreicht ist:
Job-Aktionen werden als Queue-Eintr\u00e4ge abgelegt Queue kann zus\u00e4tzlich Nicht-Job-Eintr\u00e4ge enthalten (script, chain, wait) Reihenfolge ist per API/UI \u00e4nderbar "},{"location":"pipeline/workflow/#abbruch-retry-restart","title":"Abbruch, Retry, Restart","text":" cancel: laufenden Job abbrechen oder Queue-Eintrag entfernen retry: Fehler-/Abbruch-Job neu starten reencode: aus vorhandenem RAW neu encodieren restart-review: Review aus RAW neu aufbauen restart-encode: Encoding mit letzter best\u00e4tigter Auswahl neu starten "},{"location":"tools/","title":"Anhang: Externe Tools","text":"Ripster orchestriert externe CLI-Tools. Dieser Abschnitt erkl\u00e4rt deren Rolle im Gesamtsystem.
MakeMKV
Disc-Analyse und Ripping.
MakeMKV
HandBrake
Video-Encoding inklusive Preset-Logik.
HandBrake
MediaInfo
Track-/Containeranalyse f\u00fcr Review und Auswahl.
MediaInfo
"},{"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:
--subtitle-burned=<id> --subtitle-default=<id> --subtitle-forced=<id> oder --subtitle-forced "},{"location":"tools/handbrake/#presets-auslesen","title":"Presets auslesen","text":"Ripster liest Presets mit:
HandBrakeCLI -z\n "},{"location":"tools/handbrake/#relevante-settings","title":"Relevante Settings","text":"Key Bedeutung handbrake_command CLI-Binary handbrake_preset_bluray / handbrake_preset_dvd profilspezifisches Preset handbrake_extra_args_bluray / handbrake_extra_args_dvd profilspezifische Zusatzargumente output_extension_bluray / output_extension_dvd Ausgabeformat handbrake_restart_delete_incomplete_output 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":" Preset nicht gefunden: Preset-Namen mit HandBrakeCLI -z pr\u00fcfen sehr langsames Encoding: Preset/Extra-Args pr\u00fcfen (z. B. --encoder-preset) 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:
disc:<index> (Auto-Modus) dev:/dev/sr0 (explicit) file:<path> (Datei/Ordner-Analyse) "},{"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 makemkv_registration_key gesetzt ist, f\u00fchrt Ripster vor Analyse/Rip aus:
makemkvcon reg <key>\n "},{"location":"tools/makemkv/#relevante-settings","title":"Relevante Settings","text":"Key Bedeutung makemkv_command CLI-Binary makemkv_source_index Source-Index im Auto-Modus makemkv_min_length_minutes Mindestlaufzeitfilter makemkv_rip_mode_bluray / makemkv_rip_mode_dvd mkv oder backup makemkv_analyze_extra_args_bluray / _dvd Zusatzargs Analyse makemkv_rip_extra_args_bluray / _dvd Zusatzargs Rip"},{"location":"tools/makemkv/#hinweise","title":"Hinweise","text":" Blu-ray-Backups werden oft f\u00fcr robuste Playlist-Analyse genutzt. MakeMKV-Ausgaben werden geparst und als makemkvInfo im Job gespeichert. "},{"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":" Track-/Codec-Metadaten f\u00fcr Review-Plan Fallback-Informationen in bestimmten Analysepfaden Persistenz als mediainfoInfo im Job "},{"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":" JSON-Test: mediainfo --Output=JSON <datei> unbekannte Sprache erscheint oft als und (undetermined) "},{"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":" Dashboard: Disc einlegen, Analyse starten Metadaten im Dialog \u00fcbernehmen bei READY_TO_ENCODE Titel/Tracks pr\u00fcfen Encoding starten Ergebnis in Historie kontrollieren "},{"location":"workflows/#workflow-2-playlist-entscheidung-bei-blu-ray","title":"Workflow 2: Playlist-Entscheidung bei Blu-ray","text":" Job landet in WAITING_FOR_USER_DECISION im Pipeline-Status Playlist-Kandidaten vergleichen gew\u00fcnschte Playlist ausw\u00e4hlen Playlist \u00fcbernehmen danach normal weiter bis READY_TO_ENCODE "},{"location":"workflows/#workflow-3-mehrere-jobs-mit-queue","title":"Workflow 3: Mehrere Jobs mit Queue","text":" Parallel-Limit in Settings setzen (pipeline_max_parallel_jobs) neue Jobs starten; \u00fcbersch\u00fcssige Starts gehen in Job Queue Reihenfolge per Drag-and-Drop anpassen 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:
Metadaten korrigieren: OMDb neu zuordnen gleiche Einstellungen erneut nutzen: Encode neu starten Analyse neu aufbauen: Review neu starten aus RAW erneut encodieren: RAW neu encodieren "},{"location":"workflows/#workflow-5-automatisierung-mit-skripten-und-cron","title":"Workflow 5: Automatisierung mit Skripten und Cron","text":" Settings -> Scripte: Skripte anlegen und testen Settings -> Skriptketten: Ketten bauen und testen im Dashboard-Review Pre-/Post-Ausf\u00fchrungen pro Job ausw\u00e4hlen Settings -> Cronjobs: zeitgesteuerte Ausf\u00fchrung konfigurieren 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":" im Dashboard optional erzeugte RAW/Movie-Datei bereinigen anschlie\u00dfend je nach Ziel: Retry Rippen oder Disk-Analyse neu starten "},{"location":"workflows/#fall-b-job-steht-in-ready_to_encode-ist-aber-nicht-aktive-session","title":"Fall B: Job steht in READY_TO_ENCODE, ist aber nicht aktive Session","text":" in Historie oder Database: Im Dashboard \u00f6ffnen im Dashboard Review erneut pr\u00fcfen und starten "},{"location":"workflows/#fall-c-raw-ohne-historieneintrag","title":"Fall C: RAW ohne Historieneintrag","text":" /database \u00f6ffnen Bereich RAW ohne Historie Job anlegen "}]}
\ No newline at end of file