Files
ripster/site/search/search_index.json
T
michael 5e24c6b9cc
Deploy Docs to GitHub Pages / Build Documentation (push) Has been cancelled
Deploy Docs to GitHub Pages / Deploy to GitHub Pages (push) Has been cancelled
1.0.0 docs
2026-06-12 10:38:45 +02:00

1 line
253 KiB
JSON

{"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":"<p>Diese Dokumentation ist als vollst\u00e4ndiges Benutzerhandbuch aufgebaut: t\u00e4gliche Bedienung zuerst, technische Referenz danach.</p>"},{"location":"#einstieg-in-3-schritten","title":"Einstieg in 3 Schritten","text":"<ol> <li>Installation: Installation</li> <li>Betriebskonfiguration: Ersteinrichtung</li> <li>erster End-to-End-Lauf: Erster Lauf</li> </ol>"},{"location":"#was-das-handbuch-abdeckt","title":"Was das Handbuch abdeckt","text":"<ul> <li>alle GUI-Seiten mit Aktionen und Wirkung</li> <li>vollst\u00e4ndige Workflows f\u00fcr Film, Serie und Multipart</li> <li>Queue-, Job-, Container- und Recovery-Verhalten</li> <li>detaillierte Settings-Wirkung inklusive Fallbacks</li> </ul>"},{"location":"#empfohlene-lesereihenfolge","title":"Empfohlene Lesereihenfolge","text":"<ol> <li>Benutzerhandbuch \u00dcberblick</li> <li>GUI-Seiten</li> <li>Workflows aus Nutzersicht</li> <li>Einstellungsreferenz</li> <li>bei Bedarf technischer Tiefgang im Anhang</li> </ol>"},{"location":"api/","title":"Anhang: API-Referenz","text":"<p>REST- und WebSocket-Schnittstellen f\u00fcr Integration, Automatisierung und Debugging.</p>"},{"location":"api/#basis-url","title":"Basis-URL","text":"<pre><code>http://localhost:3001\n</code></pre> <p>API-Prefix: <code>/api</code></p>"},{"location":"api/#api-gruppen","title":"API-Gruppen","text":"<ul> <li> <p> Health</p> <p>Service-Liveness.</p> <p><code>GET /api/health</code></p> </li> <li> <p> Pipeline API</p> <p>Analyse, Start/Retry/Cancel, Queue, Re-Encode.</p> <p> Pipeline API</p> </li> <li> <p> Settings API</p> <p>Einstellungen, Skripte/Ketten, User-Presets.</p> <p> Settings API</p> </li> <li> <p> History API</p> <p>Job-Historie, Orphan-Import, L\u00f6schoperationen.</p> <p> History API</p> </li> <li> <p> Cron API</p> <p>Zeitgesteuerte Skript-/Kettenausf\u00fchrung.</p> <p> Cron API</p> </li> <li> <p> Converter API</p> <p>Datei-Explorer, Upload, Job-Verwaltung f\u00fcr den Converter.</p> <p> Converter API</p> </li> <li> <p> Downloads API</p> <p>Download-Queue f\u00fcr Ausgabedateien aus der Job-Historie.</p> <p> Downloads API</p> </li> <li> <p> Runtime Activities API</p> <p>Laufende und abgeschlossene Aktivit\u00e4ten (Skripte, Ketten, Cron, Tasks).</p> <p> Runtime Activities</p> </li> <li> <p>:material-websocket: WebSocket Events</p> <p>Pipeline-, Queue-, Disk-, Settings-, Cron-, Converter- und Download-Events.</p> <p> WebSocket</p> </li> </ul>"},{"location":"api/#hinweis","title":"Hinweis","text":"<p>Ripster hat keine eingebaute Authentifizierung und ist f\u00fcr lokalen, gesch\u00fctzten Betrieb gedacht.</p>"},{"location":"api/converter/","title":"Converter API","text":"<p>Endpunkte f\u00fcr den Datei-Converter: Datei-Explorer, Upload, Job-Verwaltung.</p> <p>Basis-Pfad: <code>/api/converter</code></p>"},{"location":"api/converter/#scan-explorer","title":"Scan &amp; Explorer","text":""},{"location":"api/converter/#get-apiconvertertree","title":"<code>GET /api/converter/tree</code>","text":"<p>Vollst\u00e4ndiger Verzeichnisbaum des <code>converter_raw_dir</code> (FS-basiert, keine DB).</p> <p>Response:</p> <pre><code>{\n \"tree\": [\n {\n \"name\": \"filme\",\n \"relPath\": \"filme\",\n \"isDir\": true,\n \"children\": [\n {\n \"name\": \"film.mkv\",\n \"relPath\": \"filme/film.mkv\",\n \"isDir\": false,\n \"size\": 10485760\n }\n ]\n }\n ]\n}\n</code></pre>"},{"location":"api/converter/#get-apiconverterbrowseparentrelpath","title":"<code>GET /api/converter/browse?parent=relPath</code>","text":"<p>DB-basierter Datei-Explorer. Gibt Eintr\u00e4ge f\u00fcr einen Unterordner zur\u00fcck.</p> <p>Query-Parameter:</p> Parameter Typ Beschreibung <code>parent</code> string Relativer Pfad zum Unterordner (leer = Root) <p>Response:</p> <pre><code>{\n \"entries\": [\n {\n \"id\": 1,\n \"rel_path\": \"filme/film.mkv\",\n \"is_dir\": false,\n \"size\": 10485760,\n \"job_id\": null\n }\n ],\n \"rawDir\": \"/data/output/converter-raw\"\n}\n</code></pre>"},{"location":"api/converter/#post-apiconverterscan","title":"<code>POST /api/converter/scan</code>","text":"<p>Manuellen Scan des <code>converter_raw_dir</code> ausl\u00f6sen. Aktualisiert <code>converter_scan_entries</code> in der DB.</p> <p>Response:</p> <pre><code>{ \"result\": { \"added\": 3, \"removed\": 1 } }\n</code></pre>"},{"location":"api/converter/#jobs-erstellen","title":"Jobs erstellen","text":""},{"location":"api/converter/#post-apiconverterjobsfrom-selection","title":"<code>POST /api/converter/jobs/from-selection</code>","text":"<p>Jobs aus im Datei-Explorer ausgew\u00e4hlten Dateien erstellen.</p> <p>Body:</p> <pre><code>{\n \"relPaths\": [\"filme/film.mkv\", \"musik/track.flac\"],\n \"audioMode\": \"individual\"\n}\n</code></pre> Feld Typ Beschreibung <code>relPaths</code> string[] Relative Pfade der ausgew\u00e4hlten Dateien <code>audioMode</code> string <code>individual</code> (ein Job pro Datei) oder <code>shared</code> (ein gemeinsamer Job) <p>Response:</p> <pre><code>{ \"jobs\": [{ \"id\": 42, \"status\": \"READY_TO_START\" }] }\n</code></pre>"},{"location":"api/converter/#post-apiconvertercreate-jobs","title":"<code>POST /api/converter/create-jobs</code>","text":"<p>Jobs aus DB-Scan-Eintr\u00e4gen erstellen.</p> <p>Body:</p> <pre><code>{\n \"entries\": [\n { \"relPath\": \"filme/film.mkv\", \"converterMediaType\": \"video\" }\n ]\n}\n</code></pre>"},{"location":"api/converter/#post-apiconverterupload","title":"<code>POST /api/converter/upload</code>","text":"<p>Dateien hochladen (Multipart, max. 50 Dateien).</p> <p>Form-Felder:</p> Feld Typ Beschreibung <code>files</code> File[] Hochzuladende Dateien <code>folderName</code> string (Optional) Ziel-Unterordner <p>Response:</p> <pre><code>{\n \"folders\": [{ \"folderRelPath\": \"upload-2026-03-30\", \"fileCount\": 2 }]\n}\n</code></pre>"},{"location":"api/converter/#job-verwaltung","title":"Job-Verwaltung","text":""},{"location":"api/converter/#get-apiconverterjobs","title":"<code>GET /api/converter/jobs</code>","text":"<p>Alle Converter-Jobs zur\u00fcckgeben.</p> <p>Response:</p> <pre><code>{ \"jobs\": [{ \"id\": 42, \"status\": \"READY_TO_START\", \"title\": \"film.mkv\" }] }\n</code></pre>"},{"location":"api/converter/#get-apiconverterjobsjobid","title":"<code>GET /api/converter/jobs/:jobId</code>","text":"<p>Einzelnen Converter-Job abrufen.</p>"},{"location":"api/converter/#post-apiconverterjobsjobidconfig","title":"<code>POST /api/converter/jobs/:jobId/config</code>","text":"<p>Konfigurationsentwurf f\u00fcr einen Job speichern (persistiert in <code>encode_plan_json</code>).</p> <p>Body: Partielles Konfig-Objekt (Ausgabeformat, Presets, Metadaten, Track-Auswahl).</p>"},{"location":"api/converter/#post-apiconverterjobsjobidassign-files","title":"<code>POST /api/converter/jobs/:jobId/assign-files</code>","text":"<p>Dateien einem bestehenden (noch nicht gestarteten) Job hinzuf\u00fcgen.</p> <p>Body:</p> <pre><code>{ \"relPaths\": [\"musik/track2.flac\"] }\n</code></pre>"},{"location":"api/converter/#post-apiconverterjobsjobidremove-file","title":"<code>POST /api/converter/jobs/:jobId/remove-file</code>","text":"<p>Datei aus einem Job entfernen (per relativer Pfad).</p> <p>Body:</p> <pre><code>{ \"relPath\": \"musik/track2.flac\" }\n</code></pre>"},{"location":"api/converter/#post-apiconverterjobsjobidremove-input","title":"<code>POST /api/converter/jobs/:jobId/remove-input</code>","text":"<p>Datei aus einem Job entfernen (per absolutem Eingabepfad).</p> <p>Body:</p> <pre><code>{ \"inputPath\": \"/data/output/converter-raw/musik/track2.flac\" }\n</code></pre>"},{"location":"api/converter/#post-apiconverterjobsjobidstart","title":"<code>POST /api/converter/jobs/:jobId/start</code>","text":"<p>Job mit finaler Konfiguration starten.</p> <p>Body:</p> <pre><code>{\n \"converterMediaType\": \"video\",\n \"outputFormat\": \"mkv\",\n \"userPreset\": \"H.264 MKV 1080p30\",\n \"trackSelection\": {},\n \"handBrakeTitleId\": 1,\n \"audioFormatOptions\": {}\n}\n</code></pre>"},{"location":"api/converter/#post-apiconverterjobsjobidcancel","title":"<code>POST /api/converter/jobs/:jobId/cancel</code>","text":"<p>Laufenden Job abbrechen.</p>"},{"location":"api/converter/#delete-apiconverterjobsjobid","title":"<code>DELETE /api/converter/jobs/:jobId</code>","text":"<p>Job aus der DB l\u00f6schen.</p>"},{"location":"api/converter/#datei-operationen","title":"Datei-Operationen","text":"<p>Alle Datei-Operationen arbeiten direkt auf dem Dateisystem (ohne DB-Aktualisierung). Ein anschlie\u00dfender Scan-Aufruf synchronisiert die DB.</p>"},{"location":"api/converter/#delete-apiconverterfiles","title":"<code>DELETE /api/converter/files</code>","text":"<p>Datei oder Ordner l\u00f6schen.</p> <p>Body:</p> <pre><code>{ \"relPath\": \"filme/film.mkv\" }\n</code></pre>"},{"location":"api/converter/#post-apiconverterfilesrename","title":"<code>POST /api/converter/files/rename</code>","text":"<p>Datei oder Ordner umbenennen.</p> <p>Body:</p> <pre><code>{ \"relPath\": \"filme/film.mkv\", \"newName\": \"film-neu.mkv\" }\n</code></pre>"},{"location":"api/converter/#post-apiconverterfilesmove","title":"<code>POST /api/converter/files/move</code>","text":"<p>Datei oder Ordner verschieben.</p> <p>Body:</p> <pre><code>{ \"relPath\": \"filme/film.mkv\", \"targetParentRelPath\": \"archiv\" }\n</code></pre> <p><code>targetParentRelPath = \"\"</code> verschiebt in das Root-Verzeichnis.</p>"},{"location":"api/converter/#post-apiconverterfilesfolder","title":"<code>POST /api/converter/files/folder</code>","text":"<p>Neuen Ordner anlegen.</p> <p>Body:</p> <pre><code>{ \"parentRelPath\": \"filme\", \"name\": \"neu\" }\n</code></pre>"},{"location":"api/crons/","title":"Cron API","text":"<p>Ripster enth\u00e4lt ein eingebautes Cron-System f\u00fcr Skripte und Skript-Ketten (<code>sourceType: script|chain</code>).</p>"},{"location":"api/crons/#get-apicrons","title":"GET /api/crons","text":"<p>Listet alle Cron-Jobs.</p> <pre><code>{\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</code></pre>"},{"location":"api/crons/#post-apicrons","title":"POST /api/crons","text":"<p>Erstellt Cron-Job.</p> <pre><code>{\n \"name\": \"Nachtlauf Backup\",\n \"cronExpression\": \"0 2 * * *\",\n \"sourceType\": \"script\",\n \"sourceId\": 3,\n \"enabled\": true,\n \"pushoverEnabled\": true\n}\n</code></pre> <p>Response: <code>201</code> mit <code>{ \"job\": { ... } }</code></p>"},{"location":"api/crons/#get-apicronsid","title":"GET /api/crons/:id","text":"<p>Response:</p> <pre><code>{ \"job\": { \"id\": 1, \"name\": \"...\" } }\n</code></pre>"},{"location":"api/crons/#put-apicronsid","title":"PUT /api/crons/:id","text":"<p>Aktualisiert Cron-Job. Felder wie bei <code>POST</code>.</p> <p>Response:</p> <pre><code>{ \"job\": { ... } }\n</code></pre>"},{"location":"api/crons/#delete-apicronsid","title":"DELETE /api/crons/:id","text":"<p>Response:</p> <pre><code>{ \"removed\": { \"id\": 1, \"name\": \"Nachtlauf Backup\" } }\n</code></pre>"},{"location":"api/crons/#get-apicronsidlogs","title":"GET /api/crons/:id/logs","text":"<p>Liefert Ausf\u00fchrungs-Logs.</p> <p>Query-Parameter:</p> Parameter Typ Default Beschreibung <code>limit</code> number <code>20</code> Anzahl Eintr\u00e4ge, max. <code>100</code> <p>Response:</p> <pre><code>{\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</code></pre> <p><code>status</code>: <code>running</code> | <code>success</code> | <code>error</code></p>"},{"location":"api/crons/#post-apicronsidrun","title":"POST /api/crons/:id/run","text":"<p>Triggert Job manuell (asynchron).</p> <p>Response:</p> <pre><code>{ \"triggered\": true, \"cronJobId\": 1 }\n</code></pre> <p>Wenn Job bereits l\u00e4uft: <code>409</code>.</p>"},{"location":"api/crons/#post-apicronsvalidate-expression","title":"POST /api/crons/validate-expression","text":"<p>Validiert 5-Felder-Cron-Ausdruck und berechnet n\u00e4chsten Lauf.</p> <p>Request:</p> <pre><code>{ \"cronExpression\": \"*/15 * * * *\" }\n</code></pre> <p>G\u00fcltige Response:</p> <pre><code>{\n \"valid\": true,\n \"nextRunAt\": \"2026-03-10T14:15:00.000Z\"\n}\n</code></pre> <p>Ung\u00fcltige Response:</p> <pre><code>{\n \"valid\": false,\n \"error\": \"Cron-Ausdruck muss genau 5 Felder haben (Minute Stunde Tag Monat Wochentag).\",\n \"nextRunAt\": null\n}\n</code></pre>"},{"location":"api/crons/#cron-format","title":"Cron-Format","text":"<p>Ripster unterst\u00fctzt 5 Felder:</p> <pre><code>Minute Stunde Tag Monat Wochentag\n</code></pre> <p>Beispiele:</p> <ul> <li><code>0 2 * * *</code> t\u00e4glich 02:00</li> <li><code>*/15 * * * *</code> alle 15 Minuten</li> <li><code>0 6 * * 1-5</code> Mo-Fr 06:00</li> </ul>"},{"location":"api/crons/#websocket-events-zu-cron","title":"WebSocket-Events zu Cron","text":"<ul> <li><code>CRON_JOBS_UPDATED</code> bei Create/Update/Delete</li> <li><code>CRON_JOB_UPDATED</code> bei Laufzeitstatus (<code>running</code> -&gt; <code>success|error</code>)</li> </ul>"},{"location":"api/downloads/","title":"Downloads API","text":"<p>Endpunkte f\u00fcr die Download-Queue. Ausgabedateien aus der Job-Historie k\u00f6nnen als ZIP heruntergeladen werden.</p> <p>Basis-Pfad: <code>/api/downloads</code></p>"},{"location":"api/downloads/#get-apidownloads","title":"<code>GET /api/downloads</code>","text":"<p>Liste aller Download-Eintr\u00e4ge plus Zusammenfassung.</p> <p>Response:</p> <pre><code>{\n \"items\": [\n {\n \"id\": \"dl-42-raw\",\n \"jobId\": 42,\n \"target\": \"raw\",\n \"status\": \"ready\",\n \"archiveName\": \"Job_42_raw.zip\",\n \"outputPath\": null,\n \"createdAt\": \"2026-03-30T10:00:00.000Z\",\n \"updatedAt\": \"2026-03-30T10:01:00.000Z\",\n \"errorMessage\": null\n }\n ],\n \"summary\": {\n \"total\": 3,\n \"pending\": 1,\n \"processing\": 0,\n \"ready\": 1,\n \"failed\": 1\n }\n}\n</code></pre> <p>Status-Werte:</p> Status Beschreibung <code>pending</code> In der Queue, noch nicht gestartet <code>processing</code> ZIP wird gerade erstellt <code>ready</code> ZIP fertig, Download verf\u00fcgbar <code>failed</code> Fehler bei der Erstellung"},{"location":"api/downloads/#get-apidownloadssummary","title":"<code>GET /api/downloads/summary</code>","text":"<p>Nur die Zusammenfassung der Download-Queue (ohne Item-Liste).</p> <p>Response:</p> <pre><code>{\n \"summary\": {\n \"total\": 3,\n \"pending\": 1,\n \"processing\": 0,\n \"ready\": 1,\n \"failed\": 1\n }\n}\n</code></pre>"},{"location":"api/downloads/#post-apidownloadshistoryjobid","title":"<code>POST /api/downloads/history/:jobId</code>","text":"<p>Job-Ausgabe in die Download-Queue einreihen.</p> <p>Parameter:</p> Parameter Typ Beschreibung <code>jobId</code> number ID des Jobs in der Historie <p>Body:</p> <pre><code>{\n \"target\": \"raw\",\n \"outputPath\": null\n}\n</code></pre> Feld Typ Default Beschreibung <code>target</code> string <code>raw</code> <code>raw</code> (RAW-Dateien) oder <code>movie</code> (Ausgabedateien) <code>outputPath</code> string <code>null</code> Optionaler expliziter Ausgabepfad <p>Response (201 Created):</p> <pre><code>{\n \"created\": true,\n \"id\": \"dl-42-raw\",\n \"status\": \"pending\",\n \"summary\": { \"total\": 1, \"pending\": 1, \"processing\": 0, \"ready\": 0, \"failed\": 0 }\n}\n</code></pre> <p>Ist der Eintrag bereits vorhanden, wird <code>201</code> durch <code>200</code> ersetzt und <code>created: false</code> zur\u00fcckgegeben.</p>"},{"location":"api/downloads/#get-apidownloadsidfile","title":"<code>GET /api/downloads/:id/file</code>","text":"<p>Fertige ZIP-Datei herunterladen.</p> <p>Parameter:</p> Parameter Typ Beschreibung <code>id</code> string Download-ID (z. B. <code>dl-42-raw</code>) <p>Response: Datei-Download (<code>Content-Disposition: attachment</code>).</p> <p>Schl\u00e4gt fehl mit <code>404</code>, wenn kein Download-Eintrag mit dieser ID existiert oder die Datei noch nicht bereit ist.</p>"},{"location":"api/downloads/#delete-apidownloadsid","title":"<code>DELETE /api/downloads/:id</code>","text":"<p>Download-Eintrag l\u00f6schen (auch fertige ZIP-Dateien werden vom Dateisystem entfernt).</p> <p>Response:</p> <pre><code>{\n \"ok\": true,\n \"summary\": { \"total\": 2, \"pending\": 0, \"processing\": 0, \"ready\": 2, \"failed\": 0 }\n}\n</code></pre>"},{"location":"api/downloads/#websocket","title":"WebSocket","text":"<p>Status\u00e4nderungen werden \u00fcber <code>DOWNLOADS_UPDATED</code> in Echtzeit gemeldet. Vollst\u00e4ndige Dokumentation: WebSocket Events.</p>"},{"location":"api/history/","title":"History API","text":"<p>Endpunkte f\u00fcr Job-Historie, Metadaten-Nachpflege, Orphan-Import und L\u00f6schoperationen.</p>"},{"location":"api/history/#get-apihistory","title":"GET /api/history","text":"<p>Liefert Jobs mit optionalen Filtern.</p> <p>Query-Parameter:</p> Parameter Typ Beschreibung <code>status</code> string Einzelstatus-Filter (legacy-kompatibel). <code>statuses</code> string Mehrfachstatus als CSV, z. B. <code>FINISHED,ERROR</code>. <code>search</code> string Suche in Titel-/IMDb-Feldern. <code>limit</code> number Maximale Anzahl Ergebnisse. <code>lite</code> bool Ohne Dateisystem-Checks (schneller). <code>includeChildren</code> bool Child-Jobs (z. B. Serien-/Multipart-Kinder) explizit einbeziehen. <p>Beispiel:</p> <pre><code>GET /api/history?statuses=FINISHED,ERROR&amp;search=Inception&amp;limit=50&amp;lite=1\n</code></pre> <p>Response (Beispiel):</p> <pre><code>{\n \"jobs\": [\n {\n \"id\": 42,\n \"status\": \"FINISHED\",\n \"title\": \"Inception\",\n \"job_kind\": \"bluray\",\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</code></pre>"},{"location":"api/history/#get-apihistoryid","title":"GET /api/history/:id","text":"<p>Liefert Job-Detail.</p> <p>Query-Parameter:</p> Parameter Typ Standard Beschreibung <code>includeLogs</code> bool <code>false</code> Prozesslog laden. <code>includeLiveLog</code> bool <code>false</code> Live-/Tail-Log laden. <code>includeAllLogs</code> bool <code>false</code> vollst\u00e4ndiges Log statt Tail. <code>logTailLines</code> number <code>800</code> Tail-L\u00e4nge falls nicht <code>includeAllLogs</code>. <code>lite</code> bool <code>false</code> Detailantwort ohne FS-Checks. <p>Response (Beispiel):</p> <pre><code>{\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</code></pre>"},{"location":"api/history/#get-apihistoryorphan-raw","title":"GET /api/history/orphan-raw","text":"<p>Sucht RAW-Ordner ohne zugeh\u00f6rigen Job.</p>"},{"location":"api/history/#post-apihistoryorphan-rawimport","title":"POST /api/history/orphan-raw/import","text":"<p>Importiert einen RAW-Ordner als Job und triggert optional die Analyse des Imports.</p> <p>Request:</p> <pre><code>{ \"rawPath\": \"/mnt/raw/Inception (2010) [tt1375666] - RAW - job-99\" }\n</code></pre> <p>Response (Beispiel):</p> <pre><code>{\n \"job\": { \"id\": 77, \"status\": \"FINISHED\" },\n \"activation\": { \"started\": true },\n \"activationError\": null\n}\n</code></pre>"},{"location":"api/history/#post-apihistoryidmetadataassign","title":"POST /api/history/:id/metadata/assign","text":"<p>Weist TMDb-Metadaten nachtr\u00e4glich zu oder aktualisiert bestehende Film-/Serien-Metadaten eines Jobs.</p>"},{"location":"api/history/#post-apihistoryidcdassign","title":"POST /api/history/:id/cd/assign","text":"<p>Weist CD-Metadaten (z. B. MusicBrainz) nachtr\u00e4glich zu.</p>"},{"location":"api/history/#post-apihistoryiderrorack","title":"POST /api/history/:id/error/ack","text":"<p>Quittiert einen Fehlerzustand im Historieneintrag.</p>"},{"location":"api/history/#get-apihistoryiddelete-preview","title":"GET /api/history/:id/delete-preview","text":"<p>Liefert eine Vorschau der l\u00f6schbaren Pfade (inkl. Scope auf verkn\u00fcpfte Jobs).</p> <p>Query-Parameter:</p> Parameter Typ Standard Beschreibung <code>includeRelated</code> bool <code>true</code> Verkn\u00fcpfte Jobs in die Vorschau einbeziehen. <p>Response (Beispiel):</p> <pre><code>{\n \"preview\": {\n \"jobId\": 42,\n \"relatedJobs\": [{ \"id\": 42 }, { \"id\": 73 }],\n \"pathCandidates\": {\n \"raw\": [{ \"path\": \"/mnt/raw/...\", \"exists\": true, \"isDirectory\": true }],\n \"movie\": [{ \"path\": \"/mnt/movies/...\", \"exists\": true, \"isDirectory\": true }]\n }\n }\n}\n</code></pre>"},{"location":"api/history/#post-apihistoryiddelete-files","title":"POST /api/history/:id/delete-files","text":"<p>L\u00f6scht Dateien eines Jobs, beh\u00e4lt DB-Eintrag.</p> <p>Request:</p> <pre><code>{\n \"target\": \"both\",\n \"includeRelated\": true,\n \"selectedRawPaths\": [\"/mnt/raw/Inception - RAW - Disc1\"],\n \"selectedMoviePaths\": [\"/mnt/movies/Inception (2010)\"]\n}\n</code></pre> <p><code>target</code>: <code>raw</code> | <code>movie</code> | <code>both</code></p> <p><code>selectedRawPaths</code> / <code>selectedMoviePaths</code> sind optional und begrenzen die L\u00f6schung auf ausgew\u00e4hlte Pfade aus der Vorschau.</p>"},{"location":"api/history/#post-apihistoryiddelete","title":"POST /api/history/:id/delete","text":"<p>L\u00f6scht Job aus DB; optional auch Dateien.</p> <p>Request:</p> <pre><code>{\n \"target\": \"both\",\n \"includeRelated\": true,\n \"resetDriveState\": false,\n \"keepDetectedDevice\": true,\n \"preserveRawForImportJobs\": false,\n \"selectedRawPaths\": [\"/mnt/raw/Inception - RAW - Disc1\"],\n \"selectedMoviePaths\": [\"/mnt/movies/Inception (2010)\"]\n}\n</code></pre> <p><code>target</code>: <code>none</code> | <code>raw</code> | <code>movie</code> | <code>both</code></p> <p>Response (Beispiel):</p> <pre><code>{\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 \"safeguards\": {\n \"containsOrphanRawImportJob\": false,\n \"resetDriveStateApplied\": false,\n \"keepDetectedDeviceApplied\": true\n }\n}\n</code></pre>"},{"location":"api/history/#hinweise","title":"Hinweise","text":"<ul> <li>Ein aktiver Pipeline-Job kann nicht gel\u00f6scht werden (<code>409</code>).</li> <li>L\u00f6schoperationen sind irreversibel.</li> <li>Bei Serien-/Multipart-Containern steuern <code>includeRelated</code> und Pfadselektionen den genauen Scope.</li> </ul>"},{"location":"api/pipeline/","title":"Pipeline API","text":"<p>Endpunkte zur Steuerung des Pipeline-Workflows.</p>"},{"location":"api/pipeline/#get-apipipelinestate","title":"GET /api/pipeline/state","text":"<p>Liefert aktuellen Pipeline- und Hardware-Monitoring-Snapshot.</p> <p>Response (Beispiel):</p> <pre><code>{\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</code></pre>"},{"location":"api/pipeline/#post-apipipelineanalyze","title":"POST /api/pipeline/analyze","text":"<p>Startet Disc-Analyse und legt Job an.</p> <p>Response:</p> <pre><code>{\n \"result\": {\n \"jobId\": 42,\n \"detectedTitle\": \"INCEPTION\",\n \"omdbCandidates\": []\n }\n}\n</code></pre>"},{"location":"api/pipeline/#post-apipipelinerescan-disc","title":"POST /api/pipeline/rescan-disc","text":"<p>Erzwingt erneute Laufwerkspr\u00fcfung.</p> <p>Response (Beispiel):</p> <pre><code>{\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</code></pre>"},{"location":"api/pipeline/#post-apipipelinerescan-drive","title":"POST /api/pipeline/rescan-drive","text":"<p>Erzwingt Rescan f\u00fcr ein konkretes Laufwerk.</p> <p>Request:</p> <pre><code>{ \"devicePath\": \"/dev/sr0\" }\n</code></pre>"},{"location":"api/pipeline/#get-apipipelinetmdbmoviesearchq","title":"GET /api/pipeline/tmdb/movie/search?q= <p>TMDb-Filmsuche.</p> <p>Response:</p> <pre><code>{\n \"results\": [\n {\n \"imdbId\": \"tt1375666\",\n \"title\": \"Inception\",\n \"year\": \"2010\",\n \"type\": \"movie\",\n \"poster\": \"https://...\"\n }\n ]\n}\n</code></pre>","text":""},{"location":"api/pipeline/#get-apipipelinetmdbseriessearchqseason","title":"GET /api/pipeline/tmdb/series/search?q=&amp;season= <p>TMDb-Seriensuche (f\u00fcr Serien-Workflow bei DVD/Blu-ray).</p>","text":""},{"location":"api/pipeline/#get-apipipelinecddrives","title":"GET /api/pipeline/cd/drives <p>Liefert Snapshot der aktuell bekannten CD-Laufwerke.</p>","text":""},{"location":"api/pipeline/#get-apipipelinecdmusicbrainzsearchq","title":"GET /api/pipeline/cd/musicbrainz/search?q= <p>MusicBrainz-Suche f\u00fcr CD-Metadaten.</p>","text":""},{"location":"api/pipeline/#get-apipipelinecdmusicbrainzreleasembid","title":"GET /api/pipeline/cd/musicbrainz/release/:mbId <p>L\u00e4dt Release-Details zu einer MusicBrainz-ID.</p>","text":""},{"location":"api/pipeline/#post-apipipelinecdselect-metadata","title":"POST /api/pipeline/cd/select-metadata <p>\u00dcbernimmt CD-Metadaten f\u00fcr einen Job.</p> <p>Request (Beispiel):</p> <pre><code>{\n \"jobId\": 91,\n \"title\": \"Album\",\n \"artist\": \"Artist\",\n \"year\": 2020,\n \"mbId\": \"f5093c06-23e3-404f-aeaa-40f72885ee3a\",\n \"coverUrl\": \"https://...\",\n \"tracks\": []\n}\n</code></pre>","text":""},{"location":"api/pipeline/#post-apipipelinecdstartjobid","title":"POST /api/pipeline/cd/start/:jobId <p>Startet/queued CD-Rip mit Format-/Script-/Chain-Konfiguration.</p>","text":""},{"location":"api/pipeline/#post-apipipelineaudiobookupload","title":"POST /api/pipeline/audiobook/upload <p>Upload von AAX-Datei (Multipart/FormData).</p> <p>FormData-Felder:</p> <ul> <li><code>file</code> (Pflicht)</li> <li><code>format</code> (optional)</li> <li><code>startImmediately</code> (optional)</li> </ul>","text":""},{"location":"api/pipeline/#get-apipipelineaudiobookpending-activation","title":"GET /api/pipeline/audiobook/pending-activation <p>Zeigt AAX-Jobs mit fehlenden Activation-Bytes.</p>","text":""},{"location":"api/pipeline/#post-apipipelineaudiobookstartjobid","title":"POST /api/pipeline/audiobook/start/:jobId <p>Startet Audiobook-Job mit optionaler Konfiguration.</p>","text":""},{"location":"api/pipeline/#get-apipipelineaudiobookjobs","title":"GET /api/pipeline/audiobook/jobs <p>Liefert Audiobook-Jobliste.</p>","text":""},{"location":"api/pipeline/#get-apipipelineaudiobookoutput-tree","title":"GET /api/pipeline/audiobook/output-tree <p>Read-only Baumansicht des Audiobook-Ausgabeordners.</p>","text":""},{"location":"api/pipeline/#post-apipipelineselect-metadata","title":"POST /api/pipeline/select-metadata <p>Setzt Metadaten (und optional Playlist) f\u00fcr einen Job.</p> <p>Request:</p> <pre><code>{\n \"jobId\": 42,\n \"title\": \"Inception\",\n \"year\": 2010,\n \"imdbId\": \"tt1375666\",\n \"poster\": \"https://...\",\n \"fromOmdb\": true,\n \"selectedPlaylist\": \"00800\"\n}\n</code></pre> <p>Wichtige optionale Felder:</p> <ul> <li><code>selectedHandBrakeTitleId</code> / <code>selectedHandBrakeTitleIds</code>: Titel-Auswahl f\u00fcr Review/MediaInfo.</li> <li><code>metadataProvider</code>: <code>omdb</code> oder <code>tmdb</code>.</li> <li><code>workflowKind</code>: bei Disc-Jobs typischerweise <code>film</code> oder <code>series</code>.</li> <li><code>discNumber</code>: Pflicht f\u00fcr Serien-Disc-Zuordnung (<code>workflowKind=series</code>).</li> <li><code>duplicateAction</code>: Duplikatverhalten bei Film-Metadaten (<code>allow_new</code> oder <code>multipart_movie</code>).</li> <li><code>existingJobId</code>: optionaler Referenzjob f\u00fcr <code>multipart_movie</code>.</li> <li><code>existingDiscNumber</code>: Disc-Nummer des bestehenden Jobs f\u00fcr <code>multipart_movie</code>.</li> </ul> <p>Response:</p> <pre><code>{ \"job\": { \"id\": 42, \"status\": \"READY_TO_START\" } }\n</code></pre> <p>Konflikt-Response (Beispiel, HTTP 409):</p> <pre><code>{\n \"message\": \"Metadaten bereits in der Historie gefunden. Bitte Auswahl \u00fcbernehmen oder Multipart movie w\u00e4hlen.\",\n \"details\": [\n {\n \"code\": \"METADATA_DUPLICATE_FOUND\",\n \"mediaProfile\": \"bluray\",\n \"existingJob\": {\n \"id\": 17,\n \"title\": \"Inception\",\n \"year\": 2010,\n \"status\": \"FINISHED\",\n \"jobKind\": \"bluray\",\n \"discNumber\": 1,\n \"isMultipartMovie\": false\n }\n }\n ]\n}\n</code></pre> <p>Relevante Fehlercodes (<code>POST /api/pipeline/select-metadata</code>):</p> Code Bedeutung <code>METADATA_DUPLICATE_FOUND</code> Film-Metadaten existieren bereits in der Historie (Konfliktdialog im UI). <code>MULTIPART_DISC_REQUIRED</code> F\u00fcr Multipart fehlen Disc-Nummern (<code>discNumber</code>/<code>existingDiscNumber</code>). <code>MULTIPART_DISC_ALREADY_EXISTS</code> Disc-Nummer im Multipart-Container bereits vergeben oder doppelt. <code>MULTIPART_MEDIA_MISMATCH</code> Multipart nur bei gleichem Medientyp (DVD oder Blu-ray). <code>MULTIPART_SERIES_NOT_ALLOWED</code> Multipart ist nur f\u00fcr Film-Jobs erlaubt, nicht f\u00fcr Serien-Workflow. <code>MULTIPART_METADATA_MISMATCH</code> Ausgew\u00e4hlter bestehender Job passt nicht zu den Film-Metadaten. <code>SERIES_DISC_ALREADY_EXISTS</code> Serien-Disc-Nummer innerhalb einer Staffel bereits vorhanden.","text":""},{"location":"api/pipeline/#post-apipipelinejobsjobidraw-decision","title":"POST /api/pipeline/jobs/:jobId/raw-decision <p>Trifft Entscheidung bei vorhandenem RAW (<code>continue</code> oder <code>restart</code> je nach Dialogfluss).</p> <p>Request:</p> <pre><code>{ \"decision\": \"continue\" }\n</code></pre>","text":""},{"location":"api/pipeline/#post-apipipelinestartjobid","title":"POST /api/pipeline/start/:jobId <p>Startet vorbereiteten Job oder queued ihn (je nach Parallel-Limit).</p> <p>M\u00f6gliche Responses:</p> <pre><code>{ \"result\": { \"started\": true, \"stage\": \"RIPPING\" } }\n</code></pre> <pre><code>{ \"result\": { \"queued\": true, \"started\": false, \"queuePosition\": 2, \"action\": \"START_PREPARED\" } }\n</code></pre>","text":""},{"location":"api/pipeline/#post-apipipelineconfirm-encodejobid","title":"POST /api/pipeline/confirm-encode/:jobId <p>Best\u00e4tigt Review-Auswahl (Tracks, Pre/Post-Skripte/Ketten, User-Preset).</p> <p>Request (typisch):</p> <pre><code>{\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</code></pre> <p>Response:</p> <pre><code>{ \"job\": { \"id\": 42, \"encode_review_confirmed\": 1 } }\n</code></pre>","text":""},{"location":"api/pipeline/#post-apipipelinecancel","title":"POST /api/pipeline/cancel <p>Bricht laufenden Job ab oder entfernt Queue-Eintrag.</p> <p>Request (optional):</p> <pre><code>{ \"jobId\": 42 }\n</code></pre> <p>M\u00f6gliche Responses:</p> <pre><code>{ \"result\": { \"cancelled\": true, \"queuedOnly\": true, \"jobId\": 42 } }\n</code></pre> <pre><code>{ \"result\": { \"cancelled\": true, \"queuedOnly\": false, \"jobId\": 42 } }\n</code></pre> <pre><code>{ \"result\": { \"cancelled\": true, \"queuedOnly\": false, \"pending\": true, \"jobId\": 42 } }\n</code></pre>","text":""},{"location":"api/pipeline/#post-apipipelineretryjobid","title":"POST /api/pipeline/retry/:jobId <p>Retry f\u00fcr <code>ERROR</code>/<code>CANCELLED</code>-Jobs (oder Queue-Einreihung).</p>","text":""},{"location":"api/pipeline/#post-apipipelinereencodejobid","title":"POST /api/pipeline/reencode/:jobId <p>Startet Re-Encode aus bestehendem RAW.</p>","text":""},{"location":"api/pipeline/#post-apipipelinerestart-reviewjobid","title":"POST /api/pipeline/restart-review/:jobId <p>Berechnet Review aus RAW neu.</p>","text":""},{"location":"api/pipeline/#post-apipipelinerestart-encodejobid","title":"POST /api/pipeline/restart-encode/:jobId <p>Startet Encoding mit letzter best\u00e4tigter Review neu.</p>","text":""},{"location":"api/pipeline/#post-apipipelinerestart-cd-reviewjobid","title":"POST /api/pipeline/restart-cd-review/:jobId <p>Berechnet CD-Review aus vorhandenem RAW neu.</p>","text":""},{"location":"api/pipeline/#post-apipipelineresume-readyjobid","title":"POST /api/pipeline/resume-ready/:jobId <p>L\u00e4dt <code>READY_TO_ENCODE</code>-Job nach Neustart wieder in aktive Session.</p>","text":""},{"location":"api/pipeline/#get-apipipelineoutput-foldersjobid","title":"GET /api/pipeline/output-folders/:jobId <p>Liefert bekannte Output-Ordner entlang der Job-Lineage.</p>","text":""},{"location":"api/pipeline/#post-apipipelinedelete-output-foldersjobid","title":"POST /api/pipeline/delete-output-folders/:jobId <p>L\u00f6scht ausgew\u00e4hlte Output-Ordner.</p> <p>Request:</p> <pre><code>{ \"folderPaths\": [\"/mnt/movies/Inception (2010)\"] }\n</code></pre> <p>Alle Endpunkte liefern <code>{ result: ... }</code> bzw. <code>{ job: ... }</code>.</p>","text":""},{"location":"api/pipeline/#queue-endpunkte","title":"Queue-Endpunkte","text":""},{"location":"api/pipeline/#get-apipipelinequeue","title":"GET /api/pipeline/queue","text":"<p>Liefert Queue-Snapshot.</p> <pre><code>{\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</code></pre>"},{"location":"api/pipeline/#post-apipipelinequeuereorder","title":"POST /api/pipeline/queue/reorder","text":"<p>Sortiert Queue-Eintr\u00e4ge neu.</p> <p>Request:</p> <pre><code>{\n \"orderedEntryIds\": [12, 11]\n}\n</code></pre> <p>Legacy fallback wird akzeptiert:</p> <pre><code>{\n \"orderedJobIds\": [42, 43]\n}\n</code></pre>"},{"location":"api/pipeline/#post-apipipelinequeueentry","title":"POST /api/pipeline/queue/entry","text":"<p>F\u00fcgt Nicht-Job-Queue-Eintrag hinzu (<code>script</code>, <code>chain</code>, <code>wait</code>).</p> <p>Request-Beispiele:</p> <pre><code>{ \"type\": \"script\", \"scriptId\": 3 }\n</code></pre> <pre><code>{ \"type\": \"chain\", \"chainId\": 2, \"insertAfterEntryId\": 11 }\n</code></pre> <pre><code>{ \"type\": \"wait\", \"waitSeconds\": 45 }\n</code></pre> <p>Response:</p> <pre><code>{\n \"result\": { \"entryId\": 12, \"type\": \"wait\", \"position\": 2 },\n \"queue\": { \"...\": \"...\" }\n}\n</code></pre>"},{"location":"api/pipeline/#delete-apipipelinequeueentryentryid","title":"DELETE /api/pipeline/queue/entry/:entryId","text":"<p>Entfernt Queue-Eintrag.</p> <p>Response:</p> <pre><code>{ \"queue\": { \"...\": \"...\" } }\n</code></pre>"},{"location":"api/pipeline/#pipeline-zustande","title":"Pipeline-Zust\u00e4nde State Bedeutung <code>IDLE</code> Wartet auf Medium <code>DISC_DETECTED</code> Medium erkannt <code>ANALYZING</code> MakeMKV-Analyse l\u00e4uft <code>METADATA_SELECTION</code> Metadaten-Auswahl <code>WAITING_FOR_USER_DECISION</code> Nutzerentscheidung erforderlich (Playlist-Auswahl oder RAW-Entscheidung) <code>READY_TO_START</code> \u00dcbergang vor Start <code>RIPPING</code> MakeMKV-Rip l\u00e4uft <code>MEDIAINFO_CHECK</code> Titel-/Track-Auswertung <code>READY_TO_ENCODE</code> Review bereit <code>ENCODING</code> HandBrake-Encoding l\u00e4uft <code>CD_METADATA_SELECTION</code> CD-Metadatenauswahl aktiv <code>CD_READY_TO_RIP</code> CD-Job ist startbereit <code>CD_ANALYZING</code> CD-Struktur/Tracks werden vorbereitet <code>CD_RIPPING</code> CD-Ripping l\u00e4uft <code>CD_ENCODING</code> CD-Encode l\u00e4uft <code>FINISHED</code> Abgeschlossen <code>DONE</code> Abgeschlossen (v. a. Audiobook/Converter/CD-Varianten) <code>CANCELLED</code> Abgebrochen <code>ERROR</code> Fehler","text":""},{"location":"api/runtime-activities/","title":"Runtime Activities API","text":"<p>Ripster verfolgt alle laufenden und k\u00fcrzlich abgeschlossenen Aktivit\u00e4ten (Skripte, Skript-Ketten, Cron-Jobs, interne Tasks) in Echtzeit \u00fcber den <code>RuntimeActivityService</code>.</p>"},{"location":"api/runtime-activities/#ubersicht","title":"\u00dcbersicht","text":"<p>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.</p> <ul> <li>Aktive Aktivit\u00e4ten (<code>active</code>): Laufen gerade.</li> <li>Letzte Aktivit\u00e4ten (<code>recent</code>): Abgeschlossen, max. 120 Eintr\u00e4ge.</li> </ul> <p>\u00c4nderungen werden \u00fcber WebSocket (<code>RUNTIME_ACTIVITY_CHANGED</code>) in Echtzeit gesendet.</p>"},{"location":"api/runtime-activities/#aktivitats-objekt","title":"Aktivit\u00e4ts-Objekt","text":"<pre><code>{\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</code></pre>"},{"location":"api/runtime-activities/#felder","title":"Felder","text":"Feld Typ Beschreibung <code>id</code> <code>number</code> Eindeutige ID (Laufz\u00e4hler, nicht persistent) <code>type</code> <code>string</code> Art der Aktivit\u00e4t: <code>script</code> | <code>chain</code> | <code>cron</code> | <code>task</code> <code>name</code> <code>string \\| null</code> Anzeigename der Aktivit\u00e4t <code>status</code> <code>string</code> Aktueller Status: <code>running</code> | <code>success</code> | <code>error</code> <code>source</code> <code>string \\| null</code> Ausl\u00f6ser (z. B. <code>cron</code>, <code>pipeline</code>, <code>manual</code>) <code>message</code> <code>string \\| null</code> Kurztext zum aktuellen Zustand <code>currentStep</code> <code>string \\| null</code> Name des aktuell ausgef\u00fchrten Schritts <code>currentStepType</code> <code>string \\| null</code> Typ des Schritts (z. B. <code>script</code>, <code>wait</code>) <code>currentScriptName</code> <code>string \\| null</code> Name des Skripts im aktuellen Schritt <code>stepIndex</code> <code>number \\| null</code> Aktueller Schritt (1-basiert) <code>stepTotal</code> <code>number \\| null</code> Gesamtanzahl Schritte <code>parentActivityId</code> <code>number \\| null</code> ID der \u00fcbergeordneten Aktivit\u00e4t <code>jobId</code> <code>number \\| null</code> Verkn\u00fcpfte Job-ID <code>cronJobId</code> <code>number \\| null</code> Verkn\u00fcpfte Cron-Job-ID <code>chainId</code> <code>number \\| null</code> Verkn\u00fcpfte Skript-Ketten-ID <code>scriptId</code> <code>number \\| null</code> Verkn\u00fcpfte Skript-ID <code>canCancel</code> <code>boolean</code> Abbrechen \u00fcber API m\u00f6glich <code>canNextStep</code> <code>boolean</code> N\u00e4chster Schritt \u00fcber API ausl\u00f6sbar <code>outcome</code> <code>string \\| null</code> Abschluss-Ergebnis: <code>success</code> | <code>error</code> | <code>cancelled</code> | <code>skipped</code> | <code>running</code> <code>errorMessage</code> <code>string \\| null</code> Fehlermeldung (max. 2.000 Zeichen) <code>output</code> <code>string \\| null</code> Allgemeine Ausgabe (max. 12.000 Zeichen) <code>stdout</code> <code>string \\| null</code> Standardausgabe des Prozesses (max. 12.000 Zeichen) <code>stderr</code> <code>string \\| null</code> Fehlerausgabe des Prozesses (max. 12.000 Zeichen) <code>stdoutTruncated</code> <code>boolean</code> <code>true</code>, wenn <code>stdout</code> gek\u00fcrzt wurde <code>stderrTruncated</code> <code>boolean</code> <code>true</code>, wenn <code>stderr</code> gek\u00fcrzt wurde <code>startedAt</code> <code>string</code> ISO-8601-Zeitstempel des Starts <code>finishedAt</code> <code>string \\| null</code> ISO-8601-Zeitstempel des Endes <code>durationMs</code> <code>number \\| null</code> Laufzeit in Millisekunden <code>exitCode</code> <code>number \\| null</code> Exit-Code des Prozesses <code>success</code> <code>boolean \\| null</code> Erfolgsstatus (<code>null</code> bei laufender Aktivit\u00e4t)"},{"location":"api/runtime-activities/#snapshot-objekt","title":"Snapshot-Objekt","text":"<p>Alle Aktivit\u00e4ts-Endpunkte geben einen Snapshot zur\u00fcck:</p> <pre><code>{\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</code></pre>"},{"location":"api/runtime-activities/#endpunkte","title":"Endpunkte","text":""},{"location":"api/runtime-activities/#get-apiruntimeactivities","title":"GET <code>/api/runtime/activities</code>","text":"<p>Aktuellen Aktivit\u00e4ts-Snapshot abrufen.</p> <p>Antwort:</p> <pre><code>{\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</code></pre>"},{"location":"api/runtime-activities/#post-apiruntimeactivitiesidcancel","title":"POST <code>/api/runtime/activities/:id/cancel</code>","text":"<p>Aktive Aktivit\u00e4t abbrechen (nur wenn <code>canCancel: true</code>).</p> <p>Parameter:</p> Name In Typ Beschreibung <code>id</code> path <code>number</code> Aktivit\u00e4ts-ID <code>reason</code> body <code>string</code> Optionaler Abbruchgrund <p>Request Body:</p> <pre><code>{ \"reason\": \"Manueller Abbruch durch Benutzer\" }\n</code></pre> <p>Antwort (Erfolg):</p> <pre><code>{\n \"ok\": true,\n \"action\": null,\n \"snapshot\": { \"active\": [], \"recent\": [], \"updatedAt\": \"...\" }\n}\n</code></pre> <p>Fehlercodes:</p> HTTP Bedeutung <code>404</code> Aktivit\u00e4t nicht gefunden oder bereits abgeschlossen <code>409</code> Abbrechen wird von dieser Aktivit\u00e4t nicht unterst\u00fctzt"},{"location":"api/runtime-activities/#post-apiruntimeactivitiesidnext-step","title":"POST <code>/api/runtime/activities/:id/next-step</code>","text":"<p>N\u00e4chsten Schritt einer Aktivit\u00e4t ausl\u00f6sen (nur wenn <code>canNextStep: true</code>).</p> <p>Parameter:</p> Name In Typ Beschreibung <code>id</code> path <code>number</code> Aktivit\u00e4ts-ID <p>Antwort (Erfolg):</p> <pre><code>{\n \"ok\": true,\n \"action\": null,\n \"snapshot\": { \"active\": [], \"recent\": [], \"updatedAt\": \"...\" }\n}\n</code></pre> <p>Fehlercodes:</p> HTTP Bedeutung <code>404</code> Aktivit\u00e4t nicht gefunden <code>409</code> N\u00e4chster Schritt wird von dieser Aktivit\u00e4t nicht unterst\u00fctzt"},{"location":"api/runtime-activities/#post-apiruntimeactivitiesclear-recent","title":"POST <code>/api/runtime/activities/clear-recent</code>","text":"<p>Alle abgeschlossenen Aktivit\u00e4ten aus <code>recent</code> l\u00f6schen.</p> <p>Antwort:</p> <pre><code>{\n \"ok\": true,\n \"removed\": 14,\n \"snapshot\": { \"active\": [], \"recent\": [], \"updatedAt\": \"...\" }\n}\n</code></pre>"},{"location":"api/runtime-activities/#grenzwerte","title":"Grenzwerte","text":"Wert Limit Maximale <code>recent</code>-Eintr\u00e4ge 120 Maximale L\u00e4nge <code>stdout</code> / <code>stderr</code> / <code>output</code> 12.000 Zeichen Maximale L\u00e4nge <code>errorMessage</code> / <code>message</code> 2.000 Zeichen Maximale L\u00e4nge <code>outcome</code> 40 Zeichen <p>Gek\u00fcrzte Ausgaben erhalten den Suffix <code>...[gek\u00fcrzt]</code> (bei Inline-Text) bzw. <code>\\n...[gek\u00fcrzt]</code> (bei mehrzeiligem Output).</p>"},{"location":"api/runtime-activities/#echtzeit-updates","title":"Echtzeit-Updates","text":"<p>\u00c4nderungen werden automatisch als <code>RUNTIME_ACTIVITY_CHANGED</code> WebSocket-Event gesendet. Die Frontend-Komponente braucht <code>GET /api/runtime/activities</code> nur beim initialen Laden aufzurufen.</p>"},{"location":"api/settings/","title":"Settings API","text":"<p>Endpunkte f\u00fcr Einstellungen, Skripte, Skript-Ketten und User-Presets.</p>"},{"location":"api/settings/#get-apisettings","title":"GET /api/settings","text":"<p>Liefert alle Einstellungen kategorisiert.</p> <p>Response (Struktur):</p> <pre><code>{\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</code></pre>"},{"location":"api/settings/#put-apisettingskey","title":"PUT /api/settings/:key","text":"<p>Aktualisiert eine einzelne Einstellung.</p> <p>Request:</p> <pre><code>{ \"value\": \"/mnt/storage/raw\" }\n</code></pre> <p>Response:</p> <pre><code>{\n \"setting\": {\n \"key\": \"raw_dir\",\n \"value\": \"/mnt/storage/raw\"\n },\n \"reviewRefresh\": {\n \"triggered\": false,\n \"reason\": \"not_ready\"\n }\n}\n</code></pre> <p><code>reviewRefresh</code> ist <code>null</code> oder ein Objekt mit Status der optionalen Review-Neuberechnung.</p>"},{"location":"api/settings/#put-apisettings","title":"PUT /api/settings","text":"<p>Aktualisiert mehrere Einstellungen atomar.</p> <p>Request:</p> <pre><code>{\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</code></pre> <p>Response:</p> <pre><code>{\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</code></pre> <p>Bei Validierungsfehlern kommt <code>400</code> mit <code>error.details[]</code>.</p>"},{"location":"api/settings/#get-apisettingshandbrake-presets","title":"GET /api/settings/handbrake-presets","text":"<p>Liest Preset-Liste via <code>HandBrakeCLI -z</code> (mit Fallback auf konfigurierte Presets).</p> <p>Response (Beispiel):</p> <pre><code>{\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</code></pre>"},{"location":"api/settings/#post-apisettingspushovertest","title":"POST /api/settings/pushover/test","text":"<p>Sendet Testnachricht \u00fcber aktuelle PushOver-Settings.</p> <p>Request (optional):</p> <pre><code>{\n \"title\": \"Test\",\n \"message\": \"Ripster Test\"\n}\n</code></pre> <p>Response:</p> <pre><code>{\n \"result\": {\n \"sent\": true,\n \"eventKey\": \"test\",\n \"requestId\": \"...\"\n }\n}\n</code></pre> <p>Wenn PushOver deaktiviert ist oder Credentials fehlen, kommt i. d. R. ebenfalls <code>200</code> mit <code>sent: false</code> + <code>reason</code>.</p>"},{"location":"api/settings/#skripte","title":"Skripte","text":"<p>Basis: <code>/api/settings/scripts</code></p>"},{"location":"api/settings/#get-apisettingsscripts","title":"GET /api/settings/scripts","text":"<pre><code>{ \"scripts\": [ { \"id\": 1, \"name\": \"...\", \"scriptBody\": \"...\", \"orderIndex\": 1, \"createdAt\": \"...\", \"updatedAt\": \"...\" } ] }\n</code></pre>"},{"location":"api/settings/#post-apisettingsscripts","title":"POST /api/settings/scripts","text":"<pre><code>{ \"name\": \"Move\", \"scriptBody\": \"mv \\\"$RIPSTER_OUTPUT_PATH\\\" /mnt/movies/\" }\n</code></pre> <p>Response: <code>201</code> mit <code>{ \"script\": { ... } }</code></p>"},{"location":"api/settings/#put-apisettingsscriptsid","title":"PUT /api/settings/scripts/:id","text":"<p>Body wie <code>POST</code>, Response <code>{ \"script\": { ... } }</code>.</p>"},{"location":"api/settings/#delete-apisettingsscriptsid","title":"DELETE /api/settings/scripts/:id","text":"<p>Response <code>{ \"removed\": { ... } }</code>.</p>"},{"location":"api/settings/#post-apisettingsscriptsreorder","title":"POST /api/settings/scripts/reorder","text":"<pre><code>{ \"orderedScriptIds\": [3, 1, 2] }\n</code></pre> <p>Response <code>{ \"scripts\": [ ... ] }</code>.</p>"},{"location":"api/settings/#post-apisettingsscriptsidtest","title":"POST /api/settings/scripts/:id/test","text":"<p>F\u00fchrt Skript als Testlauf aus.</p> <pre><code>{\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</code></pre>"},{"location":"api/settings/#umgebungsvariablen-fur-skripte","title":"Umgebungsvariablen f\u00fcr Skripte","text":"<p>Diese Variablen werden beim Ausf\u00fchren gesetzt:</p> <ul> <li><code>RIPSTER_SCRIPT_RUN_AT</code></li> <li><code>RIPSTER_JOB_ID</code></li> <li><code>RIPSTER_JOB_TITLE</code></li> <li><code>RIPSTER_MODE</code></li> <li><code>RIPSTER_INPUT_PATH</code></li> <li><code>RIPSTER_OUTPUT_PATH</code></li> <li><code>RIPSTER_RAW_PATH</code></li> <li><code>RIPSTER_SCRIPT_ID</code></li> <li><code>RIPSTER_SCRIPT_NAME</code></li> <li><code>RIPSTER_SCRIPT_SOURCE</code></li> </ul>"},{"location":"api/settings/#skript-ketten","title":"Skript-Ketten","text":"<p>Basis: <code>/api/settings/script-chains</code></p> <p>Eine Kette hat Schritte vom Typ:</p> <ul> <li><code>script</code> (<code>scriptId</code> erforderlich)</li> <li><code>wait</code> (<code>waitSeconds</code> 1..3600)</li> </ul>"},{"location":"api/settings/#get-apisettingsscript-chains","title":"GET /api/settings/script-chains","text":"<p>Response <code>{ \"chains\": [ ... ] }</code> (inkl. <code>steps[]</code>).</p>"},{"location":"api/settings/#get-apisettingsscript-chainsid","title":"GET /api/settings/script-chains/:id","text":"<p>Response <code>{ \"chain\": { ... } }</code>.</p>"},{"location":"api/settings/#post-apisettingsscript-chains","title":"POST /api/settings/script-chains","text":"<pre><code>{\n \"name\": \"After Encode\",\n \"steps\": [\n { \"stepType\": \"script\", \"scriptId\": 1 },\n { \"stepType\": \"wait\", \"waitSeconds\": 15 },\n { \"stepType\": \"script\", \"scriptId\": 2 }\n ]\n}\n</code></pre> <p>Response: <code>201</code> mit <code>{ \"chain\": { ... } }</code></p>"},{"location":"api/settings/#put-apisettingsscript-chainsid","title":"PUT /api/settings/script-chains/:id","text":"<p>Body wie <code>POST</code>, Response <code>{ \"chain\": { ... } }</code>.</p>"},{"location":"api/settings/#delete-apisettingsscript-chainsid","title":"DELETE /api/settings/script-chains/:id","text":"<p>Response <code>{ \"removed\": { ... } }</code>.</p>"},{"location":"api/settings/#post-apisettingsscript-chainsreorder","title":"POST /api/settings/script-chains/reorder","text":"<pre><code>{ \"orderedChainIds\": [2, 1, 3] }\n</code></pre> <p>Response <code>{ \"chains\": [ ... ] }</code>.</p>"},{"location":"api/settings/#post-apisettingsscript-chainsidtest","title":"POST /api/settings/script-chains/:id/test","text":"<p>Response:</p> <pre><code>{\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</code></pre>"},{"location":"api/settings/#user-presets","title":"User-Presets","text":"<p>Basis: <code>/api/settings/user-presets</code></p>"},{"location":"api/settings/#get-apisettingsuser-presets","title":"GET /api/settings/user-presets","text":"<p>Optionaler Query-Parameter: <code>media_type=bluray|dvd|other|all</code></p> <pre><code>{\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</code></pre>"},{"location":"api/settings/#post-apisettingsuser-presets","title":"POST /api/settings/user-presets","text":"<pre><code>{\n \"name\": \"Blu-ray HQ\",\n \"mediaType\": \"bluray\",\n \"handbrakePreset\": \"H.264 MKV 1080p30\",\n \"extraArgs\": \"--encoder-preset slow\",\n \"description\": \"optional\"\n}\n</code></pre> <p>Response: <code>201</code> mit <code>{ \"preset\": { ... } }</code></p>"},{"location":"api/settings/#put-apisettingsuser-presetsid","title":"PUT /api/settings/user-presets/:id","text":"<p>Body mit beliebigen Feldern aus <code>POST</code>, Response <code>{ \"preset\": { ... } }</code>.</p>"},{"location":"api/settings/#delete-apisettingsuser-presetsid","title":"DELETE /api/settings/user-presets/:id","text":"<p>Response <code>{ \"removed\": { ... } }</code>.</p>"},{"location":"api/settings/#weitere-endpunkte","title":"Weitere Endpunkte","text":""},{"location":"api/settings/#get-apisettingseffective-paths","title":"GET /api/settings/effective-paths","text":"<p>Liefert aufgel\u00f6ste, effektiv genutzte Pfade aus den Settings (f\u00fcr UI- und Diagnosezwecke).</p>"},{"location":"api/settings/#post-apisettingscoverartrecover","title":"POST /api/settings/coverart/recover","text":"<p>Startet eine manuelle Coverart-Recovery.</p> <p>Response (Beispiel):</p> <pre><code>{\n \"result\": { \"started\": true },\n \"scheduler\": { \"enabled\": true }\n}\n</code></pre>"},{"location":"api/settings/#activation-bytes-aax","title":"Activation Bytes (AAX)","text":""},{"location":"api/settings/#get-apisettingsactivation-bytes","title":"GET /api/settings/activation-bytes","text":"<p>Liest gecachte AAX-Activation-Bytes.</p>"},{"location":"api/settings/#post-apisettingsactivation-bytes","title":"POST /api/settings/activation-bytes","text":"<p>Speichert Activation-Bytes.</p> <p>Request:</p> <pre><code>{\n \"checksum\": \"abc123...\",\n \"activationBytes\": \"1a2b3c4d\"\n}\n</code></pre>"},{"location":"api/settings/#laufwerke","title":"Laufwerke","text":""},{"location":"api/settings/#get-apisettingsdrives","title":"GET /api/settings/drives","text":"<p>Liefert erkannte optische Laufwerke (<code>/dev/...</code>) inkl. MakeMKV-Disc-Index.</p>"},{"location":"api/settings/#post-apisettingsdrivesforce-unlock","title":"POST /api/settings/drives/force-unlock","text":"<p>Erzwingt Entsperren aktiver Laufwerkslocks.</p> <p>Hinweis: Expertenmodus (<code>ui_expert_mode</code>) ist erforderlich, sonst <code>403</code>.</p> <p>Request (ein Laufwerk):</p> <pre><code>{ \"devicePath\": \"/dev/sr0\" }\n</code></pre> <p>Request (alle):</p> <pre><code>{ \"all\": true }\n</code></pre>"},{"location":"api/settings/#ui-preferences","title":"UI Preferences","text":""},{"location":"api/settings/#get-apisettingsprefskey","title":"GET /api/settings/prefs/:key","text":"<p>Liest einen persistierten UI-Preference-Wert.</p>"},{"location":"api/settings/#put-apisettingsprefskey","title":"PUT /api/settings/prefs/:key","text":"<p>Speichert einen persistierten UI-Preference-Wert.</p> <p>Request:</p> <pre><code>{ \"value\": \"{\\\"columns\\\":[\\\"id\\\",\\\"status\\\"]}\" }\n</code></pre>"},{"location":"api/websocket/","title":"WebSocket Events","text":"<p>Ripster sendet Echtzeit-Updates \u00fcber <code>/ws</code>.</p>"},{"location":"api/websocket/#verbindung","title":"Verbindung","text":"<pre><code>const ws = new WebSocket('ws://localhost:3001/ws');\n\nws.onmessage = (event) =&gt; {\n const msg = JSON.parse(event.data);\n console.log(msg.type, msg.payload);\n};\n</code></pre>"},{"location":"api/websocket/#nachrichtenformat","title":"Nachrichtenformat","text":"<p>Die meisten Broadcasts haben dieses Schema:</p> <pre><code>{\n \"type\": \"EVENT_TYPE\",\n \"payload\": {},\n \"timestamp\": \"2026-03-10T09:00:00.000Z\"\n}\n</code></pre> <p>Ausnahme: <code>WS_CONNECTED</code> beim Verbindungsaufbau enth\u00e4lt kein <code>timestamp</code>.</p>"},{"location":"api/websocket/#event-typen","title":"Event-Typen","text":""},{"location":"api/websocket/#ws_connected","title":"WS_CONNECTED","text":"<p>Sofort nach erfolgreicher Verbindung.</p> <pre><code>{\n \"type\": \"WS_CONNECTED\",\n \"payload\": {\n \"connectedAt\": \"2026-03-10T09:00:00.000Z\"\n }\n}\n</code></pre>"},{"location":"api/websocket/#pipeline_state_changed","title":"PIPELINE_STATE_CHANGED","text":"<p>Neuer Pipeline-Snapshot.</p> <pre><code>{\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</code></pre>"},{"location":"api/websocket/#pipeline_progress","title":"PIPELINE_PROGRESS","text":"<p>Laufende Fortschrittsupdates.</p> <pre><code>{\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</code></pre>"},{"location":"api/websocket/#pipeline_queue_changed","title":"PIPELINE_QUEUE_CHANGED","text":"<p>Queue-Snapshot aktualisiert.</p>"},{"location":"api/websocket/#disc_detected-disc_removed","title":"DISC_DETECTED / DISC_REMOVED","text":"<p>Disc-Insertion/-Removal.</p> <pre><code>{\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</code></pre> <p><code>mediaProfile</code>: <code>bluray</code> | <code>dvd</code> | <code>other</code> | <code>null</code></p>"},{"location":"api/websocket/#hardware_monitor_update","title":"HARDWARE_MONITOR_UPDATE","text":"<p>Snapshot aus Hardware-Monitoring.</p> <pre><code>{\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</code></pre>"},{"location":"api/websocket/#pipeline_error","title":"PIPELINE_ERROR","text":"<p>Fehler bei Disc-Event-Verarbeitung in Pipeline.</p>"},{"location":"api/websocket/#disk_detection_error","title":"DISK_DETECTION_ERROR","text":"<p>Fehler in Laufwerkserkennung.</p>"},{"location":"api/websocket/#settings_updated","title":"SETTINGS_UPDATED","text":"<p>Einzelnes Setting wurde gespeichert.</p>"},{"location":"api/websocket/#settings_bulk_updated","title":"SETTINGS_BULK_UPDATED","text":"<p>Bulk-Settings gespeichert.</p> <pre><code>{\n \"type\": \"SETTINGS_BULK_UPDATED\",\n \"payload\": {\n \"count\": 3,\n \"keys\": [\"raw_dir\", \"movie_dir\", \"handbrake_preset_bluray\"]\n }\n}\n</code></pre>"},{"location":"api/websocket/#settings_scripts_updated","title":"SETTINGS_SCRIPTS_UPDATED","text":"<p>Skript ge\u00e4ndert (<code>created|updated|deleted|reordered</code>).</p>"},{"location":"api/websocket/#settings_script_chains_updated","title":"SETTINGS_SCRIPT_CHAINS_UPDATED","text":"<p>Skript-Kette ge\u00e4ndert (<code>created|updated|deleted|reordered</code>).</p>"},{"location":"api/websocket/#user_presets_updated","title":"USER_PRESETS_UPDATED","text":"<p>User-Preset ge\u00e4ndert (<code>created|updated|deleted</code>).</p>"},{"location":"api/websocket/#cron_jobs_updated","title":"CRON_JOBS_UPDATED","text":"<p>Cron-Config ge\u00e4ndert (<code>created|updated|deleted</code>).</p>"},{"location":"api/websocket/#cron_job_updated","title":"CRON_JOB_UPDATED","text":"<p>Laufzeitstatus eines Cron-Jobs ge\u00e4ndert.</p> <pre><code>{\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</code></pre>"},{"location":"api/websocket/#runtime_activity_changed","title":"RUNTIME_ACTIVITY_CHANGED","text":"<p>Vollst\u00e4ndiger Snapshot aller laufenden und k\u00fcrzlich abgeschlossenen Aktivit\u00e4ten.</p> <p>Wird ausgel\u00f6st, wenn eine Aktivit\u00e4t gestartet, aktualisiert oder abgeschlossen wird sowie nach <code>clear-recent</code>.</p> <pre><code>{\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</code></pre> <p>Vollst\u00e4ndige Feldbeschreibung: Runtime Activities API.</p>"},{"location":"api/websocket/#converter_scan_update","title":"CONVERTER_SCAN_UPDATE","text":"<p>Wird nach einem Scan des Converter-Eingangsordners gesendet (manuell oder per Polling).</p> <pre><code>{\n \"type\": \"CONVERTER_SCAN_UPDATE\",\n \"payload\": {\n \"entryCount\": 12\n }\n}\n</code></pre>"},{"location":"api/websocket/#downloads_updated","title":"DOWNLOADS_UPDATED","text":"<p>Wird bei jeder Status\u00e4nderung in der Download-Queue gesendet.</p> <pre><code>{\n \"type\": \"DOWNLOADS_UPDATED\",\n \"payload\": {\n \"reason\": \"ready\",\n \"item\": {\n \"id\": \"dl-1\",\n \"jobId\": 42,\n \"status\": \"ready\",\n \"archiveName\": \"Job_42_movie.zip\",\n \"createdAt\": \"2026-03-30T10:00:00.000Z\"\n },\n \"summary\": {\n \"total\": 3,\n \"pending\": 1,\n \"processing\": 0,\n \"ready\": 1,\n \"failed\": 1\n }\n }\n}\n</code></pre> <p>M\u00f6gliche <code>reason</code>-Werte: <code>queued</code>, <code>processing</code>, <code>ready</code>, <code>failed</code>, <code>deleted</code>.</p>"},{"location":"api/websocket/#reconnect-verhalten","title":"Reconnect-Verhalten","text":"<p><code>useWebSocket</code> verbindet bei Abbruch automatisch neu:</p> <ul> <li>Retry-Intervall: <code>1500ms</code></li> <li>Wiederverbindung bis Komponente unmounted wird</li> </ul>"},{"location":"appendix/","title":"Technischer Anhang","text":"<p>Dieser Bereich enth\u00e4lt die technische Referenz hinter dem Benutzerhandbuch.</p>"},{"location":"appendix/#inhalt","title":"Inhalt","text":"<ul> <li>Konfiguration</li> <li>komplette Feldreferenz</li> <li>Umgebungsvariablen</li> <li>Pipeline intern</li> <li>Zustandsmodell</li> <li>Encode-Planung</li> <li>Playlist-Analyse</li> <li>Pre-/Post-Encode-Ausf\u00fchrungen</li> <li>API-Referenz</li> <li>REST-Endpunkte</li> <li>WebSocket-Events</li> <li>Architektur</li> <li>Backend-/Frontend-Aufbau</li> <li>Datenbank</li> <li>Deployment</li> <li>Betrieb in Entwicklung und Produktion</li> <li>Externe Tools</li> <li>MakeMKV, HandBrake, MediaInfo</li> </ul>"},{"location":"appendix/#wann-du-in-den-anhang-wechselst","title":"Wann du in den Anhang wechselst","text":"<ul> <li>du integrierst Ripster mit anderen Systemen</li> <li>du betreibst mehrere Instanzen oder willst tiefer debuggen</li> <li>du brauchst Feld-/API-/Schema-Details f\u00fcr Automatisierung</li> </ul>"},{"location":"architecture/","title":"Anhang: Architektur","text":"<p>Ripster ist eine Client-Server-Anwendung mit REST + WebSocket und externen CLI-Tools.</p>"},{"location":"architecture/#systemuberblick","title":"System\u00fcberblick","text":"<pre><code>graph TB\n subgraph Browser[\"Browser (React)\"]\n Ripper[Ripper]\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 &lt;--&gt;|HTTP| API\n Browser &lt;--&gt;|WebSocket| WS\n Pipeline --&gt; MakeMKV\n Pipeline --&gt; HandBrake\n Pipeline --&gt; MediaInfo\n API --&gt; DB\n Pipeline --&gt; DB\n Cron --&gt; DB</code></pre>"},{"location":"architecture/#details","title":"Details","text":"<ul> <li> \u00dcbersicht</li> <li> Backend-Services</li> <li> Frontend-Komponenten</li> <li> Datenbank</li> </ul>"},{"location":"architecture/backend/","title":"Backend-Services","text":"<p>Das Backend ist in Services aufgeteilt, die von Express-Routen orchestriert werden. Seit v0.12.0 erfolgt die Medienverarbeitung \u00fcber ein Plugin-System.</p>"},{"location":"architecture/backend/#plugin-system-srcplugins","title":"Plugin-System (<code>src/plugins/</code>)","text":"<p>Ab v0.12.0 ist die Pipeline modular aufgebaut. Jeder Medientyp wird von einem eigenen Plugin verwaltet.</p>"},{"location":"architecture/backend/#basisklassen","title":"Basisklassen","text":"<ul> <li><code>PluginBase.js</code> \u2014 Abstrakte Basisklasse <code>SourcePlugin</code> mit Lifecycle-Methoden</li> <li><code>PluginRegistry.js</code> \u2014 Dynamische Plugin-Erkennung, priorit\u00e4tsbasierte Auswahl, Settings-Schema-Aggregation</li> <li><code>PluginContext.js</code> \u2014 Ausf\u00fchrungskontext (Logger, Callbacks, Signals) f\u00fcr Plugin-Aufrufe</li> </ul>"},{"location":"architecture/backend/#plugin-lifecycle","title":"Plugin-Lifecycle","text":"<p>Jedes Plugin implementiert die folgenden Methoden:</p> Methode Beschreibung <code>detect(discInfo)</code> Medientyp-Erkennung <code>analyze(devicePath, job, ctx)</code> Analyse / Metadaten-Extraktion <code>rip(job, ctx)</code> Rohdaten-Extraktion <code>review(job, ctx)</code> Optionale Vorschau-Vorbereitung <code>encode(job, ctx)</code> Finales Encoding/Konvertierung <code>finalize(job, ctx)</code> Nachbearbeitung <code>onCancel(job, ctx)</code> Bereinigung bei Abbruch <code>onRetry(job, ctx)</code> Zustand-Reset vor Retry"},{"location":"architecture/backend/#implementierte-plugins","title":"Implementierte Plugins","text":"<ul> <li><code>BluRayPlugin.js</code> \u2014 Blu-ray via MakeMKV (Backup-Modus)</li> <li><code>DVDPlugin.js</code> \u2014 DVD via MakeMKV (MKV-Modus)</li> <li><code>CdPlugin.js</code> \u2014 Audio-CD via cdparanoia + FFmpeg (experimentell)</li> <li><code>AudiobookPlugin.js</code> \u2014 AAX/M4B via FFmpeg mit Kapitel-Splitting</li> <li><code>ConverterPlugin.js</code> \u2014 Generische Audio/Video-Konvertierung via FFmpeg</li> <li><code>VideoDiscPlugin.js</code> \u2014 Gemeinsame Basis f\u00fcr Blu-ray/DVD (MediaInfo-Parsing)</li> </ul>"},{"location":"architecture/backend/#pipelineservicejs","title":"<code>pipelineService.js</code>","text":"<p>Zentrale Workflow-Orchestrierung.</p> <p>Aufgaben:</p> <ul> <li>Pipeline-State-Machine + Persistenz (<code>pipeline_state</code>)</li> <li>Disc-Analyse/Rip/Review/Encode via Plugin-Delegation</li> <li>Queue-Management (Jobs + <code>script|chain|wait</code> Eintr\u00e4ge)</li> <li>Retry/Re-Encode/Restart-Flows</li> <li>WebSocket-Broadcasts f\u00fcr State/Progress/Queue</li> <li>Converter-Job-Verwaltung (<code>createConverterJobFromEntry</code>, <code>uploadConverterFiles</code>, <code>startConverterJob</code>)</li> </ul> <p>Wichtige Methoden:</p> <ul> <li><code>analyzeDisc()</code></li> <li><code>selectMetadata()</code></li> <li><code>startPreparedJob()</code></li> <li><code>confirmEncodeReview()</code></li> <li><code>cancel()</code></li> <li><code>retry()</code></li> <li><code>reencodeFromRaw()</code></li> <li><code>restartReviewFromRaw()</code></li> <li><code>restartEncodeWithLastSettings()</code></li> <li><code>resumeReadyToEncodeJob()</code></li> <li><code>enqueueNonJobEntry()</code>, <code>reorderQueue()</code>, <code>removeQueueEntry()</code></li> <li><code>createConverterJobFromEntry()</code>, <code>createConverterJobsFromSelection()</code></li> <li><code>uploadConverterFiles()</code>, <code>startConverterJob()</code></li> </ul>"},{"location":"architecture/backend/#diskdetectionservicejs","title":"<code>diskDetectionService.js</code>","text":"<p>Pollt Laufwerk(e) und emittiert:</p> <ul> <li><code>discInserted</code></li> <li><code>discRemoved</code></li> <li><code>error</code></li> </ul> <p>Zusatz:</p> <ul> <li>Modus <code>auto</code> oder <code>explicit</code></li> <li>heuristische <code>mediaProfile</code>-Erkennung (<code>bluray</code>/<code>dvd</code>/<code>other</code>)</li> <li><code>rescanAndEmit()</code> f\u00fcr manuellen Trigger</li> </ul>"},{"location":"architecture/backend/#settingsservicejs","title":"<code>settingsService.js</code>","text":"<p>Settings-Layer mit Validation/Serialisierung.</p> <p>Features:</p> <ul> <li><code>getCategorizedSettings()</code> f\u00fcr UI-Form</li> <li><code>setSettingValue()</code> / <code>setSettingsBulk()</code></li> <li>profilspezifische Aufl\u00f6sung (<code>resolveEffectiveToolSettings</code>)</li> <li>CLI-Config-Building f\u00fcr MakeMKV/HandBrake/MediaInfo/FFmpeg</li> <li>HandBrake-Preset-Liste via <code>HandBrakeCLI -z</code></li> <li>MakeMKV-Key-Synchronisation aus <code>makemkv_registration_key</code> nach <code>~/.MakeMKV/settings.conf</code></li> <li>Pfadaufl\u00f6sung f\u00fcr alle Medienprofile inkl. Audiobook und Converter</li> </ul>"},{"location":"architecture/backend/#historyservicejs","title":"<code>historyService.js</code>","text":"<p>Historie + Dateioperationen.</p> <p>Features:</p> <ul> <li>Job-Liste/Detail inkl. Log-Tail</li> <li>Orphan-RAW-Erkennung und Import</li> <li>TMDb-Neuzuordnung</li> <li>Dateil\u00f6schung (<code>raw|movie|both</code>)</li> <li>Job-L\u00f6schung (<code>none|raw|movie|both</code>)</li> </ul>"},{"location":"architecture/backend/#audiobookservicejs","title":"<code>audiobookService.js</code>","text":"<p>Audiobook-Verarbeitung (AAX/M4B).</p> <p>Features:</p> <ul> <li>FFprobe-basierte Analyse (Kapitel, Metadaten)</li> <li>FFmpeg-basiertes Encoding mit Kapitel-Splitting</li> <li>Ausgabeformate: M4B, MP3, FLAC</li> <li>Template-basierte Pfade (<code>{author}</code>, <code>{title}</code>, <code>{year}</code>, <code>{narrator}</code>, <code>{series}</code>, <code>{part}</code>)</li> </ul>"},{"location":"architecture/backend/#activationbytesservicejs","title":"<code>activationBytesService.js</code>","text":"<p>Verwaltung von Audible-Activation-Bytes f\u00fcr AAX-DRM-Handling.</p> <p>Features:</p> <ul> <li>SHA-1-Pr\u00fcfsumme der AAX-Datei berechnen</li> <li>Activation Bytes in <code>aax_activation_bytes</code>-Tabelle cachen</li> <li>Lookup via <code>audnexService</code> (wenn konfiguriert)</li> </ul>"},{"location":"architecture/backend/#converterscanservicejs","title":"<code>converterScanService.js</code>","text":"<p>Dateisystem-\u00dcberwachung des Converter-Eingangsordners.</p> <p>Features:</p> <ul> <li>Vollst\u00e4ndiger FS-Baum (<code>getTree()</code>)</li> <li>DB-basierter Datei-Explorer (<code>getEntries()</code>)</li> <li>Manueller und automatischer Scan (Polling)</li> <li>Pfad-Normalisierung mit Traversal-Schutz</li> <li>WebSocket-Broadcast: <code>CONVERTER_SCAN_UPDATE</code></li> </ul>"},{"location":"architecture/backend/#downloadservicejs","title":"<code>downloadService.js</code>","text":"<p>Download-Queue f\u00fcr Ausgabedateien aus der Historie.</p> <p>Features:</p> <ul> <li>Job in Download-Queue einreihen (<code>enqueueHistoryJob</code>)</li> <li>ZIP-Archiv aus Ausgabedateien erstellen (<code>archiver</code>)</li> <li>Datei-Streaming via <code>res.download()</code></li> <li>WebSocket-Broadcast: <code>DOWNLOADS_UPDATED</code> bei Status-\u00c4nderungen</li> <li>Download-Item l\u00f6schen</li> </ul>"},{"location":"architecture/backend/#cronservicejs","title":"<code>cronService.js</code>","text":"<p>Integriertes Cron-System ohne externe Parser-Library.</p> <p>Features:</p> <ul> <li>5-Feld-Cron-Parser + <code>nextRun</code>-Berechnung</li> <li>Quellen: <code>script</code> oder <code>chain</code></li> <li>Laufzeitlogs (<code>cron_run_logs</code>)</li> <li>manuelles Triggern</li> <li>WebSocket-Events: <code>CRON_JOBS_UPDATED</code>, <code>CRON_JOB_UPDATED</code></li> </ul>"},{"location":"architecture/backend/#runtimeactivityservicejs","title":"<code>runtimeActivityService.js</code>","text":"<p>In-Memory-Tracking aller laufenden und k\u00fcrzlich abgeschlossenen Aktivit\u00e4ten (Skripte, Ketten, Cron-Jobs, Tasks).</p> <p>Features:</p> <ul> <li><code>startActivity(type, payload)</code> \u2192 Aktivit\u00e4t registrieren, ID zur\u00fcckgeben</li> <li><code>updateActivity(id, patch)</code> \u2192 Laufende Aktivit\u00e4t aktualisieren</li> <li><code>completeActivity(id, payload)</code> \u2192 Aktivit\u00e4t abschlie\u00dfen und in <code>recent</code> verschieben</li> <li><code>setControls(id, { cancel, nextStep })</code> \u2192 Steuer-Handler registrieren (f\u00fcr <code>canCancel</code>/<code>canNextStep</code>)</li> <li><code>requestCancel(id)</code> / <code>requestNextStep(id)</code> \u2192 Steuer-Handler aufrufen</li> <li><code>clearRecent()</code> \u2192 Abgeschlossene Aktivit\u00e4ten l\u00f6schen</li> <li><code>getSnapshot()</code> \u2192 Snapshot mit <code>active</code> + <code>recent</code> + <code>updatedAt</code></li> <li>Broadcasts <code>RUNTIME_ACTIVITY_CHANGED</code> \u00fcber WebSocket bei jeder \u00c4nderung</li> </ul> <p>Limits:</p> <ul> <li><code>recent</code> max. 120 Eintr\u00e4ge</li> <li><code>stdout</code>/<code>stderr</code>/<code>output</code> max. 12.000 Zeichen</li> <li><code>message</code>/<code>errorMessage</code> max. 2.000 Zeichen</li> </ul> <p>Vollst\u00e4ndige API-Dokumentation: Runtime Activities API</p>"},{"location":"architecture/backend/#weitere-services","title":"Weitere Services","text":"<ul> <li><code>scriptService.js</code> (CRUD + Test + Wrapper-Ausf\u00fchrung)</li> <li><code>scriptChainService.js</code> (CRUD + Step-Execution)</li> <li><code>userPresetService.js</code> (HandBrake User-Presets)</li> <li><code>hardwareMonitorService.js</code> (CPU/RAM/GPU/Storage)</li> <li><code>websocketService.js</code> (Client-Registry + Broadcast)</li> <li><code>notificationService.js</code> (PushOver)</li> <li><code>cdRipService.js</code> (CD-Ripping mit cdparanoia)</li> <li><code>musicBrainzService.js</code> (MusicBrainz-Metadaten-Lookup)</li> <li><code>audnexService.js</code> (Audnex-API f\u00fcr Audiobook-Metadaten)</li> <li><code>coverArtRecoveryService.js</code> (Cover-Art-Wiederherstellung)</li> <li><code>thumbnailService.js</code> (Vorschaubild-Generierung)</li> <li><code>tmdbService.js</code> (Film-/Serien-Metadaten-Suche)</li> <li><code>logger.js</code> (rotierende Datei-Logs)</li> </ul>"},{"location":"architecture/backend/#bootstrapping-srcindexjs","title":"Bootstrapping (<code>src/index.js</code>)","text":"<p>Beim Start:</p> <ol> <li>DB init/migrate</li> <li>Pipeline-Init (inkl. Plugin-Registry)</li> <li>Cron-Init</li> <li>Express-Routes + Error-Handler</li> <li>WebSocket-Server auf <code>/ws</code></li> <li>Hardware-Monitoring-Init</li> <li>Disk-Detection-Start</li> <li>Converter-Scan-Service-Init (Polling falls aktiviert)</li> </ol>"},{"location":"architecture/database/","title":"Datenbank","text":"<p>Ripster verwendet SQLite (<code>backend/data/ripster.db</code>).</p>"},{"location":"architecture/database/#tabellen","title":"Tabellen","text":"<pre><code>settings_schema\nsettings_values\njobs\njob_lineage_artifacts\njob_output_folders\npipeline_state\nscripts\nscript_chains\nscript_chain_steps\nuser_presets\ncron_jobs\ncron_run_logs\naax_activation_bytes\nuser_prefs\nconverter_scan_entries\n</code></pre>"},{"location":"architecture/database/#jobs","title":"<code>jobs</code>","text":"<p>Speichert Pipeline-Lifecycle und Artefakte pro Job.</p> <p>Zentrale Felder:</p> <ul> <li>Metadaten: <code>title</code>, <code>year</code>, <code>imdb_id</code>, <code>poster_url</code>, <code>omdb_json</code>, <code>selected_from_omdb</code></li> <li>Laufzeit: <code>start_time</code>, <code>end_time</code>, <code>status</code>, <code>last_state</code></li> <li>Pfade: <code>raw_path</code>, <code>output_path</code>, <code>encode_input_path</code></li> <li>Tool-Ausgaben: <code>makemkv_info_json</code>, <code>handbrake_info_json</code>, <code>mediainfo_info_json</code>, <code>encode_plan_json</code></li> <li>Kontrolle: <code>encode_review_confirmed</code>, <code>rip_successful</code>, <code>error_message</code></li> <li>Medientyp: <code>media_type</code> (<code>bluray|dvd|cd|audiobook|converter</code>)</li> <li>Job-Typ/Beziehung: <code>job_kind</code>, <code>parent_job_id</code></li> <li>Multipart-/Disc-Merkmale: <code>is_multipart_movie</code>, <code>disc_number</code>, <code>metadata_fingerprint</code></li> <li>Pr\u00fcfsumme: <code>aax_checksum</code> (f\u00fcr AAX-Dateien)</li> <li>Audit: <code>created_at</code>, <code>updated_at</code></li> </ul> <p>Typische <code>job_kind</code>-Werte:</p> <ul> <li>Standard: <code>bluray</code>, <code>dvd</code>, <code>cd</code>, <code>audiobook</code>, <code>converter_audio</code>, <code>converter_video</code>, <code>converter_iso</code></li> <li>Serien: <code>dvd_series_container</code>, <code>dvd_series_child</code></li> <li>Multipart Film: <code>multipart_movie_container</code>, <code>multipart_movie_child</code></li> </ul> <p>Wichtige Indizes:</p> <ul> <li><code>idx_jobs_status</code></li> <li><code>idx_jobs_parent_job_id</code></li> <li><code>idx_jobs_job_kind</code></li> <li><code>idx_jobs_disc_number</code></li> <li><code>idx_jobs_metadata_fingerprint</code></li> </ul>"},{"location":"architecture/database/#job_lineage_artifacts","title":"<code>job_lineage_artifacts</code>","text":"<p>Verkn\u00fcpft Jobs mit ihren Quell-Jobs (z. B. Re-Encode aus einem vorherigen Rip).</p> <p>Felder:</p> <ul> <li><code>job_id</code> \u2014 der abgeleitete Job</li> <li><code>source_job_id</code> \u2014 der Quell-Job</li> <li><code>artifact_type</code> \u2014 Art der Verkn\u00fcpfung (z. B. <code>reencode</code>, <code>restart_review</code>)</li> <li><code>created_at</code></li> </ul>"},{"location":"architecture/database/#job_output_folders","title":"<code>job_output_folders</code>","text":"<p>Verfolgt Ausgabepfade pro Job (mehrere Ausgaben m\u00f6glich, z. B. bei Kapitel-Splitting).</p> <p>Felder:</p> <ul> <li><code>job_id</code></li> <li><code>folder_path</code></li> <li><code>label</code> \u2014 optionaler Bezeichner</li> <li><code>created_at</code></li> </ul>"},{"location":"architecture/database/#pipeline_state","title":"<code>pipeline_state</code>","text":"<p>Singleton-Tabelle (<code>id = 1</code>) f\u00fcr aktiven Snapshot:</p> <ul> <li><code>state</code></li> <li><code>active_job_id</code></li> <li><code>progress</code></li> <li><code>eta</code></li> <li><code>status_text</code></li> <li><code>context_json</code></li> <li><code>updated_at</code></li> </ul>"},{"location":"architecture/database/#settings_schema-settings_values","title":"<code>settings_schema</code> + <code>settings_values</code>","text":"<ul> <li><code>settings_schema</code>: Definition (Typ, Default, Validation, Reihenfolge)</li> <li><code>settings_values</code>: aktueller Wert pro Key</li> </ul>"},{"location":"architecture/database/#scripts-script_chains-script_chain_steps","title":"<code>scripts</code>, <code>script_chains</code>, <code>script_chain_steps</code>","text":"<ul> <li><code>scripts</code>: Shell-Skripte (<code>name</code>, <code>script_body</code>, <code>order_index</code>)</li> <li><code>script_chains</code>: Ketten (<code>name</code>, <code>order_index</code>)</li> <li><code>script_chain_steps</code>: Schritte je Kette</li> <li><code>step_type</code>: <code>script</code> oder <code>wait</code></li> <li><code>script_id</code> oder <code>wait_seconds</code></li> </ul>"},{"location":"architecture/database/#user_presets","title":"<code>user_presets</code>","text":"<p>Benannte HandBrake-Preset-Sets:</p> <ul> <li><code>name</code></li> <li><code>media_type</code> (<code>bluray|dvd|other|all</code>)</li> <li><code>handbrake_preset</code></li> <li><code>extra_args</code></li> <li><code>description</code></li> </ul>"},{"location":"architecture/database/#cron_jobs-cron_run_logs","title":"<code>cron_jobs</code> + <code>cron_run_logs</code>","text":"<ul> <li><code>cron_jobs</code>: Zeitplan + Status</li> <li><code>cron_run_logs</code>: einzelne L\u00e4ufe</li> <li><code>status</code>: <code>running|success|error</code></li> <li><code>output</code></li> <li><code>error_message</code></li> </ul>"},{"location":"architecture/database/#aax_activation_bytes","title":"<code>aax_activation_bytes</code>","text":"<p>Cache f\u00fcr Audible-Activation-Bytes (AAX-DRM).</p> <p>Felder:</p> <ul> <li><code>checksum</code> \u2014 SHA-1-Pr\u00fcfsumme der AAX-Datei (Prim\u00e4rschl\u00fcssel)</li> <li><code>activation_bytes</code> \u2014 Hex-String der Activation Bytes</li> <li><code>created_at</code></li> </ul>"},{"location":"architecture/database/#user_prefs","title":"<code>user_prefs</code>","text":"<p>Benutzer-spezifische Einstellungen (Key-Value).</p> <p>Felder:</p> <ul> <li><code>key</code></li> <li><code>value</code></li> <li><code>updated_at</code></li> </ul>"},{"location":"architecture/database/#converter_scan_entries","title":"<code>converter_scan_entries</code>","text":"<p>DB-seitige Erfassung gescannter Dateien im Converter-Eingangsordner.</p> <p>Felder:</p> <ul> <li><code>rel_path</code> \u2014 relativer Pfad zum <code>converter_raw_dir</code></li> <li><code>is_dir</code> \u2014 Verzeichnis-Flag</li> <li><code>size</code> \u2014 Dateigr\u00f6\u00dfe in Bytes</li> <li><code>modified_at</code> \u2014 Datei-\u00c4nderungsdatum</li> <li><code>job_id</code> \u2014 zugewiesener Converter-Job (falls vorhanden)</li> <li><code>scanned_at</code></li> </ul>"},{"location":"architecture/database/#migrationrecovery","title":"Migration/Recovery","text":"<p>Beim Start werden Schema und Settings-Metadaten automatisch abgeglichen.</p> <p>Bei korruptem SQLite-File:</p> <ol> <li>Datei wird nach <code>backend/data/corrupt-backups/</code> verschoben</li> <li>neue DB wird initialisiert</li> <li>Schema wird neu aufgebaut</li> </ol>"},{"location":"architecture/database/#direkte-inspektion","title":"Direkte Inspektion","text":"<pre><code>sqlite3 backend/data/ripster.db\n\n.mode table\nSELECT id, status, title, media_type, created_at FROM jobs ORDER BY created_at DESC;\nSELECT id, parent_job_id, job_kind, is_multipart_movie, disc_number FROM jobs ORDER BY created_at DESC;\nSELECT key, value FROM settings_values ORDER BY key;\nSELECT checksum, activation_bytes FROM aax_activation_bytes;\nSELECT rel_path, job_id FROM converter_scan_entries;\n</code></pre>"},{"location":"architecture/frontend/","title":"Frontend-Komponenten","text":"<p>Frontend: React + PrimeReact + Vite.</p>"},{"location":"architecture/frontend/#hauptseiten","title":"Hauptseiten","text":""},{"location":"architecture/frontend/#ripperpagejsx","title":"<code>RipperPage.jsx</code>","text":"<p>Pipeline-Steuerung:</p> <ul> <li>Status/Progress/ETA</li> <li>Metadaten-Dialog</li> <li>Playlist-Entscheidung</li> <li>Review-Panel (Track-Auswahl)</li> <li>Queue-Interaktion (reorder/add/remove)</li> <li>Job-Aktionen (Start/Cancel/Retry/Re-Encode)</li> <li>Hardware-Monitoring-Anzeige</li> <li>Aktivit\u00e4ts-Tracking (Skripte, Ketten, Cron)</li> </ul>"},{"location":"architecture/frontend/#settingspagejsx","title":"<code>SettingsPage.jsx</code>","text":"<p>Konfiguration:</p> <ul> <li>dynamisches Settings-Formular (<code>DynamicSettingsForm</code>)</li> <li>Skripte/Ketten inkl. Reorder/Test</li> <li>User-Presets</li> <li>Cron-Jobs (<code>CronJobsTab</code>)</li> </ul>"},{"location":"architecture/frontend/#historypagejsx","title":"<code>HistoryPage.jsx</code>","text":"<p>Historie:</p> <ul> <li>Job-Liste/Filter</li> <li>Job-Details + Logs</li> <li>TMDb-Neuzuordnung</li> <li>Re-Encode/Restart-Workflows</li> </ul>"},{"location":"architecture/frontend/#converterpagejsx","title":"<code>ConverterPage.jsx</code>","text":"<p>Datei-Converter:</p> <ul> <li>Datei-Explorer des Converter-Eingangsordners (Baum-Ansicht)</li> <li>Upload von Audio/Video-Dateien (bis zu 50 Dateien gleichzeitig)</li> <li>Dateiverwaltung: Umbenennen, Verschieben, L\u00f6schen, Ordner erstellen</li> <li>Jobs aus Dateiauswahl erstellen</li> <li>Converter-Job-Konfiguration (Ausgabeformat, Preset, Tracks)</li> <li>Job-Start, Abbruch, L\u00f6schung</li> <li>Automatischer Scan-Status</li> </ul>"},{"location":"architecture/frontend/#audiobookspagejsx","title":"<code>AudiobooksPage.jsx</code>","text":"<p>Dedizierter AAX-/Audiobook-Flow:</p> <ul> <li>Upload-Panel f\u00fcr AAX-Dateien</li> <li>aktive Audiobook-Jobkarten mit Start/Cancel/Retry/Delete</li> <li>Audiobook-Konfigurationspanel und Output-Explorer</li> </ul>"},{"location":"architecture/frontend/#downloadspagejsx","title":"<code>DownloadsPage.jsx</code>","text":"<p>Download-Queue:</p> <ul> <li>Ausgabedateien aus der Job-Historie in die Queue einreihen</li> <li>Download-Status verfolgen (ausstehend, wird verarbeitet, bereit, fehlgeschlagen)</li> <li>Dateien als ZIP herunterladen</li> <li>Download-Eintr\u00e4ge l\u00f6schen</li> </ul>"},{"location":"architecture/frontend/#databasepagejsx","title":"<code>DatabasePage.jsx</code>","text":"<p>Expert-Modus:</p> <ul> <li>Tabellarische Rohsicht der Job-Datenbank</li> <li>Orphan-RAW-Import</li> </ul>"},{"location":"architecture/frontend/#wichtige-komponenten","title":"Wichtige Komponenten","text":"<ul> <li><code>PipelineStatusCard.jsx</code> \u2014 Pipeline-Status-Anzeige mit Progress</li> <li><code>MetadataSelectionDialog.jsx</code> \u2014 TMDb-Metadaten-Auswahl</li> <li><code>MediaInfoReviewPanel.jsx</code> \u2014 Track-Auswahl-Interface (Video/Audio/Untertitel)</li> <li><code>JobDetailDialog.jsx</code> \u2014 Job-Detailansicht mit Logs</li> <li><code>CronJobsTab.jsx</code> \u2014 Cron-Job-Verwaltung</li> <li><code>DynamicSettingsForm.jsx</code> \u2014 Schema-gesteuertes Einstellungsformular</li> <li><code>ConverterJobCard.jsx</code> \u2014 Converter-Job-Darstellung</li> <li><code>CdRipConfigPanel.jsx</code> \u2014 Konfiguration f\u00fcr Audio-CD-Ripping</li> </ul>"},{"location":"architecture/frontend/#api-client-apiclientjs","title":"API-Client (<code>api/client.js</code>)","text":"<ul> <li>zentraler <code>request()</code> mit JSON-Handling</li> <li>Fehlerobjekt aus API wird auf <code>Error(message)</code> gemappt</li> <li><code>VITE_API_BASE</code> default <code>/api</code></li> </ul>"},{"location":"architecture/frontend/#websocket-hooksusewebsocketjs","title":"WebSocket (<code>hooks/useWebSocket.js</code>)","text":"<ul> <li>URL: <code>VITE_WS_URL</code> oder automatisch <code>ws(s)://&lt;host&gt;/ws</code></li> <li>Auto-Reconnect mit 1500ms Intervall</li> </ul> <p>In <code>App.jsx</code> werden u. a. verarbeitet:</p> <ul> <li><code>PIPELINE_STATE_CHANGED</code></li> <li><code>PIPELINE_PROGRESS</code></li> <li><code>PIPELINE_QUEUE_CHANGED</code></li> <li>Disk erkannt / Disk entfernt</li> <li><code>HARDWARE_MONITOR_UPDATE</code></li> <li><code>DOWNLOADS_UPDATED</code></li> <li><code>CONVERTER_SCAN_UPDATE</code></li> <li><code>RUNTIME_ACTIVITY_CHANGED</code></li> </ul>"},{"location":"architecture/frontend/#buildrun","title":"Build/Run","text":"<pre><code># dev\nnpm run dev --prefix frontend\n\n# prod build\nnpm run build --prefix frontend\n</code></pre>"},{"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":"<p><code>pipelineService</code> h\u00e4lt einen Snapshot der State-Machine und broadcastet \u00c4nderungen sofort via WebSocket.</p> <pre><code>State-\u00c4nderung -&gt; PIPELINE_STATE_CHANGED/PIPELINE_PROGRESS -&gt; Frontend-Update\n</code></pre>"},{"location":"architecture/overview/#service-layer","title":"Service-Layer","text":"<pre><code>Route -&gt; Service -&gt; DB/Tool-Execution\n</code></pre> <p>Routes enthalten kaum Business-Logik.</p>"},{"location":"architecture/overview/#schema-getriebene-settings","title":"Schema-getriebene Settings","text":"<p>Settings sind DB-schema-getrieben (<code>settings_schema</code> + <code>settings_values</code>), UI rendert dynamisch aus diesen Daten.</p>"},{"location":"architecture/overview/#echtzeit-kommunikation","title":"Echtzeit-Kommunikation","text":"<p>WebSocket l\u00e4uft auf <code>/ws</code>.</p> <p>Wichtige Events:</p> <ul> <li><code>PIPELINE_STATE_CHANGED</code>, <code>PIPELINE_PROGRESS</code>, <code>PIPELINE_QUEUE_CHANGED</code></li> <li>Disk erkannt, Disk entfernt</li> <li><code>HARDWARE_MONITOR_UPDATE</code></li> <li><code>SETTINGS_UPDATED</code>, <code>SETTINGS_BULK_UPDATED</code></li> <li><code>SETTINGS_SCRIPTS_UPDATED</code>, <code>SETTINGS_SCRIPT_CHAINS_UPDATED</code>, <code>USER_PRESETS_UPDATED</code></li> <li><code>CRON_JOBS_UPDATED</code>, <code>CRON_JOB_UPDATED</code></li> <li><code>PIPELINE_ERROR</code>, <code>DISK_DETECTION_ERROR</code></li> </ul>"},{"location":"architecture/overview/#prozessausfuhrung","title":"Prozessausf\u00fchrung","text":"<p>Externe Tools werden als Child-Processes gestartet (<code>processRunner</code>):</p> <ul> <li>Streaming von stdout/stderr</li> <li>Progress-Parsing (<code>progressParsers.js</code>)</li> <li>kontrollierter Abbruch (SIGINT/SIGKILL-Fallback)</li> </ul>"},{"location":"architecture/overview/#persistenz","title":"Persistenz","text":"<p>SQLite-Datei: <code>backend/data/ripster.db</code></p> <p>Kern-Tabellen:</p> <ul> <li><code>jobs</code>, <code>pipeline_state</code></li> <li><code>settings_schema</code>, <code>settings_values</code></li> <li><code>scripts</code>, <code>script_chains</code>, <code>script_chain_steps</code></li> <li><code>user_presets</code></li> <li><code>cron_jobs</code>, <code>cron_run_logs</code></li> </ul> <p>Beim Start werden Schema und Settings-Migrationen automatisch ausgef\u00fchrt.</p>"},{"location":"architecture/overview/#fehlerbehandlung","title":"Fehlerbehandlung","text":"<p>Zentrales Error-Handling liefert:</p> <pre><code>{\n \"error\": {\n \"message\": \"...\",\n \"statusCode\": 400,\n \"reqId\": \"...\",\n \"details\": []\n }\n}\n</code></pre> <p>Fehlgeschlagene Jobs bleiben in der Historie (<code>Fehler</code> oder <code>Abgebrochen</code>) und k\u00f6nnen erneut gestartet werden.</p>"},{"location":"architecture/overview/#cors-runtime-konfig","title":"CORS &amp; Runtime-Konfig","text":"<ul> <li><code>CORS_ORIGIN</code> default: <code>*</code></li> <li><code>LOG_LEVEL</code> default: <code>info</code></li> <li>DB-/Log-Pfade \u00fcber <code>DB_PATH</code>/<code>LOG_DIR</code> konfigurierbar</li> </ul>"},{"location":"configuration/","title":"Anhang: Konfiguration","text":"<p>Dieser Abschnitt ist die technische Referenz zu allen Konfigurationsarten in Ripster.</p>"},{"location":"configuration/#inhalte","title":"Inhalte","text":"<ul> <li> <p> Einstellungsreferenz</p> <p>Vollst\u00e4ndige Liste aller UI-Settings (Typ, Default, Hinweise).</p> <p> Einstellungsreferenz</p> </li> <li> <p> Umgebungsvariablen</p> <p><code>backend/.env</code> und <code>frontend/.env</code> inkl. Priorit\u00e4ten.</p> <p> Umgebungsvariablen</p> </li> </ul>"},{"location":"configuration/#zuruck-zum-handbuch","title":"Zur\u00fcck zum Handbuch","text":"<ul> <li>Benutzerhandbuch \u00dcberblick</li> </ul>"},{"location":"configuration/environment/","title":"Umgebungsvariablen","text":"<p>Umgebungsvariablen steuern Backend/Vite au\u00dferhalb der DB-basierten UI-Settings.</p>"},{"location":"configuration/environment/#backend-backendenv","title":"Backend (<code>backend/.env</code>)","text":"Variable Default (Code) Beschreibung <code>PORT</code> <code>3001</code> Express-Port <code>DB_PATH</code> <code>backend/data/ripster.db</code> SQLite-Datei (relativ zu <code>backend/</code>) <code>LOG_DIR</code> <code>backend/logs</code> Fallback-Logverzeichnis (wenn <code>log_dir</code>-Setting nicht gesetzt/lesbar) <code>CORS_ORIGIN</code> <code>*</code> CORS-Origin f\u00fcr API <code>LOG_LEVEL</code> <code>info</code> <code>debug</code>, <code>info</code>, <code>warn</code>, <code>error</code> <p>Beispiel:</p> <pre><code>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</code></pre> <p>Hinweis: <code>backend/.env.example</code> enth\u00e4lt bewusst dev-freundliche Werte (z. B. lokaler <code>CORS_ORIGIN</code>).</p>"},{"location":"configuration/environment/#frontend-frontendenv","title":"Frontend (<code>frontend/.env</code>)","text":"Variable Default Beschreibung <code>VITE_API_BASE</code> <code>/api</code> API-Basis f\u00fcr Fetch-Client <code>VITE_WS_URL</code> automatisch aus <code>window.location</code> + <code>/ws</code> Optional explizite WebSocket-URL <code>VITE_PUBLIC_ORIGIN</code> leer \u00d6ffentliche Vite-Origin (Remote-Dev) <code>VITE_ALLOWED_HOSTS</code> <code>true</code> Komma-separierte Hostliste f\u00fcr Vite <code>allowedHosts</code> <code>VITE_HMR_PROTOCOL</code> abgeleitet aus <code>VITE_PUBLIC_ORIGIN</code> HMR-Protokoll (<code>ws</code>/<code>wss</code>) <code>VITE_HMR_HOST</code> abgeleitet aus <code>VITE_PUBLIC_ORIGIN</code> HMR-Host <code>VITE_HMR_CLIENT_PORT</code> abgeleitet aus <code>VITE_PUBLIC_ORIGIN</code> HMR-Client-Port <p>Beispiele:</p> <pre><code># lokal (mit Vite-Proxy)\nVITE_API_BASE=/api\n</code></pre> <pre><code># 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</code></pre>"},{"location":"configuration/environment/#prioritat","title":"Priorit\u00e4t","text":"<ol> <li>Prozess-Umgebungsvariablen</li> <li><code>.env</code></li> <li>Code-Defaults</li> </ol>"},{"location":"configuration/settings-reference/","title":"Einstellungsreferenz","text":"<p>Diese Seite beschreibt jede aktuelle Einstellung aus der Settings-GUI: was technisch passiert und warum man sie setzt.</p>"},{"location":"configuration/settings-reference/#lesehilfe","title":"Lesehilfe","text":"<ul> <li><code>Sichtbarkeit</code>: <code>Standard</code>, <code>Expertenmodus</code> oder <code>Ausgeblendet (nur API/DB)</code>.</li> <li><code>Default</code>: UI-/Schema-Default (sensible Werte werden als <code>leer</code> dargestellt).</li> <li><code>Was passiert technisch?</code>: direkte Wirkung im Backend/Pipeline-Verhalten.</li> <li><code>Warum/Wann setzen?</code>: Praxisgrund inkl. typischem Einsatzzweck.</li> </ul>"},{"location":"configuration/settings-reference/#wie-diese-seite-zu-lesen-ist","title":"Wie diese Seite zu lesen ist","text":"<p>Wenn du nicht von oben bis unten lesen willst, helfen diese typischen Einstiegsfragen:</p> <ul> <li>Disc wird nicht sauber erkannt: zuerst <code>Laufwerk</code></li> <li>falsche Playlist- oder Titelauswahl: zuerst <code>Tools</code></li> <li>Ausgabe landet im falschen Ordner: zuerst <code>Pfade</code></li> <li>zu viele oder zu wenige parallele Jobs: zuerst <code>Tools</code></li> <li>Converter scannt nicht wie erwartet: zuerst <code>Converter</code></li> <li>Hardware oder Speicher fehlen im Monitoring: zuerst <code>Monitoring</code> und <code>Pfade</code></li> </ul>"},{"location":"configuration/settings-reference/#vollstandige-feldliste","title":"Vollst\u00e4ndige Feldliste","text":""},{"location":"configuration/settings-reference/#kategorie-benachrichtigungen","title":"Kategorie: Benachrichtigungen","text":"GUI-Feld Key Typ Default Sichtbarkeit Was passiert technisch? Warum/Wann setzen? <code>Expertenmodus</code> <code>ui_expert_mode</code> <code>boolean</code> <code>false</code> Standard Schaltet erweiterte Einstellungen in der UI ein. Wird sofort einzeln gespeichert und beeinflusst Sichtbarkeit von Feldern/Kategorien. Wenn du selten benoetigte technische Felder sehen willst (z.B. Logging- oder CLI-Details). <code>PushOver aktiviert</code> <code>pushover_enabled</code> <code>boolean</code> <code>false</code> Standard Master-Schalter f\u00fcr PushOver Versand. Wenn du aktive Laufzeit-Benachrichtigungen auf Mobilgeraete erhalten willst. <code>PushOver Token</code> <code>pushover_token</code> <code>string</code> <code>leer</code> Standard Application Token f\u00fcr PushOver. Wenn Ripster in deine PushOver-App senden soll (Token aus PushOver-App-Config). <code>PushOver User</code> <code>pushover_user</code> <code>string</code> <code>leer</code> Standard User-Key f\u00fcr PushOver. Wenn Benachrichtigungen an einen bestimmten PushOver-Account gehen sollen. <code>PushOver Device (optional)</code> <code>pushover_device</code> <code>string</code> <code>leer</code> Expertenmodus Optionales Ziel-Device in PushOver. Wenn Nachrichten nur auf ein bestimmtes Endgeraet zugestellt werden sollen. <code>PushOver Titel-Pr\u00e4fix</code> <code>pushover_title_prefix</code> <code>string</code> <code>Ripster</code> Standard Prefix im PushOver Titel. Wenn du Meldungen mehrerer Instanzen sauber unterscheiden willst (z.B. \"Ripper-Wohnzimmer\"). <code>PushOver Priority</code> <code>pushover_priority</code> <code>number</code> <code>0</code> Expertenmodus Priorit\u00e4t -2 bis 2. Wenn Meldungen bewusst leiser (niedrig) oder dringender (hoch) zugestellt werden sollen. <code>PushOver Timeout (ms)</code> <code>pushover_timeout_ms</code> <code>number</code> <code>7000</code> Expertenmodus HTTP Timeout f\u00fcr PushOver Requests. Wenn PushOver bei schlechter Verbindung mehr oder weniger Zeit fuer den Request bekommen soll. <code>Bei manueller Auswahl senden</code> <code>pushover_notify_metadata_ready</code> <code>boolean</code> <code>true</code> Standard Sendet, wenn ein Job eine manuelle Auswahl/Entscheidung ben\u00f6tigt (z.B. Metadaten, Titel oder Playlist). Wenn 'Bei manueller Auswahl senden' bewusst ein- oder ausgeschaltet werden soll, um den Ablauf an deine Umgebung anzupassen. <code>Bei Rip-Start senden</code> <code>pushover_notify_rip_started</code> <code>boolean</code> <code>true</code> Standard Sendet beim Start des MakeMKV-Rips. Wenn 'Bei Rip-Start senden' bewusst ein- oder ausgeschaltet werden soll, um den Ablauf an deine Umgebung anzupassen. <code>Bei Encode-Start senden</code> <code>pushover_notify_encoding_started</code> <code>boolean</code> <code>true</code> Standard Sendet beim Start von HandBrake. Wenn 'Bei Encode-Start senden' bewusst ein- oder ausgeschaltet werden soll, um den Ablauf an deine Umgebung anzupassen. <code>Bei Erfolg senden</code> <code>pushover_notify_job_finished</code> <code>boolean</code> <code>true</code> Standard Sendet bei erfolgreich abgeschlossenem Job. Wenn 'Bei Erfolg senden' bewusst ein- oder ausgeschaltet werden soll, um den Ablauf an deine Umgebung anzupassen. <code>Bei Fehler senden</code> <code>pushover_notify_job_error</code> <code>boolean</code> <code>true</code> Standard Sendet bei Fehlern in der Pipeline. Wenn 'Bei Fehler senden' bewusst ein- oder ausgeschaltet werden soll, um den Ablauf an deine Umgebung anzupassen. <code>Bei Abbruch senden</code> <code>pushover_notify_job_cancelled</code> <code>boolean</code> <code>true</code> Standard Sendet wenn Job manuell abgebrochen wurde. Wenn 'Bei Abbruch senden' bewusst ein- oder ausgeschaltet werden soll, um den Ablauf an deine Umgebung anzupassen. <code>Bei Re-Encode Start senden</code> <code>pushover_notify_reencode_started</code> <code>boolean</code> <code>true</code> Standard Sendet beim Start von RAW Re-Encode. Wenn 'Bei Re-Encode Start senden' bewusst ein- oder ausgeschaltet werden soll, um den Ablauf an deine Umgebung anzupassen. <code>Bei Re-Encode Erfolg senden</code> <code>pushover_notify_reencode_finished</code> <code>boolean</code> <code>true</code> Standard Sendet bei erfolgreichem RAW Re-Encode. Wenn 'Bei Re-Encode Erfolg senden' bewusst ein- oder ausgeschaltet werden soll, um den Ablauf an deine Umgebung anzupassen."},{"location":"configuration/settings-reference/#kategorie-converter","title":"Kategorie: Converter","text":"GUI-Feld Key Typ Default Sichtbarkeit Was passiert technisch? Warum/Wann setzen? <code>Erlaubte Datei-Endungen</code> <code>converter_scan_extensions</code> <code>string</code> <code>mkv,mp4,m2ts,iso,avi,mov,flac,mp3,aac,wav,m4a,ogg,opus</code> Standard Komma-getrennte Liste erlaubter Dateiendungen f\u00fcr den Scan (ohne Punkt). Steuert sowohl Upload-Validierung als auch Converter-Scan-Filter. Wenn 'Erlaubte Datei-Endungen' vom Default abweichen soll. <code>Auto-Scan (Polling)</code> <code>converter_polling_enabled</code> <code>boolean</code> <code>false</code> Standard Converter Raw-Ordner automatisch in regelm\u00e4\u00dfigen Abst\u00e4nden scannen. Wenn neue Dateien im Converter-Ordner automatisch erscheinen sollen, ohne manuellen Scan. <code>Polling-Intervall (Sekunden)</code> <code>converter_polling_interval</code> <code>number</code> <code>300</code> Standard Intervall f\u00fcr automatischen Scan des Converter-Ordners. Wenn der Auto-Scan schneller (kleiner Wert) oder ressourcenschonender (groesserer Wert) laufen soll."},{"location":"configuration/settings-reference/#kategorie-laufwerk","title":"Kategorie: Laufwerk","text":"GUI-Feld Key Typ Default Sichtbarkeit Was passiert technisch? Warum/Wann setzen? <code>Laufwerksmodus</code> <code>drive_mode</code> <code>select</code> <code>auto</code> Standard Auto-Discovery oder explizites Device. Wenn du zwischen automatischer Laufwerkserkennung und fixer Device-Liste umschalten willst. <code>Explizite Laufwerke</code> <code>drive_devices</code> <code>path</code> <code>[]</code> Standard Laufwerke f\u00fcr den expliziten Modus als JSON-Array mit Pfad und MakeMKV-Index, z.B. [{\"path\":\"/dev/sr0\",\"makemkvIndex\":0},{\"path\":\"/dev/sr1\",\"makemkvIndex\":1}]. Nur relevant wenn Modus = Explizites Device. Wird als JSON gespeichert und vom Laufwerksdienst fuer explizite Zuordnung genutzt. Wenn auf dem Host mehrere Laufwerke stabil gemappt werden muessen (z.B. /dev/sr0=disc:0, /dev/sr1=disc:1). <code>Device Pfad</code> <code>drive_device</code> <code>path</code> <code>/dev/sr0</code> Ausgeblendet (nur API/DB) Nur f\u00fcr expliziten Modus, z.B. /dev/sr0. Wenn 'Device Pfad' vom Default abweichen soll. <code>MakeMKV Source Index</code> <code>makemkv_source_index</code> <code>number</code> <code>0</code> Ausgeblendet (nur API/DB) Disc Index im Auto-Modus. Wenn 'MakeMKV Source Index' fuer Performance, Last oder Genauigkeit feinjustiert werden soll. <code>Automatische Disk-Erkennung</code> <code>disc_auto_detection_enabled</code> <code>boolean</code> <code>true</code> Standard Wenn deaktiviert, findet keine automatische Laufwerkspr\u00fcfung statt. Neue Disks werden nur per \"Laufwerk neu lesen\" erkannt. Wenn Discs nur manuell statt automatisch erkannt werden sollen. <code>Polling Intervall (ms)</code> <code>disc_poll_interval_ms</code> <code>number</code> <code>4000</code> Expertenmodus Intervall f\u00fcr Disk-Erkennung. Wenn die Erkennung schneller reagieren oder weniger oft pollen soll. <code>Laufwerk nach Rip auswerfen</code> <code>auto_eject_after_rip</code> <code>boolean</code> <code>false</code> Standard Wenn aktiv, wird das Laufwerk nach erfolgreichem Abschluss eines Rip-Vorgangs automatisch ausgeworfen (eject). Wenn ein Laufwerk nach erfolgreichem Rip direkt freigegeben/ausgeworfen werden soll."},{"location":"configuration/settings-reference/#kategorie-logging","title":"Kategorie: Logging","text":"GUI-Feld Key Typ Default Sichtbarkeit Was passiert technisch? Warum/Wann setzen? <code>Terminal-Ausgabe aktiv</code> <code>server_console_log_output_enabled</code> <code>boolean</code> <code>true</code> Expertenmodus Master-Schalter f\u00fcr die Ausgabe der Server-Logs im Terminal (z.B. start.sh). Das Schreiben in Log-Dateien bleibt immer aktiv. Aenderung wirkt direkt auf die Terminal-Logausgabe, Dateilogging bleibt erhalten. Wenn Terminal-Logs bei Betrieb unter Service/SSH ein- oder ausgeschaltet werden sollen. <code>HTTP-Logs im Terminal</code> <code>server_console_log_http_enabled</code> <code>boolean</code> <code>true</code> Expertenmodus Steuert HTTP Request-Logs im Terminal (z.B. request:start). Dateilogs bleiben unver\u00e4ndert. Aenderung wirkt direkt auf die Terminal-Logausgabe, Dateilogging bleibt erhalten. Wenn HTTP-Request-Logs im Terminal fuer API-Debugging gebraucht werden. <code>DEBUG im Terminal</code> <code>server_console_log_debug_enabled</code> <code>boolean</code> <code>true</code> Expertenmodus Steuert DEBUG-Meldungen in der Terminal-Ausgabe. Dateilogs bleiben unver\u00e4ndert. Aenderung wirkt direkt auf die Terminal-Logausgabe, Dateilogging bleibt erhalten. Wenn detailreiche DEBUG-Logs im Terminal benoetigt werden (Fehlersuche). <code>INFO im Terminal</code> <code>server_console_log_info_enabled</code> <code>boolean</code> <code>true</code> Expertenmodus Steuert INFO-Meldungen in der Terminal-Ausgabe. Dateilogs bleiben unver\u00e4ndert. Aenderung wirkt direkt auf die Terminal-Logausgabe, Dateilogging bleibt erhalten. Wenn normale INFO-Laufzeitmeldungen im Terminal sichtbar sein sollen. <code>WARN im Terminal</code> <code>server_console_log_warn_enabled</code> <code>boolean</code> <code>true</code> Expertenmodus Steuert WARN-Meldungen in der Terminal-Ausgabe. Dateilogs bleiben unver\u00e4ndert. Aenderung wirkt direkt auf die Terminal-Logausgabe, Dateilogging bleibt erhalten. Wenn Warnungen im Terminal hervorgehoben bleiben sollen. <code>ERROR im Terminal</code> <code>server_console_log_error_enabled</code> <code>boolean</code> <code>true</code> Expertenmodus Steuert ERROR-Meldungen in der Terminal-Ausgabe. Dateilogs bleiben unver\u00e4ndert. Aenderung wirkt direkt auf die Terminal-Logausgabe, Dateilogging bleibt erhalten. Wenn Fehler zwingend im Terminal sichtbar sein sollen."},{"location":"configuration/settings-reference/#kategorie-metadaten","title":"Kategorie: Metadaten","text":"GUI-Feld Key Typ Default Sichtbarkeit Was passiert technisch? Warum/Wann setzen? <code>TMDb Read Access Token</code> <code>tmdb_api_read_access_token</code> <code>string</code> <code>leer</code> Standard Read Access Token f\u00fcr Serien-Metadaten \u00fcber TheMovieDB (TMDb). Wird von TMDb-Service und Serienzuordnung in Analyse/Metadaten-Dialog genutzt. Wenn TMDb-Metadaten (Suche/Zuordnung/Serienepisoden) verl\u00e4sslich funktionieren sollen. <code>Film-Sprache</code> <code>dvd_series_language</code> <code>string</code> <code>de-DE</code> Standard Bevorzugte TMDb-Sprache f\u00fcr Film- und Serienmetadaten (DVD/Blu-ray), z.B. de-DE oder en-US. Wird von TMDb-Service und Serienzuordnung in Analyse/Metadaten-Dialog genutzt. Wenn bevorzugt deutsche, englische oder andere lokalisierte Metadaten genutzt werden sollen. <code>Fallback Sprache</code> <code>dvd_series_fallback_languages</code> <code>string</code> <code>de-DE,en-US</code> Standard Kommagetrennte TMDb-Fallback-Sprachen f\u00fcr Film- und Serienmetadaten (DVD/Blu-ray), z.B. de-DE,en-US,fr-FR. Wird von TMDb-Service und Serienzuordnung in Analyse/Metadaten-Dialog genutzt. Wenn bei fehlender Prim\u00e4rsprache automatisch andere Sprachversionen ausprobiert werden sollen. <code>Coverart-Nachladen aktiv</code> <code>coverart_recovery_enabled</code> <code>boolean</code> <code>true</code> Standard Wenn aktiv, werden fehlende Coverarts automatisch in Intervallen gepr\u00fcft und nachgeladen. Aenderung aktualisiert den Coverart-Recovery-Scheduler. Wenn fehlende Cover sp\u00e4ter automatisch nachgezogen werden sollen. <code>Coverart-Pr\u00fcfintervall (Stunden)</code> <code>coverart_recovery_interval_hours</code> <code>number</code> <code>6</code> Standard Intervall f\u00fcr automatische Pr\u00fcfung fehlender Coverarts in Stunden. Aenderung aktualisiert den Coverart-Recovery-Scheduler. Wenn der Nachlade-Job haeufiger oder seltener laufen soll. <code>NFO nach Encode erzeugen</code> <code>generate_nfo_after_encode</code> <code>boolean</code> <code>false</code> Standard Erstellt nach erfolgreichem Encode automatisch eine .nfo-Datei neben der Ausgabedatei. Wird nach erfolgreichem Encode in der Historie/Pipeline ausgewertet. Wenn neben der Ausgabedatei automatisch eine .nfo fuer Media-Center erzeugt werden soll."},{"location":"configuration/settings-reference/#kategorie-monitoring","title":"Kategorie: Monitoring","text":"GUI-Feld Key Typ Default Sichtbarkeit Was passiert technisch? Warum/Wann setzen? <code>Hardware Monitoring aktiviert</code> <code>hardware_monitoring_enabled</code> <code>boolean</code> <code>true</code> Standard Master-Schalter: aktiviert/deaktiviert das komplette Hardware-Monitoring (Polling + Berechnung + WebSocket-Updates). Aenderung triggert Re-Konfiguration des Hardware-Monitoring-Dienstes. Wenn CPU/RAM/GPU/Speicher live sichtbar sein sollen. <code>Hardware Monitoring Intervall (ms)</code> <code>hardware_monitoring_interval_ms</code> <code>number</code> <code>5000</code> Expertenmodus Polling-Intervall f\u00fcr CPU/RAM/GPU/Storage-Metriken. Aenderung triggert Re-Konfiguration des Hardware-Monitoring-Dienstes. Wenn Monitoring h\u00e4ufiger aktualisiert oder Last reduziert werden soll."},{"location":"configuration/settings-reference/#kategorie-pfade","title":"Kategorie: Pfade","text":"GUI-Feld Key Typ Default Sichtbarkeit Was passiert technisch? Warum/Wann setzen? <code>Raw Ausgabeordner (Blu-ray)</code> <code>raw_dir_bluray</code> <code>path</code> <code>leer</code> Standard Optionaler RAW-Zielpfad nur f\u00fcr Blu-ray. Leer = Fallback auf \"Raw Ausgabeordner\". Wenn 'Raw Ausgabeordner (Blu-ray)' vom Default abweichen soll. <code>Raw Ausgabeordner (DVD)</code> <code>raw_dir_dvd</code> <code>path</code> <code>leer</code> Standard Optionaler RAW-Zielpfad nur f\u00fcr DVD. Leer = Fallback auf \"Raw Ausgabeordner\". Wenn 'Raw Ausgabeordner (DVD)' vom Default abweichen soll. <code>CD RAW-Ordner</code> <code>raw_dir_cd</code> <code>path</code> <code>leer</code> Standard Basisordner f\u00fcr rohe CD-WAV-Dateien (cdparanoia-Output). Leer = Standardpfad (data/output/cd). Wenn 'CD RAW-Ordner' vom Default abweichen soll. <code>Audiobook RAW-Ordner</code> <code>raw_dir_audiobook</code> <code>path</code> <code>leer</code> Standard Basisordner f\u00fcr hochgeladene AAX-Dateien. Leer = Standardpfad (data/output/audiobook-raw). Wenn 'Audiobook RAW-Ordner' vom Default abweichen soll. <code>Serien-Ordner (Blu-ray)</code> <code>series_dir_bluray</code> <code>path</code> <code>leer</code> Standard Zielordner f\u00fcr Blu-ray-Serienfolgen. Leer = Standardpfad (data/output/series). Wenn 'Serien-Ordner (Blu-ray)' vom Default abweichen soll. <code>Film Ausgabeordner (Blu-ray)</code> <code>movie_dir_bluray</code> <code>path</code> <code>leer</code> Standard Optionaler Encode-Zielpfad nur f\u00fcr Blu-ray. Leer = Fallback auf \"Film Ausgabeordner\". Wenn 'Film Ausgabeordner (Blu-ray)' vom Default abweichen soll. <code>Film Ausgabeordner (DVD)</code> <code>movie_dir_dvd</code> <code>path</code> <code>leer</code> Standard Optionaler Encode-Zielpfad nur f\u00fcr DVD. Leer = Fallback auf \"Film Ausgabeordner\". Wenn 'Film Ausgabeordner (DVD)' vom Default abweichen soll. <code>Serien-Ordner (DVD)</code> <code>series_dir_dvd</code> <code>path</code> <code>leer</code> Standard Zielordner f\u00fcr DVD-Serienfolgen. Leer = Standardpfad (data/output/series). Wenn 'Serien-Ordner (DVD)' vom Default abweichen soll. <code>CD Output-Ordner</code> <code>movie_dir_cd</code> <code>path</code> <code>leer</code> Standard Zielordner f\u00fcr encodierte CD-Ausgaben (FLAC, MP3 usw.). Leer = gleicher Ordner wie CD RAW-Ordner. Wenn 'CD Output-Ordner' vom Default abweichen soll. <code>Audiobook Output-Ordner</code> <code>movie_dir_audiobook</code> <code>path</code> <code>leer</code> Standard Zielordner f\u00fcr encodierte Audiobook-Dateien. Leer = Standardpfad (data/output/audiobooks). Wenn 'Audiobook Output-Ordner' vom Default abweichen soll. <code>Download ZIP-Ordner</code> <code>download_dir</code> <code>path</code> <code>leer</code> Standard Zielordner f\u00fcr vorbereitete ZIP-Downloads. Leer = Standardpfad (data/downloads). Leere Werte nutzen automatisch den Installations-Defaultpfad. Wenn RAW/Output/Download auf andere Datentraeger verschoben werden sollen (z.B. grosse HDD/NAS). <code>Externe Speicher</code> <code>external_storage_paths</code> <code>path</code> <code>[]</code> Standard Wird links unter \"Freie Speicher\" angezeigt. Wenn 'Externe Speicher' vom Default abweichen soll. <code>Log Ordner</code> <code>log_dir</code> <code>path</code> <code>installationsabhaengig</code> Standard Basisordner f\u00fcr Logs. Job-Logs liegen direkt hier, Backend-Logs in /backend. Wird zur Laufzeit angewendet; bei ungueltigem Pfad faellt Ripster auf Fallback-Logpfad zurueck. Wenn Logs auf ein anderes Medium sollen (z.B. persistentes NAS/SSD statt Standardpfad). <code>CD Output Template</code> <code>cd_output_template</code> <code>string</code> <code>{artist} - {album} ({year})/{trackNr} {artist} - {title}</code> Standard Template f\u00fcr relative CD-Ausgabepfade ohne Dateiendung. Platzhalter: {artist}, {album}, {year}, {title}, {trackNr}, {trackNo}. Unterordner sind \u00fcber \"/\" m\u00f6glich. Die Endung wird \u00fcber das gew\u00e4hlte Ausgabeformat gesetzt. Wenn Ausgabe-/Ordnernamen standardisiert werden sollen. Beispiel: Serien nach Staffel oder Kapitel in Unterordner strukturieren. <code>Output Template (Blu-ray)</code> <code>output_template_bluray</code> <code>string</code> <code>${title} (${year})/${title} (${year})</code> Standard Template f\u00fcr Ordner und Dateiname. Platzhalter: ${title}, ${year}, ${imdbId}. Unterordner \u00fcber \"/\" m\u00f6glich \u2013 alles nach dem letzten \"/\" ist der Dateiname. Die Endung wird \u00fcber das gew\u00e4hlte Ausgabeformat gesetzt. Wenn Ausgabe-/Ordnernamen standardisiert werden sollen. Beispiel: Serien nach Staffel oder Kapitel in Unterordner strukturieren. <code>Output Template (Blu-ray Serie, Episode)</code> <code>output_template_bluray_series_episode</code> <code>string</code> <code>{seriesTitle}/Staffel {seasonNr}/S{seasonNr}E{episodeNr} - {episodeTitle}</code> Standard Template f\u00fcr einzelne Blu-ray-Serienepisoden ohne Dateiendung. Platzhalter: {seriesTitle}, {seasonNr}, {episodeNr}, {episodeTitle}, {discNr}, {year}, {language}. Optional mit f\u00fchrender Null: {0:seasonNr}, {0:episodeNr}. Wenn Ausgabe-/Ordnernamen standardisiert werden sollen. Beispiel: Serien nach Staffel oder Kapitel in Unterordner strukturieren. <code>Output Template (Blu-ray Serie, Multi-Episode)</code> <code>output_template_bluray_series_multi_episode</code> <code>string</code> <code>{seriesTitle}/Staffel {seasonNr}/S{0:seasonNr}E{episodeRange} - {episodeTitle} (Teil {parts})</code> Standard Template f\u00fcr zusammengefasste Blu-ray-Serienepisoden ohne Dateiendung. Platzhalter: {seriesTitle}, {seasonNr}, {episodeNoStart}, {episodeNoEnd}, {episodeRange}, {episodeTitle}, {parts}, {discNr}, {year}, {language}. Optional mit f\u00fchrender Null: {0:seasonNr}, {0:episodeNoStart}, {0:episodeNoEnd}. Wenn Ausgabe-/Ordnernamen standardisiert werden sollen. Beispiel: Serien nach Staffel oder Kapitel in Unterordner strukturieren. <code>Output Template (DVD)</code> <code>output_template_dvd</code> <code>string</code> <code>${title} (${year})/${title} (${year})</code> Standard Template f\u00fcr Ordner und Dateiname. Platzhalter: ${title}, ${year}, ${imdbId}. Unterordner \u00fcber \"/\" m\u00f6glich \u2013 alles nach dem letzten \"/\" ist der Dateiname. Die Endung wird \u00fcber das gew\u00e4hlte Ausgabeformat gesetzt. Wenn Ausgabe-/Ordnernamen standardisiert werden sollen. Beispiel: Serien nach Staffel oder Kapitel in Unterordner strukturieren. <code>Output Template (DVD Serie, Episode)</code> <code>output_template_dvd_series_episode</code> <code>string</code> <code>{seriesTitle}/Season {seasonNr}/{seriesTitle} - S{seasonNo}E{episodeNo} - {episodeTitle}</code> Standard Template f\u00fcr einzelne DVD-Serienepisoden ohne Dateiendung. Platzhalter: {seriesTitle}, {seasonNr}, {episodeNr}, {episodeTitle}, {discNr}, {year}, {language}. Optional mit f\u00fchrender Null: {0:seasonNr}, {0:episodeNr}. Wenn Ausgabe-/Ordnernamen standardisiert werden sollen. Beispiel: Serien nach Staffel oder Kapitel in Unterordner strukturieren. <code>Output Template (DVD Serie, Multi-Episode)</code> <code>output_template_dvd_series_multi_episode</code> <code>string</code> <code>{seriesTitle}/Season {seasonNr}/{seriesTitle} - S{seasonNo}E{episodeRange}</code> Standard Template f\u00fcr zusammengefasste DVD-Serienepisoden ohne Dateiendung. Platzhalter: {seriesTitle}, {seasonNr}, {episodeNoStart}, {episodeNoEnd}, {episodeRange}, {episodeTitle}, {parts}, {discNr}, {year}, {language}. Optional mit f\u00fchrender Null: {0:seasonNr}, {0:episodeNoStart}, {0:episodeNoEnd}. Wenn Ausgabe-/Ordnernamen standardisiert werden sollen. Beispiel: Serien nach Staffel oder Kapitel in Unterordner strukturieren. <code>Output Template (Audiobook)</code> <code>output_template_audiobook</code> <code>string</code> <code>{author}/{author} - {title} ({year})</code> Standard Template f\u00fcr relative Audiobook-Ausgabepfade ohne Dateiendung. Platzhalter: {author}, {title}, {year}, {narrator}, {series}, {part}, {format}. Unterordner sind \u00fcber \"/\" m\u00f6glich. Wenn Ausgabe-/Ordnernamen standardisiert werden sollen. Beispiel: Serien nach Staffel oder Kapitel in Unterordner strukturieren. <code>Audiobook RAW Template</code> <code>audiobook_raw_template</code> <code>string</code> <code>{author} - {title} ({year})</code> Standard Template f\u00fcr relative Audiobook-RAW-Ordner. Platzhalter: {author}, {title}, {year}, {narrator}, {series}, {part}. Wenn Ausgabe-/Ordnernamen standardisiert werden sollen. Beispiel: Serien nach Staffel oder Kapitel in Unterordner strukturieren. <code>Converter Raw-Ordner</code> <code>converter_raw_dir</code> <code>path</code> <code>leer</code> Standard Eingangsordner f\u00fcr den Converter (Import-Scan und Datei-Uploads). Jeder Upload erh\u00e4lt einen Unterordner. Leer = Standardpfad (data/output/converter-raw). Leere Werte nutzen automatisch den Installations-Defaultpfad. Wenn RAW/Output/Download auf andere Datentraeger verschoben werden sollen (z.B. grosse HDD/NAS). <code>Converter Ausgabe (Video)</code> <code>converter_movie_dir</code> <code>path</code> <code>leer</code> Standard Ausgabepfad f\u00fcr konvertierte Video-Dateien. Leer = Standardpfad (data/output/converted-movies). Leere Werte nutzen automatisch den Installations-Defaultpfad. Wenn RAW/Output/Download auf andere Datentraeger verschoben werden sollen (z.B. grosse HDD/NAS). <code>Converter Ausgabe (Audio)</code> <code>converter_audio_dir</code> <code>path</code> <code>leer</code> Standard Ausgabepfad f\u00fcr konvertierte Audio-Dateien. Leer = Standardpfad (data/output/converted-audio). Leere Werte nutzen automatisch den Installations-Defaultpfad. Wenn RAW/Output/Download auf andere Datentraeger verschoben werden sollen (z.B. grosse HDD/NAS). <code>Output-Template (Video)</code> <code>converter_output_template_video</code> <code>string</code> <code>{title}</code> Standard Dateiname-Template f\u00fcr konvertierte Video-Dateien (ohne Endung). Platzhalter: {title}, {year}. Wenn Ausgabe-/Ordnernamen standardisiert werden sollen. Beispiel: Serien nach Staffel oder Kapitel in Unterordner strukturieren. <code>Output-Template (Audio)</code> <code>converter_output_template_audio</code> <code>string</code> <code>{artist} - {title}</code> Standard Dateiname-Template f\u00fcr konvertierte Audio-Dateien (ohne Endung). Platzhalter: {artist}, {title}, {album}, {year}, {trackNr}. Wenn Ausgabe-/Ordnernamen standardisiert werden sollen. Beispiel: Serien nach Staffel oder Kapitel in Unterordner strukturieren. <code>RAW-Ordner (Blu-ray Serie)</code> <code>raw_dir_bluray_series</code> <code>path</code> <code>leer</code> Standard RAW-Zielpfad f\u00fcr Blu-ray-Serien. Leer = gleicher Pfad wie RAW-Ordner (Blu-ray). Wenn 'RAW-Ordner (Blu-ray Serie)' vom Default abweichen soll. <code>Eigent\u00fcmer RAW-Ordner (Blu-ray Serie)</code> <code>raw_dir_bluray_series_owner</code> <code>string</code> <code>leer</code> Standard Eigent\u00fcmer der Dateien im Format user:gruppe f\u00fcr Blu-ray-Serien-RAW. Leer = Eigent\u00fcmer Raw-Ordner (Blu-ray). Wird beim Anlegen/Finalisieren per <code>chown</code> auf Zielpfade angewendet. Wenn Dateien/Ordner nicht dem Service-User gehoeren sollen (z.B. NAS-Freigaben). Beispiel: <code>media:media</code>. <code>Eigent\u00fcmer Raw-Ordner (Blu-ray)</code> <code>raw_dir_bluray_owner</code> <code>string</code> <code>leer</code> Standard Eigent\u00fcmer der Dateien im Format user:gruppe. Nur aktiv wenn ein alternativer Pfad gesetzt ist. Leer = Standardbenutzer des Dienstes. Wird beim Anlegen/Finalisieren per <code>chown</code> auf Zielpfade angewendet. Wenn Dateien/Ordner nicht dem Service-User gehoeren sollen (z.B. NAS-Freigaben). Beispiel: <code>media:media</code>. <code>RAW-Ordner (DVD Serie)</code> <code>raw_dir_dvd_series</code> <code>path</code> <code>leer</code> Standard RAW-Zielpfad f\u00fcr DVD-Serien. Leer = gleicher Pfad wie RAW-Ordner (DVD). Wenn 'RAW-Ordner (DVD Serie)' vom Default abweichen soll. <code>Eigent\u00fcmer RAW-Ordner (DVD Serie)</code> <code>raw_dir_dvd_series_owner</code> <code>string</code> <code>leer</code> Standard Eigent\u00fcmer der Dateien im Format user:gruppe f\u00fcr DVD-Serien-RAW. Leer = Eigent\u00fcmer Raw-Ordner (DVD). Wird beim Anlegen/Finalisieren per <code>chown</code> auf Zielpfade angewendet. Wenn Dateien/Ordner nicht dem Service-User gehoeren sollen (z.B. NAS-Freigaben). Beispiel: <code>media:media</code>. <code>Eigent\u00fcmer Raw-Ordner (DVD)</code> <code>raw_dir_dvd_owner</code> <code>string</code> <code>leer</code> Standard Eigent\u00fcmer der Dateien im Format user:gruppe. Nur aktiv wenn ein alternativer Pfad gesetzt ist. Leer = Standardbenutzer des Dienstes. Wird beim Anlegen/Finalisieren per <code>chown</code> auf Zielpfade angewendet. Wenn Dateien/Ordner nicht dem Service-User gehoeren sollen (z.B. NAS-Freigaben). Beispiel: <code>media:media</code>. <code>Eigent\u00fcmer CD RAW-Ordner</code> <code>raw_dir_cd_owner</code> <code>string</code> <code>leer</code> Standard Eigent\u00fcmer der Dateien im Format user:gruppe. Nur aktiv wenn ein alternativer Pfad gesetzt ist. Leer = Standardbenutzer des Dienstes. Wird beim Anlegen/Finalisieren per <code>chown</code> auf Zielpfade angewendet. Wenn Dateien/Ordner nicht dem Service-User gehoeren sollen (z.B. NAS-Freigaben). Beispiel: <code>media:media</code>. <code>Eigent\u00fcmer Audiobook RAW-Ordner</code> <code>raw_dir_audiobook_owner</code> <code>string</code> <code>leer</code> Standard Eigent\u00fcmer der Audiobook-RAW-Dateien im Format user:gruppe. Nur aktiv wenn ein Pfad gesetzt ist. Leer = Standardbenutzer des Dienstes. Wird beim Anlegen/Finalisieren per <code>chown</code> auf Zielpfade angewendet. Wenn Dateien/Ordner nicht dem Service-User gehoeren sollen (z.B. NAS-Freigaben). Beispiel: <code>media:media</code>. <code>Eigent\u00fcmer Converter RAW-Ordner</code> <code>converter_raw_dir_owner</code> <code>string</code> <code>leer</code> Standard Eigent\u00fcmer der Converter-Eingabedateien im Format user:gruppe. Leer = Standardbenutzer des Dienstes. Wird beim Anlegen/Finalisieren per <code>chown</code> auf Zielpfade angewendet. Wenn Dateien/Ordner nicht dem Service-User gehoeren sollen (z.B. NAS-Freigaben). Beispiel: <code>media:media</code>. <code>Eigent\u00fcmer Serien-Ordner (Blu-ray)</code> <code>series_dir_bluray_owner</code> <code>string</code> <code>leer</code> Standard Eigent\u00fcmer der Blu-ray-Serienausgaben im Format user:gruppe. Leer = Standardbenutzer des Dienstes. Wird beim Anlegen/Finalisieren per <code>chown</code> auf Zielpfade angewendet. Wenn Dateien/Ordner nicht dem Service-User gehoeren sollen (z.B. NAS-Freigaben). Beispiel: <code>media:media</code>. <code>Eigent\u00fcmer Film-Ordner (Blu-ray)</code> <code>movie_dir_bluray_owner</code> <code>string</code> <code>leer</code> Standard Eigent\u00fcmer der Dateien im Format user:gruppe. Nur aktiv wenn ein alternativer Pfad gesetzt ist. Leer = Standardbenutzer des Dienstes. Wird beim Anlegen/Finalisieren per <code>chown</code> auf Zielpfade angewendet. Wenn Dateien/Ordner nicht dem Service-User gehoeren sollen (z.B. NAS-Freigaben). Beispiel: <code>media:media</code>. <code>Eigent\u00fcmer Film-Ordner (DVD)</code> <code>movie_dir_dvd_owner</code> <code>string</code> <code>leer</code> Standard Eigent\u00fcmer der Dateien im Format user:gruppe. Nur aktiv wenn ein alternativer Pfad gesetzt ist. Leer = Standardbenutzer des Dienstes. Wird beim Anlegen/Finalisieren per <code>chown</code> auf Zielpfade angewendet. Wenn Dateien/Ordner nicht dem Service-User gehoeren sollen (z.B. NAS-Freigaben). Beispiel: <code>media:media</code>. <code>Eigent\u00fcmer Serien-Ordner (DVD)</code> <code>series_dir_dvd_owner</code> <code>string</code> <code>leer</code> Standard Eigent\u00fcmer der DVD-Serienausgaben im Format user:gruppe. Leer = Standardbenutzer des Dienstes. Wird beim Anlegen/Finalisieren per <code>chown</code> auf Zielpfade angewendet. Wenn Dateien/Ordner nicht dem Service-User gehoeren sollen (z.B. NAS-Freigaben). Beispiel: <code>media:media</code>. <code>Eigent\u00fcmer CD Output-Ordner</code> <code>movie_dir_cd_owner</code> <code>string</code> <code>leer</code> Standard Eigent\u00fcmer der encodierten CD-Ausgaben im Format user:gruppe. Leer = Standardbenutzer des Dienstes. Wird beim Anlegen/Finalisieren per <code>chown</code> auf Zielpfade angewendet. Wenn Dateien/Ordner nicht dem Service-User gehoeren sollen (z.B. NAS-Freigaben). Beispiel: <code>media:media</code>. <code>Eigent\u00fcmer Audiobook Output-Ordner</code> <code>movie_dir_audiobook_owner</code> <code>string</code> <code>leer</code> Standard Eigent\u00fcmer der encodierten Audiobook-Dateien im Format user:gruppe. Leer = Standardbenutzer des Dienstes. Wird beim Anlegen/Finalisieren per <code>chown</code> auf Zielpfade angewendet. Wenn Dateien/Ordner nicht dem Service-User gehoeren sollen (z.B. NAS-Freigaben). Beispiel: <code>media:media</code>. <code>Eigent\u00fcmer Converter Video Output-Ordner</code> <code>converter_movie_dir_owner</code> <code>string</code> <code>leer</code> Standard Eigent\u00fcmer der konvertierten Video-Dateien im Format user:gruppe. Leer = Standardbenutzer des Dienstes. Wird beim Anlegen/Finalisieren per <code>chown</code> auf Zielpfade angewendet. Wenn Dateien/Ordner nicht dem Service-User gehoeren sollen (z.B. NAS-Freigaben). Beispiel: <code>media:media</code>. <code>Eigent\u00fcmer Converter Audio Output-Ordner</code> <code>converter_audio_dir_owner</code> <code>string</code> <code>leer</code> Standard Eigent\u00fcmer der konvertierten Audio-Dateien im Format user:gruppe. Leer = Standardbenutzer des Dienstes. Wird beim Anlegen/Finalisieren per <code>chown</code> auf Zielpfade angewendet. Wenn Dateien/Ordner nicht dem Service-User gehoeren sollen (z.B. NAS-Freigaben). Beispiel: <code>media:media</code>. <code>Eigent\u00fcmer Download ZIP-Ordner</code> <code>download_dir_owner</code> <code>string</code> <code>leer</code> Standard Eigent\u00fcmer der vorbereiteten ZIP-Dateien im Format user:gruppe. Leer = Standardbenutzer des Dienstes. Wird beim Anlegen/Finalisieren per <code>chown</code> auf Zielpfade angewendet. Greift bei ZIP-Ordner, Archivdatei und Metadatei. Wenn Dateien/Ordner nicht dem Service-User gehoeren sollen (z.B. NAS-Freigaben). Beispiel: <code>media:media</code>. <code>Kapitel Template (Audiobook)</code> <code>output_chapter_template_audiobook</code> <code>string</code> <code>{author}/{author} - {title} ({year})/{chapterNr} {chapterTitle}</code> Standard Template f\u00fcr kapitelweise Audiobook-Ausgaben (MP3/FLAC) ohne Dateiendung. Platzhalter: {author}, {title}, {year}, {narrator}, {series}, {part}, {format}, {chapterNr}, {chapterNo}, {chapterTitle}. Unterordner sind \u00fcber \"/\" m\u00f6glich. Wenn Ausgabe-/Ordnernamen standardisiert werden sollen. Beispiel: Serien nach Staffel oder Kapitel in Unterordner strukturieren."},{"location":"configuration/settings-reference/#kategorie-tools","title":"Kategorie: Tools","text":"GUI-Feld Key Typ Default Sichtbarkeit Was passiert technisch? Warum/Wann setzen? <code>MakeMKV Kommando</code> <code>makemkv_command</code> <code>string</code> <code>makemkvcon</code> Expertenmodus Pfad oder Befehl f\u00fcr makemkvcon. Wenn ein Tool nicht im PATH liegt oder eine feste Binary genutzt werden soll (voller Pfad). <code>MakeMKV Key</code> <code>makemkv_registration_key</code> <code>string</code> <code>leer</code> Standard Optionaler Registrierungsschl\u00fcssel. Wird beim Speichern nach ~/.MakeMKV/settings.conf synchronisiert. Darunter kann der aktuelle Betakey per API \u00fcbernommen werden. Wenn MakeMKV-Features ohne Trial-Limit genutzt werden sollen (inkl. Betakey-Usecase). <code>Mediainfo Kommando</code> <code>mediainfo_command</code> <code>string</code> <code>mediainfo</code> Expertenmodus Pfad oder Befehl f\u00fcr mediainfo. Wenn ein Tool nicht im PATH liegt oder eine feste Binary genutzt werden soll (voller Pfad). <code>Minimale Titell\u00e4nge (Minuten)</code> <code>makemkv_min_length_minutes</code> <code>number</code> <code>60</code> Standard Filtert kurze Titel beim Rip. Wenn kurze Bonus-/Trailer-Titel automatisch ausgefiltert werden sollen. <code>TMDb Runtime-Abzug f\u00fcr Playlistfilter (%)</code> <code>playlist_tmdb_runtime_subtract_percent</code> <code>number</code> <code>0</code> Standard Zieht optional einen Prozentsatz von der TMDb-Laufzeit ab, damit Ripster bei problematischen Blu-rays leicht k\u00fcrzere Hauptfassungen trotzdem als Playlist-Kandidaten zul\u00e4sst. Eine Mindesttoleranz von 2 Minuten nach unten bleibt erhalten. Wenn die Playlist-Analyse bei einzelnen Discs zu streng ist und der Hauptfilm knapp unter der TMDb-Laufzeit liegt. Beispiel: TMDb sagt 120 Minuten, die Disc liefert 116 bis 118 Minuten, aber die Fassung ist trotzdem korrekt. <code>HandBrake Kommando</code> <code>handbrake_command</code> <code>string</code> <code>HandBrakeCLI</code> Expertenmodus Pfad oder Befehl f\u00fcr HandBrakeCLI. Wenn ein Tool nicht im PATH liegt oder eine feste Binary genutzt werden soll (voller Pfad). <code>Encode-Neustart: unvollst\u00e4ndige Ausgabe l\u00f6schen</code> <code>handbrake_restart_delete_incomplete_output</code> <code>boolean</code> <code>true</code> Standard Wenn aktiv, wird bei \"Encode neu starten\" der bisherige (nicht erfolgreiche) Output vor Start entfernt. Wenn bei Encode-Neustart alte, unvollstaendige Dateien sicher entfernt werden sollen. <code>Parallele Jobs</code> <code>pipeline_max_parallel_jobs</code> <code>number</code> <code>1</code> Standard Maximale Anzahl parallel laufender Jobs. Weitere Starts landen in der Queue. Aenderung beeinflusst Queue-Pump und Startentscheidungen fuer neue Jobs. Wenn Durchsatz und CPU-Last fuer Videojobs ausbalanciert werden sollen. <code>Max. parallele Audio CD Jobs</code> <code>pipeline_max_parallel_cd_encodes</code> <code>number</code> <code>2</code> Standard Maximale Anzahl parallel laufender Audio CD Jobs (Rip + Encode als Einheit). Gilt zus\u00e4tzlich zum Gesamtlimit. Aenderung beeinflusst Queue-Pump und Startentscheidungen fuer neue Jobs. Wenn mehrere Audio-CD-Jobs parallel erlaubt/begrenzt werden sollen. <code>Script-Test Timeout (ms)</code> <code>script_test_timeout_ms</code> <code>number</code> <code>0</code> Expertenmodus Timeout fuer Script-Tests in den Settings. 0 = kein Timeout. Wird beim Testlauf von Scripts in Settings angewendet. Wenn Script-Tests bei Haengern automatisch abgebrochen werden sollen. <code>Max. Encodes gesamt (medienunabh\u00e4ngig)</code> <code>pipeline_max_total_encodes</code> <code>number</code> <code>3</code> Standard Gesamtlimit f\u00fcr alle parallel laufenden Encode-Jobs (Film + Audio CD). Dieses Limit hat Vorrang vor den Einzellimits. Aenderung beeinflusst Queue-Pump und Startentscheidungen fuer neue Jobs. Wenn ein harter Deckel fuer alle Encodes zusammen gelten soll. <code>Audio CDs: Queue-Reihenfolge \u00fcberspringen</code> <code>pipeline_cd_bypasses_queue</code> <code>boolean</code> <code>false</code> Standard Wenn aktiv, k\u00f6nnen Audio CD Jobs unabh\u00e4ngig von Film-Jobs starten (\u00fcberspringen die Film-Queue-Reihenfolge). Einzellimits und Gesamtlimit gelten weiterhin. Aenderung beeinflusst Queue-Pump und Startentscheidungen fuer neue Jobs. Wenn Audio-CD-Jobs nicht hinter langen Video-Warteschlangen blockieren sollen. <code>cdparanoia Kommando</code> <code>cdparanoia_command</code> <code>string</code> <code>cdparanoia</code> Expertenmodus Pfad oder Befehl f\u00fcr cdparanoia. Wird als Fallback genutzt wenn kein individuelles Kommando gesetzt ist. Wenn ein Tool nicht im PATH liegt oder eine feste Binary genutzt werden soll (voller Pfad). <code>FFmpeg Kommando</code> <code>ffmpeg_command</code> <code>string</code> <code>ffmpeg</code> Standard Pfad oder Befehl f\u00fcr ffmpeg. Wird f\u00fcr Audiobook-Encoding genutzt. Wenn ein Tool nicht im PATH liegt oder eine feste Binary genutzt werden soll (voller Pfad). <code>FFprobe Kommando</code> <code>ffprobe_command</code> <code>string</code> <code>ffprobe</code> Standard Pfad oder Befehl f\u00fcr ffprobe. Wird f\u00fcr Audiobook-Metadaten und Kapitel genutzt. Wenn ein Tool nicht im PATH liegt oder eine feste Binary genutzt werden soll (voller Pfad). <code>Mediainfo Extra Args</code> <code>mediainfo_extra_args_bluray</code> <code>string</code> <code>leer</code> Expertenmodus Zus\u00e4tzliche CLI-Parameter f\u00fcr mediainfo (Blu-ray). Wenn du das CLI-Verhalten feinjustieren willst (Codec, Sprache, Untertitel, Analyse-Optionen). <code>MakeMKV Rip Modus</code> <code>makemkv_rip_mode_bluray</code> <code>select</code> <code>backup</code> Ausgeblendet (nur API/DB) mkv: direkte MKV-Dateien; backup: vollst\u00e4ndige Blu-ray Struktur im RAW-Ordner. Wenn fuer 'MakeMKV Rip Modus' ein anderes Standardverhalten benoetigt wird. <code>MakeMKV Analyze Extra Args</code> <code>makemkv_analyze_extra_args_bluray</code> <code>string</code> <code>leer</code> Expertenmodus Zus\u00e4tzliche CLI-Parameter f\u00fcr Analyze (Blu-ray). Wenn du das CLI-Verhalten feinjustieren willst (Codec, Sprache, Untertitel, Analyse-Optionen). <code>MakeMKV Rip Extra Args</code> <code>makemkv_rip_extra_args_bluray</code> <code>string</code> <code>leer</code> Expertenmodus Zus\u00e4tzliche CLI-Parameter f\u00fcr Rip (Blu-ray). Wenn du das CLI-Verhalten feinjustieren willst (Codec, Sprache, Untertitel, Analyse-Optionen). <code>HandBrake Preset</code> <code>handbrake_preset_bluray</code> <code>string</code> <code>H.264 MKV 1080p30</code> Standard Preset Name f\u00fcr -Z (Blu-ray). Leer = kein Preset, nur CLI-Parameter werden verwendet. Wenn ein bevorzugtes Standard-Preset fuer Blu-ray nicht jedes Mal manuell gewaehlt werden soll. <code>HandBrake Extra Args</code> <code>handbrake_extra_args_bluray</code> <code>string</code> <code>--audio-lang-list deu,eng --first-audio --subtitle-lang-list deu,eng --first-subtitle --aencoder copy --audio-copy-ma...</code> Standard Zus\u00e4tzliche CLI-Argumente (Blu-ray). Wenn du das CLI-Verhalten feinjustieren willst (Codec, Sprache, Untertitel, Analyse-Optionen). <code>Review Audio-Sprachen (Blu-ray Film)</code> <code>handbrake_review_audio_languages_bluray_movie</code> <code>string</code> <code>leer</code> Standard Kommagetrennte Sprachliste f\u00fcr die Review-Vorauswahl von Audio-Spuren bei Blu-ray-Filmen. Beispiel: <code>de,en,jp</code>. Greift nur, wenn Preset/Extra Args keine Audio-Auswahl vorgeben. Wenn bei Blu-ray-Filmen im Review nicht mehr alle Audio-Spuren vorausgew\u00e4hlt werden sollen, sondern nur bestimmte Sprachen. <code>Review UT-Sprachen (Blu-ray Film)</code> <code>handbrake_review_subtitle_languages_bluray_movie</code> <code>string</code> <code>leer</code> Standard Kommagetrennte Sprachliste f\u00fcr die Review-Vorauswahl von Untertiteln bei Blu-ray-Filmen. Beispiel: <code>de,en,jp</code>. Greift nur, wenn Preset/Extra Args keine Subtitle-Auswahl vorgeben. Wenn bei Blu-ray-Filmen im Review nicht mehr alle Untertitel vorausgew\u00e4hlt werden sollen, sondern nur bestimmte Sprachen. <code>Review Audio-Sprachen (Blu-ray Serie)</code> <code>handbrake_review_audio_languages_bluray_series</code> <code>string</code> <code>leer</code> Standard Kommagetrennte Sprachliste f\u00fcr die Review-Vorauswahl von Audio-Spuren bei Blu-ray-Serien. Beispiel: <code>de,en,jp</code>. Greift nur, wenn Preset/Extra Args keine Audio-Auswahl vorgeben. Wenn bei Blu-ray-Serien im Review nicht mehr alle Audio-Spuren vorausgew\u00e4hlt werden sollen, sondern nur bestimmte Sprachen. <code>Review UT-Sprachen (Blu-ray Serie)</code> <code>handbrake_review_subtitle_languages_bluray_series</code> <code>string</code> <code>leer</code> Standard Kommagetrennte Sprachliste f\u00fcr die Review-Vorauswahl von Untertiteln bei Blu-ray-Serien. Beispiel: <code>de,en,jp</code>. Greift nur, wenn Preset/Extra Args keine Subtitle-Auswahl vorgeben. Wenn bei Blu-ray-Serien im Review nicht mehr alle Untertitel vorausgew\u00e4hlt werden sollen, sondern nur bestimmte Sprachen. <code>Ausgabeformat</code> <code>output_extension_bluray</code> <code>select</code> <code>mkv</code> Standard Dateiendung f\u00fcr finale Datei (Blu-ray). Wenn finale Blu-ray-Dateien standardmaessig als MKV oder MP4 ausgegeben werden sollen. <code>Mediainfo Extra Args</code> <code>mediainfo_extra_args_dvd</code> <code>string</code> <code>leer</code> Expertenmodus Zus\u00e4tzliche CLI-Parameter f\u00fcr mediainfo (DVD). Wenn du das CLI-Verhalten feinjustieren willst (Codec, Sprache, Untertitel, Analyse-Optionen). <code>MakeMKV Rip Modus</code> <code>makemkv_rip_mode_dvd</code> <code>select</code> <code>mkv</code> Ausgeblendet (nur API/DB) mkv: direkte MKV-Dateien; backup: vollst\u00e4ndige Disc-Struktur im RAW-Ordner. Wenn fuer 'MakeMKV Rip Modus' ein anderes Standardverhalten benoetigt wird. <code>MakeMKV Analyze Extra Args</code> <code>makemkv_analyze_extra_args_dvd</code> <code>string</code> <code>leer</code> Expertenmodus Zus\u00e4tzliche CLI-Parameter f\u00fcr Analyze (DVD). Wenn du das CLI-Verhalten feinjustieren willst (Codec, Sprache, Untertitel, Analyse-Optionen). <code>MakeMKV Rip Extra Args</code> <code>makemkv_rip_extra_args_dvd</code> <code>string</code> <code>leer</code> Expertenmodus Zus\u00e4tzliche CLI-Parameter f\u00fcr Rip (DVD). Wenn du das CLI-Verhalten feinjustieren willst (Codec, Sprache, Untertitel, Analyse-Optionen). <code>HandBrake Preset</code> <code>handbrake_preset_dvd</code> <code>string</code> <code>H.264 MKV 480p30</code> Standard Preset Name f\u00fcr -Z (DVD). Leer = kein Preset, nur CLI-Parameter werden verwendet. Wenn ein bevorzugtes Standard-Preset fuer DVD nicht jedes Mal manuell gewaehlt werden soll. <code>HandBrake Extra Args</code> <code>handbrake_extra_args_dvd</code> <code>string</code> <code>--audio-lang-list deu,eng --first-audio --subtitle-lang-list deu,eng --first-subtitle --aencoder copy --audio-copy-ma...</code> Standard Zus\u00e4tzliche CLI-Argumente (DVD). Wenn du das CLI-Verhalten feinjustieren willst (Codec, Sprache, Untertitel, Analyse-Optionen). <code>Review Audio-Sprachen (DVD Film)</code> <code>handbrake_review_audio_languages_dvd_movie</code> <code>string</code> <code>leer</code> Standard Kommagetrennte Sprachliste f\u00fcr die Review-Vorauswahl von Audio-Spuren bei DVD-Filmen. Beispiel: <code>de,en,jp</code>. Greift nur, wenn Preset/Extra Args keine Audio-Auswahl vorgeben. Wenn bei DVD-Filmen im Review nicht mehr alle Audio-Spuren vorausgew\u00e4hlt werden sollen, sondern nur bestimmte Sprachen. <code>Review UT-Sprachen (DVD Film)</code> <code>handbrake_review_subtitle_languages_dvd_movie</code> <code>string</code> <code>leer</code> Standard Kommagetrennte Sprachliste f\u00fcr die Review-Vorauswahl von Untertiteln bei DVD-Filmen. Beispiel: <code>de,en,jp</code>. Greift nur, wenn Preset/Extra Args keine Subtitle-Auswahl vorgeben. Wenn bei DVD-Filmen im Review nicht mehr alle Untertitel vorausgew\u00e4hlt werden sollen, sondern nur bestimmte Sprachen. <code>Review Audio-Sprachen (DVD Serie)</code> <code>handbrake_review_audio_languages_dvd_series</code> <code>string</code> <code>leer</code> Standard Kommagetrennte Sprachliste f\u00fcr die Review-Vorauswahl von Audio-Spuren bei DVD-Serien. Beispiel: <code>de,en,jp</code>. Greift nur, wenn Preset/Extra Args keine Audio-Auswahl vorgeben. Wenn bei DVD-Serien im Review nicht mehr alle Audio-Spuren vorausgew\u00e4hlt werden sollen, sondern nur bestimmte Sprachen. <code>Review UT-Sprachen (DVD Serie)</code> <code>handbrake_review_subtitle_languages_dvd_series</code> <code>string</code> <code>leer</code> Standard Kommagetrennte Sprachliste f\u00fcr die Review-Vorauswahl von Untertiteln bei DVD-Serien. Beispiel: <code>de,en,jp</code>. Greift nur, wenn Preset/Extra Args keine Subtitle-Auswahl vorgeben. Wenn bei DVD-Serien im Review nicht mehr alle Untertitel vorausgew\u00e4hlt werden sollen, sondern nur bestimmte Sprachen. <code>Ausgabeformat</code> <code>output_extension_dvd</code> <code>select</code> <code>mkv</code> Standard Dateiendung f\u00fcr finale Datei (DVD). Wenn finale DVD-Dateien standardmaessig als MKV oder MP4 ausgegeben werden sollen. <code>mkvmerge Kommando</code> <code>mkvmerge_command</code> <code>string</code> <code>mkvmerge</code> Standard Pfad oder Befehl f\u00fcr mkvmerge. Wird f\u00fcr Multipart-Movie-Merges genutzt. Wenn ein Tool nicht im PATH liegt oder eine feste Binary genutzt werden soll (voller Pfad)."},{"location":"configuration/settings-reference/#spezielle-werteformate","title":"Spezielle Werteformate","text":"<ul> <li><code>Eigent\u00fcmer (user:gruppe)</code>: z.B. <code>media:media</code> oder <code>1000:1000</code>.</li> <li><code>drive_devices</code> (JSON): <code>[{\"path\":\"/dev/sr0\",\"makemkvIndex\":0},{\"path\":\"/dev/sr1\",\"makemkvIndex\":1}]</code></li> <li><code>external_storage_paths</code> (JSON): <code>[{\"name\":\"USB HDD\",\"path\":\"/mnt/usb-hdd\"}]</code></li> <li><code>converter_scan_extensions</code>: kommagetrennt, ohne Punkt, z.B. <code>mkv,mp4,flac,mp3</code>.</li> <li>Template-Felder: erlauben Platzhalter (<code>{...}</code> / <code>${...}</code>) und <code>/</code> fuer Unterordner.</li> </ul>"},{"location":"configuration/settings-reference/#hinweis-zu-ausgeblendeten-feldern","title":"Hinweis zu ausgeblendeten Feldern","text":"<p>Die Keys <code>drive_device</code>, <code>makemkv_source_index</code>, <code>makemkv_rip_mode_bluray</code>, <code>makemkv_rip_mode_dvd</code> liegen im Schema, werden aber bewusst nicht im normalen Formular angezeigt.</p>"},{"location":"deployment/","title":"Anhang: Deployment","text":"<p>Technische Betriebsdokumentation f\u00fcr Entwicklung und Produktion.</p> <ul> <li> <p> Entwicklungsumgebung</p> <p>Lokale Entwicklung mit Hot-Reload.</p> <p> Entwicklung</p> </li> <li> <p> Produktion</p> <p>Installation und Betrieb auf Servern.</p> <p> Produktion</p> </li> </ul>"},{"location":"deployment/development/","title":"Entwicklungsumgebung","text":""},{"location":"deployment/development/#voraussetzungen","title":"Voraussetzungen","text":"<ul> <li>Node.js &gt;= 20.19.0</li> <li>externe Tools installiert (<code>makemkvcon</code>, <code>HandBrakeCLI</code>, <code>mediainfo</code>)</li> </ul>"},{"location":"deployment/development/#schnellstart","title":"Schnellstart","text":"<pre><code>./start.sh\n</code></pre> <p>Startet:</p> <ul> <li>Backend (<code>http://localhost:3001</code>, mit nodemon)</li> <li>Frontend (<code>http://localhost:5173</code>, mit Vite HMR)</li> </ul> <p>Stoppen: <code>Ctrl+C</code>.</p>"},{"location":"deployment/development/#manuell","title":"Manuell","text":""},{"location":"deployment/development/#backend","title":"Backend","text":"<pre><code>cd backend\nnpm install\nnpm run dev\n</code></pre>"},{"location":"deployment/development/#frontend","title":"Frontend","text":"<pre><code>cd frontend\nnpm install\nnpm run dev\n</code></pre>"},{"location":"deployment/development/#vite-proxy-dev","title":"Vite-Proxy (Dev)","text":"<p><code>frontend/vite.config.js</code> proxied standardm\u00e4\u00dfig:</p> <ul> <li><code>/api</code> -&gt; <code>http://127.0.0.1:3001</code></li> <li><code>/ws</code> -&gt; <code>ws://127.0.0.1:3001</code></li> </ul>"},{"location":"deployment/development/#remote-dev-optional","title":"Remote-Dev (optional)","text":"<p>Beispiel <code>frontend/.env.local</code>:</p> <pre><code>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</code></pre>"},{"location":"deployment/development/#nutzliche-kommandos","title":"N\u00fctzliche Kommandos","text":"<pre><code># 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</code></pre>"},{"location":"deployment/production/","title":"Produktions-Deployment","text":""},{"location":"deployment/production/#automatische-installation-empfohlen","title":"Automatische Installation (empfohlen)","text":"<p>Das mitgelieferte <code>install.sh</code> richtet Ripster vollautomatisch ein \u2013 inklusive Node.js, MakeMKV, HandBrake, nginx und systemd-Dienst.</p> <p>Unterst\u00fctzte Systeme laut Script: Debian, Ubuntu, Linux Mint, Pop!_OS Voraussetzung: root-Rechte, Internetzugang</p>"},{"location":"deployment/production/#schnellstart-via-curl","title":"Schnellstart via curl","text":"<pre><code>curl -fsSL https://raw.githubusercontent.com/Mboehmlaender/ripster/main/install.sh | sudo bash\n</code></pre> <p>Oder mit wget:</p> <pre><code>wget -qO- https://raw.githubusercontent.com/Mboehmlaender/ripster/main/install.sh | sudo bash\n</code></pre> <p>Optionen nur via Datei</p> <p>Beim Pipen von curl/wget k\u00f6nnen keine Argumente \u00fcbergeben werden. F\u00fcr benutzerdefinierte Optionen zuerst herunterladen und dann mit <code>sudo bash install.sh [Optionen]</code> ausf\u00fchren.</p>"},{"location":"deployment/production/#optionen","title":"Optionen","text":"Option Standard Beschreibung <code>--branch &lt;branch&gt;</code> <code>dev</code> Git-Branch f\u00fcr die Installation <code>--dir &lt;pfad&gt;</code> <code>/opt/ripster</code> Installationsverzeichnis <code>--user &lt;benutzer&gt;</code> <code>ripster</code> Systembenutzer f\u00fcr den Dienst <code>--port &lt;port&gt;</code> <code>3001</code> Backend-Port <code>--host &lt;hostname&gt;</code> Auto (Maschinen-IP) Hostname/IP f\u00fcr die Weboberfl\u00e4che <code>--no-makemkv</code> \u2013 MakeMKV-Installation \u00fcberspringen <code>--no-handbrake</code> \u2013 HandBrake-Installation \u00fcberspringen <code>--no-nginx</code> \u2013 nginx-Einrichtung \u00fcberspringen <code>--reinstall</code> \u2013 Bestehende Installation aktualisieren (Daten bleiben erhalten) <code>-h</code>, <code>--help</code> \u2013 Hilfe anzeigen"},{"location":"deployment/production/#beispiele","title":"Beispiele","text":"<pre><code># 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</code></pre>"},{"location":"deployment/production/#was-das-skript-erledigt","title":"Was das Skript erledigt","text":"<ol> <li>Systempr\u00fcfung \u2013 OS-Erkennung und Root-Check</li> <li>Systempakete \u2013 <code>curl</code>, <code>wget</code>, <code>git</code>, <code>mediainfo</code>, <code>udev</code> u. a.</li> <li>Node.js 20 \u2013 via NodeSource, falls noch nicht installiert</li> <li>MakeMKV \u2013 aktuelle Version wird aus dem offiziellen Forum ermittelt und aus dem Quellcode kompiliert (kann mit <code>--no-makemkv</code> \u00fcbersprungen werden)</li> <li>HandBrake \u2013 interaktive Auswahl:<ul> <li>Option 1: Standard (<code>apt install handbrake-cli</code>)</li> <li>Option 2: Geb\u00fcndelte GPU-Version mit NVDEC aus <code>bin/HandBrakeCLI</code></li> </ul> </li> <li>Systembenutzer <code>ripster</code> \u2013 ohne Login-Shell und ohne Home-Verzeichnis; Gruppen werden (falls vorhanden) erg\u00e4nzt: <code>cdrom</code>, <code>optical</code>, <code>disk</code>, <code>video</code>, <code>render</code></li> <li>Repository \u2013 klont Branch nach <code>--dir</code> (bei <code>--reinstall</code>: sichert <code>backend/data</code>, aktualisiert Repo, stellt Daten wieder her)</li> <li>Verzeichnisse \u2013 stellt u. a. sicher: <code>backend/data</code>, <code>backend/logs</code>, <code>backend/data/output/raw</code>, <code>backend/data/output/movies</code>, <code>backend/data/logs</code></li> <li>npm-Abh\u00e4ngigkeiten \u2013 Root, Backend (nur production), Frontend</li> <li>Frontend-Build \u2013 <code>npm run build</code> mit relativen API-URLs (nginx-kompatibel)</li> <li>Backend <code>.env</code> \u2013 wird automatisch generiert (bei <code>--reinstall</code> bleibt bestehende <code>.env</code> erhalten)</li> <li>Berechtigungen \u2013 zun\u00e4chst <code>ripster:ripster</code> auf Installationsverzeichnis; bei sudo-Aufruf werden Output-/Log-Ordner auf <code>&lt;aufrufender user&gt;:ripster</code> mit <code>775</code> gesetzt; <code>.env</code> wird auf <code>600</code> gesetzt</li> <li>MakeMKV User-Ordner \u2013 erstellt bei sudo-Aufruf <code>~/.MakeMKV</code> f\u00fcr den aufrufenden Benutzer</li> <li>systemd-Dienst \u2013 <code>ripster-backend.service</code> erstellt, aktiviert und gestartet</li> <li>nginx \u2013 konfiguriert als Reverse-Proxy f\u00fcr Frontend, <code>/api/</code> und <code>/ws</code> (kann mit <code>--no-nginx</code> \u00fcbersprungen werden)</li> </ol>"},{"location":"deployment/production/#nach-der-installation","title":"Nach der Installation","text":"<pre><code># 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</code></pre> <p>Zugriff: <code>http://&lt;Maschinen-IP&gt;</code> (oder der mit <code>--host</code> angegebene Hostname)</p>"},{"location":"deployment/production/#handbrake-modus-gpunvdec","title":"HandBrake-Modus (GPU/NVDEC)","text":"<p>Bei nicht-interaktiver Ausf\u00fchrung (Pipe von curl) wird automatisch die Standard-Version gew\u00e4hlt. F\u00fcr die GPU-Version zuerst herunterladen:</p> <pre><code>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</code></pre> <p>Das geb\u00fcndelte Binary liegt unter <code>bin/HandBrakeCLI</code> und wird nach <code>/usr/local/bin/HandBrakeCLI</code> kopiert.</p>"},{"location":"deployment/production/#manuelle-installation","title":"Manuelle Installation","text":"<p>Die folgenden Abschnitte beschreiben die einzelnen Schritte f\u00fcr manuelle oder angepasste Setups.</p>"},{"location":"deployment/production/#empfohlene-architektur","title":"Empfohlene Architektur","text":"<pre><code>Client\n -&gt; nginx (Reverse Proxy + statisches Frontend)\n -&gt; Backend API/WebSocket (Node.js, Port 3001)\n</code></pre> <p>Wichtig: Das Backend serviert im aktuellen Stand keine <code>frontend/dist</code>-Dateien automatisch.</p>"},{"location":"deployment/production/#1-frontend-builden","title":"1) Frontend builden","text":"<pre><code>cd frontend\nnpm install\nnpm run build\n</code></pre> <p>Artefakte liegen in <code>frontend/dist/</code>.</p>"},{"location":"deployment/production/#2-backend-als-systemd-service","title":"2) Backend als systemd-Service","text":"<p>Beispiel <code>/etc/systemd/system/ripster-backend.service</code>:</p> <pre><code>[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</code></pre> <p>Aktivieren:</p> <pre><code>sudo systemctl daemon-reload\nsudo systemctl enable --now ripster-backend\nsudo systemctl status ripster-backend\n</code></pre>"},{"location":"deployment/production/#3-nginx-konfigurieren","title":"3) nginx konfigurieren","text":"<p>Beispiel <code>/etc/nginx/sites-available/ripster</code>:</p> <pre><code>server {\n listen 80;\n server_name ripster.local;\n client_max_body_size 8G;\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</code></pre> <p>Aktivieren:</p> <pre><code>sudo ln -s /etc/nginx/sites-available/ripster /etc/nginx/sites-enabled/\nsudo nginx -t\nsudo systemctl reload nginx\n</code></pre> <p>Hinweis: Fuer groessere Uploads wie <code>.aax</code>-Audiobooks muss <code>client_max_body_size</code> ausreichend hoch gesetzt sein. Im mitgelieferten Beispiel sind <code>8G</code> hinterlegt.</p>"},{"location":"deployment/production/#datenbank-backup","title":"Datenbank-Backup","text":"<pre><code>sqlite3 /opt/ripster/backend/data/ripster.db \\\n \".backup '/var/backups/ripster-$(date +%Y%m%d).db'\"\n</code></pre>"},{"location":"deployment/production/#sicherheit","title":"Sicherheit","text":"<ul> <li>Ripster hat keine eingebaute Authentifizierung.</li> <li>F\u00fcr externen Zugriff mindestens Basic Auth + TLS + Netzwerksegmentierung/VPN einsetzen.</li> <li>Secrets nicht ins Repo committen (<code>.env</code>, Settings-Felder).</li> </ul>"},{"location":"getting-started/","title":"Benutzerhandbuch \u00dcberblick","text":"<p>Dieses Kapitel ist f\u00fcr den Betrieb von Ripster im Alltag geschrieben.</p>"},{"location":"getting-started/#zielgruppe","title":"Zielgruppe","text":"<ul> <li>Anwender, die Discs verarbeiten wollen</li> <li>Betreiber, die den t\u00e4glichen Ablauf stabil fahren m\u00f6chten</li> <li>Power-User, die Queue/Skripte/Cron im UI steuern m\u00f6chten</li> </ul>"},{"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":"<ol> <li>Voraussetzungen</li> <li>Installation</li> <li>Ersteinrichtung</li> <li>Erster Lauf</li> </ol>"},{"location":"getting-started/#wenn-ripster-bereits-lauft","title":"Wenn Ripster bereits l\u00e4uft","text":"<ol> <li>GUI-Seiten</li> <li>Workflows</li> <li>Bei Detailfragen: Technischer Anhang</li> </ol>"},{"location":"getting-started/configuration/","title":"Ersteinrichtung","text":"<p>Diese Seite ist die Betriebs-Checkliste vor dem ersten produktiven Lauf.</p>"},{"location":"getting-started/configuration/#ziel-der-ersteinrichtung","title":"Ziel der Ersteinrichtung","text":"<p>Vor dem ersten Job sollten f\u00fcnf Bereiche sauber gesetzt sein:</p> <ol> <li>Pfade und Templates</li> <li>Laufwerk und Disc-Erkennung</li> <li>Metadatenzugang \u00fcber TMDb</li> <li>Encode-Standards und Queue-Regeln</li> <li>optionale Automatisierung und Benachrichtigungen</li> </ol>"},{"location":"getting-started/configuration/#empfohlene-reihenfolge","title":"Empfohlene Reihenfolge","text":""},{"location":"getting-started/configuration/#1-basis-in-settings-konfiguration","title":"1. Basis in <code>Settings -&gt; Konfiguration</code>","text":"<p>Pr\u00fcfe zuerst diese Kernfelder:</p> <ul> <li>RAW- und Zielordner f\u00fcr Blu-ray, DVD, CD, Audiobooks und Converter</li> <li><code>Log Ordner</code></li> <li><code>TMDb Read Access Token</code></li> <li><code>MakeMKV Kommando</code>, <code>HandBrake Kommando</code>, <code>Mediainfo Kommando</code></li> <li><code>FFmpeg Kommando</code>, <code>FFprobe Kommando</code>, <code>cdparanoia Kommando</code>, <code>mkvmerge Kommando</code>, falls du die jeweiligen Workflows nutzt</li> </ul> <p>Danach speichern.</p>"},{"location":"getting-started/configuration/#2-pfade-und-templates-bewusst-festlegen","title":"2. Pfade und Templates bewusst festlegen","text":"<p>Wichtig f\u00fcr den Alltag:</p> <ul> <li>Film-Workflows nutzen <code>raw_dir_*</code>, <code>movie_dir_*</code> und <code>output_template_*</code></li> <li>Serien-Workflows nutzen zus\u00e4tzlich <code>raw_dir_*_series</code>, <code>series_dir_*</code> und die Episode-/Multi-Episode-Templates</li> <li>Audiobooks nutzen <code>raw_dir_audiobook</code>, <code>movie_dir_audiobook</code>, <code>audiobook_raw_template</code>, <code>output_template_audiobook</code>, <code>output_chapter_template_audiobook</code></li> <li>Converter nutzt <code>converter_raw_dir</code>, <code>converter_movie_dir</code>, <code>converter_audio_dir</code> und die beiden Converter-Templates</li> <li>Downloads nutzen <code>download_dir</code></li> </ul> <p>Wenn du auf NAS, USB oder andere Benutzer/Gruppen schreiben willst, pr\u00fcfe auch die jeweiligen <code>*_owner</code>-Felder.</p>"},{"location":"getting-started/configuration/#3-laufwerk-und-automatische-erkennung-prufen","title":"3. Laufwerk und automatische Erkennung pr\u00fcfen","text":"<p>Relevant:</p> <ul> <li><code>Laufwerksmodus</code></li> <li><code>Explizite Laufwerke</code>, falls du nicht mit Auto-Discovery arbeiten willst</li> <li><code>Automatische Disk-Erkennung</code></li> <li><code>Polling Intervall (ms)</code> im Expertenmodus</li> <li><code>Laufwerk nach Rip auswerfen</code></li> </ul> <p>Empfehlung:</p> <ul> <li>Einzelnes Standardlaufwerk: <code>auto</code></li> <li>mehrere stabile Laufwerke oder ungew\u00f6hnliche Device-Mappings: <code>Explizite Laufwerke</code></li> </ul>"},{"location":"getting-started/configuration/#4-tmdb-und-metadatenverhalten-festlegen","title":"4. TMDb und Metadatenverhalten festlegen","text":"<p>Relevant:</p> <ul> <li><code>TMDb Read Access Token</code></li> <li><code>Film-Sprache</code></li> <li><code>Fallback Sprache</code></li> <li><code>Coverart-Nachladen aktiv</code></li> <li><code>Coverart-Pr\u00fcfintervall (Stunden)</code></li> <li><code>NFO nach Encode erzeugen</code></li> </ul> <p>Diese Einstellungen wirken direkt in Metadatensuche, Serienzuordnung, Nachpflege von Covern und im finalen Output.</p>"},{"location":"getting-started/configuration/#5-encode-und-review-standards-festlegen","title":"5. Encode- und Review-Standards festlegen","text":"<p>F\u00fcr Video-Workflows besonders wichtig:</p> <ul> <li><code>Minimale Titell\u00e4nge (Minuten)</code></li> <li><code>TMDb Runtime-Abzug f\u00fcr Playlistfilter (%)</code></li> <li><code>HandBrake Preset</code> und <code>HandBrake Extra Args</code> je Medium</li> <li><code>Review Audio-Sprachen (...)</code></li> <li><code>Review UT-Sprachen (...)</code></li> <li><code>Ausgabeformat</code></li> </ul> <p>Praxis:</p> <ul> <li><code>Minimale Titell\u00e4nge</code> filtert Bonusmaterial fr\u00fch weg</li> <li><code>TMDb Runtime-Abzug ...</code> lockert bei problematischen Blu-rays die Laufzeitpr\u00fcfung der Playlist-Kandidaten</li> <li>Review-Sprachen bestimmen, welche Audio-/Untertitelspuren in der Review schon vorausgew\u00e4hlt sind</li> </ul>"},{"location":"getting-started/configuration/#6-queue-verhalten-definieren","title":"6. Queue-Verhalten definieren","text":"<p>Stelle diese vier Felder bewusst ein:</p> <ul> <li><code>Parallele Jobs</code></li> <li><code>Max. parallele Audio CD Jobs</code></li> <li><code>Max. Encodes gesamt (medienunabh\u00e4ngig)</code></li> <li><code>Audio CDs: Queue-Reihenfolge \u00fcberspringen</code></li> </ul> <p>Damit steuerst du, wie aggressiv Ripster mehrere Jobs gleichzeitig startet.</p>"},{"location":"getting-started/configuration/#7-optional-user-presets-und-standard-zuordnungen","title":"7. Optional: User-Presets und Standard-Zuordnungen","text":"<p>Unter <code>Settings -&gt; Encode-Presets</code> kannst du:</p> <ul> <li>eigene HandBrake-User-Presets anlegen</li> <li>Standard-Zuordnungen f\u00fcr <code>Blu-ray Film</code>, <code>Blu-ray Serie</code>, <code>DVD Film</code>, <code>DVD Serie</code> setzen</li> </ul> <p>Diese Defaults wirken sp\u00e4ter in der Review automatisch vorbef\u00fcllend.</p>"},{"location":"getting-started/configuration/#8-optional-benachrichtigungen","title":"8. Optional: Benachrichtigungen","text":"<p>Pr\u00fcfe:</p> <ul> <li><code>PushOver aktiviert</code></li> <li>Token/User/optional Device</li> <li>Event-Toggles wie <code>Bei manueller Auswahl senden</code>, <code>Bei Rip-Start senden</code>, <code>Bei Erfolg senden</code></li> </ul> <p>Danach in <code>Settings</code> den Button <code>PushOver Test</code> ausf\u00fchren.</p>"},{"location":"getting-started/configuration/#9-optional-automatisierung","title":"9. Optional: Automatisierung","text":"<p>Erst wenn die Grundkonfiguration stabil ist:</p> <ol> <li>Skripte anlegen und testen</li> <li>Skriptketten aufbauen</li> <li>Cronjobs aktivieren</li> </ol>"},{"location":"getting-started/configuration/#funktionsprufung","title":"Funktionspr\u00fcfung","text":"<p>Ein sinnvoller Kurztest:</p> <ol> <li>Disc in <code>Ripper</code> erkennen lassen</li> <li><code>Analyse starten</code></li> <li>TMDb-Metadaten \u00fcbernehmen</li> <li>ggf. Playlist-/RAW-Entscheidung durchlaufen</li> <li>bis <code>Bereit zum Encodieren</code> kommen</li> <li>Encode starten</li> <li>Ergebnis in <code>Historie</code> pr\u00fcfen</li> </ol>"},{"location":"getting-started/configuration/#typische-konfigurationsfehler","title":"Typische Konfigurationsfehler","text":"Symptom H\u00e4ufige Ursache Disc wird nicht erkannt Laufwerksmodus oder Auto-Erkennung passt nicht Playlist-Auswahl wirkt unplausibel <code>Minimale Titell\u00e4nge</code> oder <code>TMDb Runtime-Abzug ...</code> ist zu streng/zu locker falsche Spuren sind in der Review vorausgew\u00e4hlt Review-Sprachfilter oder HandBrake-Args greifen unerwartet Ausgabe landet am falschen Ort Profilpfade oder Templates greifen \u00fcber Fallback Queue verh\u00e4lt sich unerwartet <code>Parallele Jobs</code>, CD-Limit und Gesamtlimit widersprechen sich"},{"location":"getting-started/configuration/#weiter","title":"Weiter","text":"<ul> <li>Erster Lauf</li> <li>GUI-Seiten</li> <li>Workflows aus Nutzersicht</li> <li>Alle Einstellungen</li> </ul>"},{"location":"getting-started/installation/","title":"Installation","text":"<p>Die empfohlene Installation startet immer \u00fcber <code>setup.sh</code>. <code>setup.sh</code> l\u00e4dt das passende <code>install.sh</code> aus dem gew\u00fcnschten Branch und \u00fcbergibt alle weiteren Parameter unver\u00e4ndert an den eigentlichen Installer.</p> <p>Wichtig:</p> <ul> <li>Standard-Einstieg: <code>setup.sh</code></li> <li>kein <code>curl | bash</code></li> <li>du musst die Tools nicht manuell vorinstallieren, sofern du sie nicht bewusst mit <code>--no-*</code> ausl\u00e4sst</li> </ul>"},{"location":"getting-started/installation/#voraussetzungen","title":"Voraussetzungen","text":"<ul> <li>unterst\u00fctztes Linux-System</li> <li>Root-Rechte oder <code>sudo</code></li> <li>Internetzugang w\u00e4hrend der Installation</li> </ul> <p>Der Installer erkennt aktuell:</p> <ul> <li>Debian</li> <li>Ubuntu</li> <li>Linux Mint</li> <li>Pop!_OS</li> </ul>"},{"location":"getting-started/installation/#standardinstallation","title":"Standardinstallation","text":"<pre><code>wget -qO setup.sh https://raw.githubusercontent.com/Mboehmlaender/ripster/main/setup.sh\nbash setup.sh\n</code></pre> <p>Ohne <code>--branch</code> fragt <code>setup.sh</code> interaktiv nach dem gew\u00fcnschten Branch.</p> <p>Die typischen Branches sind:</p> <ul> <li><code>main</code>: stabiles Release</li> <li><code>dev</code>: aktueller Entwicklungsstand</li> </ul>"},{"location":"getting-started/installation/#installation-mit-branch-oder-optionen","title":"Installation mit Branch oder Optionen","text":"<p>Beispiele:</p> <pre><code>bash setup.sh --branch main\nbash setup.sh --branch dev\nbash setup.sh --branch dev --dir /opt/ripster --user ripster --port 3001 --host 192.168.1.10\n</code></pre> <p><code>setup.sh</code> wertet selbst nur <code>--branch</code> aus. Alles andere \u00fcbernimmt <code>install.sh</code>.</p>"},{"location":"getting-started/installation/#wichtige-optionen-von-installsh","title":"Wichtige Optionen von <code>install.sh</code>","text":"Option Default Zweck <code>--branch &lt;branch&gt;</code> <code>dev</code> installiert genau diesen Git-Branch <code>--dir &lt;pfad&gt;</code> <code>/opt/ripster</code> Installationsverzeichnis <code>--user &lt;benutzer&gt;</code> <code>ripster</code> Systembenutzer f\u00fcr den Dienst <code>--port &lt;port&gt;</code> <code>3001</code> Backend-Port <code>--host &lt;hostname|ip&gt;</code> automatisch ermittelte Host-IP Hostname/IP f\u00fcr Webzugriff und CORS <code>--no-makemkv</code> aus MakeMKV nicht installieren <code>--no-handbrake</code> aus HandBrake nicht installieren <code>--no-nginx</code> aus nginx-Setup \u00fcberspringen <code>--no-system-deps</code> aus Systemabh\u00e4ngigkeiten nicht nachinstallieren <code>--reinstall</code> aus bestehende Installation aktualisieren"},{"location":"getting-started/installation/#was-der-installer-einrichtet","title":"Was der Installer einrichtet","text":"<p>Typischer Ablauf:</p> <ol> <li>Betriebssystem, Root-Rechte und Host pr\u00fcfen</li> <li>Systemabh\u00e4ngigkeiten installieren</li> <li>Node.js 20 sicherstellen</li> <li>optional MakeMKV installieren</li> <li>optional HandBrakeCLI installieren</li> <li>optional nginx konfigurieren</li> <li>Repository nach <code>--dir</code> klonen oder aktualisieren</li> <li>Backend-/Frontend-Abh\u00e4ngigkeiten installieren</li> <li>Frontend bauen</li> <li><code>backend/.env</code> und Laufzeitverzeichnisse vorbereiten</li> <li><code>ripster-backend.service</code> anlegen und starten</li> </ol>"},{"location":"getting-started/installation/#dienst-prufen","title":"Dienst pr\u00fcfen","text":"<pre><code>sudo systemctl status ripster-backend\n</code></pre> <p>Typische Aufrufe im Betrieb:</p> <pre><code>sudo journalctl -u ripster-backend -f\nsudo systemctl restart ripster-backend\n</code></pre>"},{"location":"getting-started/installation/#update-einer-bestehenden-installation","title":"Update einer bestehenden Installation","text":"<p>Standard:</p> <pre><code>sudo bash /opt/ripster/install.sh --reinstall\n</code></pre> <p>Wenn die Installation mit abweichenden Kernparametern eingerichtet wurde, dieselben Parameter wieder mitgeben:</p> <pre><code>sudo bash /opt/ripster/install.sh --reinstall --dir /opt/ripster --user ripster --port 3001 --host 192.168.1.10\n</code></pre> <p>Alternativ kannst du auch erneut \u00fcber <code>setup.sh</code> gehen:</p> <pre><code>sudo bash /opt/ripster/setup.sh --reinstall\n</code></pre> <p><code>--reinstall</code> aktualisiert die Installation, beh\u00e4lt aber die persistenten Daten der bestehenden Instanz.</p>"},{"location":"getting-started/installation/#danach-weiter","title":"Danach weiter","text":"<ol> <li>Ersteinrichtung</li> <li>Erster Lauf</li> </ol>"},{"location":"getting-started/prerequisites/","title":"Voraussetzungen","text":"<p>Die Voraussetzungen h\u00e4ngen davon ab, ob du Ripster produktiv installieren oder lokal entwickeln willst.</p>"},{"location":"getting-started/prerequisites/#produktionsbetrieb-mit-setupsh","title":"Produktionsbetrieb mit <code>setup.sh</code>","text":"<p>F\u00fcr den normalen Betrieb brauchst du nur die Basisvoraussetzungen. Die eigentlichen Tools werden vom Installer eingerichtet, sofern du sie nicht bewusst mit <code>--no-*</code> \u00fcberspringst.</p>"},{"location":"getting-started/prerequisites/#pflicht","title":"Pflicht","text":"<ul> <li>unterst\u00fctztes Linux-System</li> <li>Root-Rechte oder <code>sudo</code></li> <li>Internetzugang w\u00e4hrend der Installation</li> <li>optisches Laufwerk, wenn du Disc-Workflows nutzen willst</li> </ul> <p>Der Installer unterst\u00fctzt aktuell:</p> <ul> <li>Debian</li> <li>Ubuntu</li> <li>Linux Mint</li> <li>Pop!_OS</li> </ul> <p>Standard-Einstieg:</p> <pre><code>wget -qO setup.sh https://raw.githubusercontent.com/Mboehmlaender/ripster/main/setup.sh\nbash setup.sh\n</code></pre>"},{"location":"getting-started/prerequisites/#laufwerk-kurz-prufen","title":"Laufwerk kurz pr\u00fcfen","text":"<pre><code>ls /dev/sr*\nlsblk | grep rom\n</code></pre>"},{"location":"getting-started/prerequisites/#optional-vorab","title":"Optional vorab","text":"<ul> <li>TMDb Read Access Token f\u00fcr Film-/Serien-Metadaten</li> <li>PushOver-Zugangsdaten f\u00fcr Benachrichtigungen</li> </ul> <p>Beides kann auch erst nach der Installation in <code>Settings</code> gesetzt werden.</p>"},{"location":"getting-started/prerequisites/#entwicklungsmodus","title":"Entwicklungsmodus","text":"<p>Wenn du lokal entwickelst (<code>./start.sh</code>, <code>npm run dev</code>), gelten zus\u00e4tzliche Voraussetzungen:</p> <ul> <li>Node.js <code>&gt;= 20.19.0</code></li> <li><code>makemkvcon</code>, <code>HandBrakeCLI</code>, <code>mediainfo</code> im <code>PATH</code></li> </ul> <p>Details: Entwicklungsumgebung</p>"},{"location":"getting-started/prerequisites/#abschluss-checkliste","title":"Abschluss-Checkliste","text":"<ul> <li>[ ] Linux + Root/Sudo + Internet vorhanden</li> <li>[ ] optisches Laufwerk vorhanden, falls Disc-Ripping genutzt werden soll</li> <li>[ ] TMDb/PushOver-Zugangsdaten liegen bereit, falls diese Funktionen sofort genutzt werden sollen</li> <li>[ ] im Dev-Modus zus\u00e4tzlich Node.js und CLI-Tools lokal verf\u00fcgbar</li> </ul>"},{"location":"getting-started/quickstart/","title":"Erster Lauf","text":"<p>Dieser Ablauf f\u00fchrt einen typischen Disc-Job von Erkennung bis fertiger Datei durch.</p>"},{"location":"getting-started/quickstart/#1-disc-erkennen","title":"1. Disc erkennen","text":"<ol> <li><code>Ripper</code> \u00f6ffnen</li> <li>Disc einlegen</li> <li>auf <code>Medium erkannt</code> warten</li> </ol> <p>Pr\u00fcfen:</p> <ul> <li><code>Disk-Information</code> zeigt Device, Label und Laufwerksstatus</li> <li>falls nicht: <code>Laufwerk neu lesen</code></li> </ul> <p>Relevante Settings:</p> <ul> <li><code>Laufwerksmodus</code></li> <li><code>Automatische Disk-Erkennung</code></li> <li><code>Polling Intervall (ms)</code></li> </ul>"},{"location":"getting-started/quickstart/#2-analyse-starten","title":"2. Analyse starten","text":"<p>Aktion:</p> <ul> <li><code>Analyse starten</code></li> </ul> <p>Erwartung:</p> <ul> <li>Status <code>Analyse</code></li> <li>danach der Metadaten-Dialog</li> </ul> <p>Relevantes Setting:</p> <ul> <li><code>Minimale Titell\u00e4nge (Minuten)</code> beeinflusst bereits, welche Titel/Playlists Ripster sp\u00e4ter als relevant betrachtet</li> </ul>"},{"location":"getting-started/quickstart/#3-metadaten-in-tmdb-bestatigen","title":"3. Metadaten in TMDb best\u00e4tigen","text":"<p>Im Dialog:</p> <ol> <li>Treffer suchen oder filtern</li> <li>Film oder Serie ausw\u00e4hlen</li> <li>bei Serien zus\u00e4tzlich <code>Disc-Nummer</code> setzen</li> <li><code>Auswahl \u00fcbernehmen</code></li> </ol> <p>M\u00f6gliche Abzweigungen:</p> <ul> <li>Duplikatfilm: <code>\u00dcbernahme erzwingen</code> oder <code>Multipart movie</code></li> <li>vorhandenes RAW: Entscheidungsdialog <code>weiterverwenden</code> oder <code>neu rippen</code></li> </ul> <p>Relevante Settings:</p> <ul> <li><code>TMDb Read Access Token</code></li> <li><code>Film-Sprache</code></li> <li><code>Fallback Sprache</code></li> </ul>"},{"location":"getting-started/quickstart/#4-raw-und-playlist-entscheidungen","title":"4. RAW- und Playlist-Entscheidungen","text":"<p>Je nach Disc-Situation geht es jetzt unterschiedlich weiter.</p>"},{"location":"getting-started/quickstart/#normalfall","title":"Normalfall","text":"<p><code>Startbereit</code> -&gt; <code>Rippen</code> -&gt; <code>Mediainfo-Pr\u00fcfung</code></p>"},{"location":"getting-started/quickstart/#vorhandenes-raw","title":"Vorhandenes RAW","text":"<p>Kein neuer Rip, sondern erst eine Entscheidung:</p> <ul> <li>vorhandenes RAW weiterverwenden</li> <li>RAW l\u00f6schen und Rip neu starten</li> <li>bei passenden Film-Konstellationen optional Multipart mit Orphan-RAW</li> </ul>"},{"location":"getting-started/quickstart/#playlist-oder-titelauswahl-erforderlich","title":"Playlist- oder Titelauswahl erforderlich","text":"<p>Bei bestimmten Blu-ray-/DVD-F\u00e4llen erscheint <code>Warte auf Auswahl</code>.</p> <p>Dann best\u00e4tigst du:</p> <ul> <li>eine Playlist</li> <li>oder einen/mehrere HandBrake-Titel</li> </ul> <p>Relevante Settings:</p> <ul> <li><code>Minimale Titell\u00e4nge (Minuten)</code></li> <li><code>TMDb Runtime-Abzug f\u00fcr Playlistfilter (%)</code></li> </ul>"},{"location":"getting-started/quickstart/#5-encode-review-abschlieen","title":"5. Encode-Review abschlie\u00dfen","text":"<p>Bei <code>Bereit zum Encodieren</code> pr\u00fcfst du:</p> <ul> <li>Titelwahl</li> <li>Audio-Spuren</li> <li>Untertitel</li> <li>User-Preset oder HandBrake-Preset</li> <li>Pre-/Post-Encode-Skripte und Ketten</li> </ul> <p>Dann:</p> <ul> <li><code>Encoding starten</code></li> </ul> <p>Relevante Settings:</p> <ul> <li><code>HandBrake Preset</code> und <code>HandBrake Extra Args</code> je Medium</li> <li><code>Review Audio-Sprachen (...)</code></li> <li><code>Review UT-Sprachen (...)</code></li> <li><code>Ausgabeformat</code></li> <li>Standard-Zuordnungen unter <code>Settings -&gt; Encode-Presets</code></li> </ul>"},{"location":"getting-started/quickstart/#6-encoding-uberwachen","title":"6. Encoding \u00fcberwachen","text":"<p>W\u00e4hrend <code>Encodieren</code>:</p> <ul> <li>Fortschritt/ETA im Ripper</li> <li>Queue-Status beobachten</li> <li>bei Bedarf <code>Hardware</code>-Ansicht \u00f6ffnen</li> </ul> <p>Relevante Settings:</p> <ul> <li><code>Parallele Jobs</code></li> <li><code>Max. parallele Audio CD Jobs</code></li> <li><code>Max. Encodes gesamt (medienunabh\u00e4ngig)</code></li> <li><code>Hardware Monitoring aktiviert</code></li> <li><code>Hardware Monitoring Intervall (ms)</code></li> </ul>"},{"location":"getting-started/quickstart/#7-ergebnis-verifizieren","title":"7. Ergebnis verifizieren","text":"<p>Nach <code>Fertig</code>:</p> <ol> <li><code>Historie</code> \u00f6ffnen</li> <li>Jobdetail pr\u00fcfen</li> <li>Output-Pfad und Log kontrollieren</li> </ol> <p>Kontrollpunkte:</p> <ul> <li>finale Datei liegt am erwarteten Template-Pfad</li> <li>RAW-Ordner ist finalisiert</li> <li>optional <code>.nfo</code> wurde erzeugt, falls aktiviert</li> </ul> <p>Relevante Settings:</p> <ul> <li><code>output_template_*</code></li> <li><code>series_dir_*</code> und Serien-Templates</li> <li><code>generate_nfo_after_encode</code></li> </ul>"},{"location":"getting-started/quickstart/#8-typische-folgeaktionen","title":"8. Typische Folgeaktionen","text":"<ul> <li>falsche TMDb-Zuordnung: <code>TMDb neu zuweisen</code></li> <li>andere Trackauswahl: <code>Review neu starten</code></li> <li>erneuter Encode aus RAW: <code>RAW neu encodieren</code></li> <li>gleicher Plan erneut: <code>Encode neu starten</code></li> <li>Rip erneut versuchen: <code>Retry Rippen</code></li> </ul>"},{"location":"gui/","title":"GUI-Seiten","text":"<p>Dieses Kapitel ist das Bedienhandbuch f\u00fcr die Oberfl\u00e4chen im Alltag.</p>"},{"location":"gui/#seitenuberblick","title":"Seiten\u00fcberblick","text":"Seite Rolle im Betrieb Typischer Einsatz Ripper Live-Steuerung der Disc-Pipeline Disc erkennen, Analyse starten, Entscheidungen treffen, Queue steuern Hardware Detailansicht f\u00fcr Live-Monitoring CPU/RAM/GPU und Verlauf pr\u00fcfen Audiobooks AAX-Spezialflow Upload, Kapitelpr\u00fcfung und Encode von Audiobooks Settings Konfiguration und Automatisierung Pfade, Tools, Queue, Presets, Skripte, Cron Historie Nachbearbeitung und Kontrolle Logs, Re-Encode, TMDb-Neuzuordnung, L\u00f6schvorschau Converter dateibasierte Konvertierung Video/Audio/ISO ohne Disc-Rip verarbeiten Downloads ZIP-Exports RAW/Output aus der Historie bereitstellen Database (Expert) Recovery-Sicht orphan RAW finden, pr\u00fcfen und importieren TMDb Migration Sonderseite f\u00fcr Altbest\u00e4nde alte Jobs gesammelt auf TMDb umstellen"},{"location":"gui/#empfohlener-tagesablauf","title":"Empfohlener Tagesablauf","text":"<ol> <li><code>Ripper</code>, <code>Converter</code> oder <code>Audiobooks</code>: neue Arbeit starten</li> <li><code>Historie</code>: Ergebnisse kontrollieren und ggf. nachbearbeiten</li> <li><code>Downloads</code>: Artefakte f\u00fcr externe \u00dcbergabe vorbereiten</li> <li><code>Settings</code>: Regeln, Presets oder Limits nur kontrolliert anpassen</li> <li><code>Hardware</code>: bei Lastspitzen oder Batch-L\u00e4ufen den Verlauf pr\u00fcfen</li> </ol>"},{"location":"gui/#navigation","title":"Navigation","text":"<p>Direkt in der Top-Navigation:</p> <ul> <li><code>Ripper</code></li> <li><code>Converter</code></li> <li><code>Audiobooks</code></li> <li><code>Settings</code></li> <li><code>Historie</code></li> <li><code>Downloads</code></li> </ul> <p>Zusatzansichten:</p> <ul> <li><code>Hardware</code> unter <code>/hardware</code></li> <li><code>Database</code> unter <code>/database</code> und im Expertenmodus zus\u00e4tzlich in der Navigation</li> <li><code>TMDb Migration</code> unter <code>/tmdb-migration</code> als Direktlink</li> </ul>"},{"location":"gui/audiobooks/","title":"Audiobooks","text":"<p>Die Seite <code>Audiobooks</code> ist der spezialisierte Workflow f\u00fcr Audible-<code>*.aax</code>-Dateien.</p>"},{"location":"gui/audiobooks/#seitenstruktur","title":"Seitenstruktur","text":"<p>Die Oberfl\u00e4che besteht aus zwei Hauptbereichen:</p> <ol> <li><code>Audiobooks Upload</code></li> <li><code>Audiobook Jobs</code></li> </ol>"},{"location":"gui/audiobooks/#1-audiobooks-upload","title":"1. Audiobooks Upload","text":"<p>Der Upload akzeptiert ausschlie\u00dflich <code>.aax</code>.</p>"},{"location":"gui/audiobooks/#bedienung","title":"Bedienung","text":"<ul> <li>Datei ausw\u00e4hlen oder per Drag-and-Drop ablegen</li> <li>Upload starten</li> <li>Auswahl entfernen oder laufenden Upload abbrechen</li> </ul> <p>W\u00e4hrend des Uploads zeigt die UI:</p> <ul> <li>Prozentfortschritt</li> <li>\u00fcbertragene und gesamte Bytes</li> <li>Statusmeldung</li> </ul>"},{"location":"gui/audiobooks/#ablauf-nach-erfolgreichem-upload","title":"Ablauf nach erfolgreichem Upload","text":"<ul> <li>die AAX-Datei wird gepr\u00fcft</li> <li>Ripster versucht Metadata, Kapitel und Activation-Bytes-Kontext aufzubauen</li> <li>ein Audiobook-Job wird angelegt</li> <li>der Job startet direkt oder wird in die Queue eingereiht</li> </ul>"},{"location":"gui/audiobooks/#2-audiobook-jobs","title":"2. Audiobook Jobs","text":"<p>Die Seite zeigt aktive Jobs. Abgeschlossene Jobs findest du in der <code>Historie</code>.</p> <p>Ein Job kann eingeklappt oder ausgeklappt werden und zeigt:</p> <ul> <li>Titel, Autor, Sprecher, Jahr</li> <li>Kapitelanzahl</li> <li>Fortschritt und ETA</li> <li>bei Split-Ausgabe den Kapitelstatus</li> </ul>"},{"location":"gui/audiobooks/#konfigurierbare-job-parameter","title":"Konfigurierbare Job-Parameter","text":"<p>Im ausgeklappten Job kannst du setzen:</p> <ul> <li>Ausgabeformat <code>m4b</code>, <code>mp3</code> oder <code>flac</code></li> <li>formatspezifische Optionen</li> <li>Kapitelnamen</li> <li>Pre-Encode-Skripte und -Ketten</li> <li>Post-Encode-Skripte und -Ketten</li> </ul>"},{"location":"gui/audiobooks/#formatverhalten","title":"Formatverhalten","text":"<ul> <li><code>m4b</code>: eine Datei mit Kapitelmarken</li> <li><code>mp3</code>: eine Datei pro Kapitel</li> <li><code>flac</code>: eine Datei pro Kapitel</li> </ul> <p>Wenn du <code>mp3</code> oder <code>flac</code> w\u00e4hlst, zeigt die UI zus\u00e4tzlich eine Kapitel-Status-Tabelle.</p>"},{"location":"gui/audiobooks/#activation-bytes","title":"Activation Bytes","text":"<p>Wenn Ripster f\u00fcr eine Datei keine Activation Bytes verwenden kann, wird im Workflow eine manuelle Eingabe n\u00f6tig.</p> <p>Wichtig:</p> <ul> <li>die Bytes werden lokal gecacht</li> <li>derselbe AAX-Hash muss dann sp\u00e4ter nicht erneut manuell eingegeben werden</li> <li>der Expertenblock in <code>Settings</code> zeigt bekannte Cache-Eintr\u00e4ge an</li> </ul>"},{"location":"gui/audiobooks/#relevante-settings","title":"Relevante Settings","text":"<ul> <li><code>raw_dir_audiobook</code></li> <li><code>movie_dir_audiobook</code></li> <li><code>raw_dir_audiobook_owner</code></li> <li><code>movie_dir_audiobook_owner</code></li> <li><code>audiobook_raw_template</code></li> <li><code>output_template_audiobook</code></li> <li><code>output_chapter_template_audiobook</code></li> <li><code>ffprobe_command</code></li> <li><code>ffmpeg_command</code></li> </ul>"},{"location":"gui/audiobooks/#so-wirken-die-settings-im-alltag","title":"So wirken die Settings im Alltag","text":"<ul> <li><code>audiobook_raw_template</code> bestimmt den Namen des AAX-RAW-Ordners</li> <li><code>output_template_audiobook</code> bestimmt die Einzeldatei f\u00fcr <code>m4b</code></li> <li><code>output_chapter_template_audiobook</code> bestimmt Zielstruktur und Dateinamen f\u00fcr <code>mp3</code>/<code>flac</code></li> <li><code>ffprobe_command</code> liest Kapitel und Metadaten</li> <li><code>ffmpeg_command</code> erzeugt die finalen Dateien</li> </ul>"},{"location":"gui/audiobooks/#queue-und-laufzeit","title":"Queue und Laufzeit","text":"<p>Audiobook-Jobs nutzen dieselbe globale Pipeline wie die anderen Bereiche.</p> <p>Relevante Settings:</p> <ul> <li><code>Parallele Jobs</code></li> <li><code>Max. Encodes gesamt (medienunabh\u00e4ngig)</code></li> </ul>"},{"location":"gui/audiobooks/#typische-fehlerbilder","title":"Typische Fehlerbilder","text":"<ul> <li>Upload wird abgelehnt: Datei ist keine g\u00fcltige <code>*.aax</code></li> <li>Analyse schl\u00e4gt fehl: <code>ffprobe</code> ist nicht erreichbar</li> <li>Encode schl\u00e4gt fehl: <code>ffmpeg</code> ist nicht erreichbar</li> <li>Ausgabe landet unerwartet: Templates oder Zielpfade passen nicht zur gew\u00fcnschten Struktur</li> </ul>"},{"location":"gui/converter/","title":"Converter","text":"<p>Die Seite <code>Converter</code> verarbeitet vorhandene Dateien ohne Laufwerks-Rip. Sie ist f\u00fcr Video-, Audio- und ISO-Dateien gedacht, die bereits auf dem System liegen oder hochgeladen werden.</p>"},{"location":"gui/converter/#betriebsmodell","title":"Betriebsmodell","text":"<p>Der Converter arbeitet auf dem Eingangspfad <code>converter_raw_dir</code>.</p> <p>Dort landen:</p> <ul> <li>Uploads</li> <li>neu angelegte Ordner</li> <li>umbenannte oder verschobene Dateien</li> <li>alle Dateien, aus denen sp\u00e4ter Converter-Jobs entstehen</li> </ul> <p>Wichtig:</p> <ul> <li>Upload erzeugt nicht automatisch einen Job</li> <li>die Joberstellung erfolgt bewusst aus der Explorer-Auswahl</li> </ul>"},{"location":"gui/converter/#datei-explorer","title":"Datei-Explorer","text":"<p>Der Explorer zeigt den kompletten Baum unter <code>converter_raw_dir</code>.</p> <p>Aktionen:</p> Aktion Wirkung <code>Upload</code> schreibt neue Dateien in den Converter-RAW-Baum <code>Ordner erstellen</code> legt Unterordner an <code>Umbenennen</code> benennt Datei oder Ordner um <code>Verschieben</code> verschiebt Eintr\u00e4ge innerhalb des Raw-Baums <code>L\u00f6schen</code> entfernt Datei oder Ordner dauerhaft <code>Scannen</code> synchronisiert Dateisystem und Converter-Datenbank"},{"location":"gui/converter/#upload-und-scan-regeln","title":"Upload- und Scan-Regeln","text":"<ul> <li>Dateiendungen m\u00fcssen in <code>Erlaubte Datei-Endungen</code> enthalten sein</li> <li>neue Dateien erscheinen sofort nach manuellem Scan</li> <li>mit Polling auch automatisch</li> </ul> <p>Relevante Settings:</p> <ul> <li><code>Erlaubte Datei-Endungen</code></li> <li><code>Auto-Scan (Polling)</code></li> <li><code>Polling-Intervall (Sekunden)</code></li> </ul>"},{"location":"gui/converter/#joberstellung-aus-explorer-auswahl","title":"Joberstellung aus Explorer-Auswahl","text":"<p>Es gibt zwei Audio-Strategien:</p> <ol> <li><code>Ein Job pro Datei</code></li> <li><code>Gemeinsamer Job (Audio)</code></li> </ol> <p>Verhalten:</p> <ul> <li>Video und ISO werden immer als Einzeljobs angelegt</li> <li>Audio kann als gemeinsamer Album-/Ordner-Job erzeugt werden</li> </ul> <p>Shared-Audio-Job:</p> <ul> <li>h\u00e4lt mehrere <code>inputPaths</code></li> <li>kann vor dem Start erweitert oder reduziert werden</li> </ul>"},{"location":"gui/converter/#job-konfiguration","title":"Job-Konfiguration","text":"<p>Vor dem Start je Job einstellbar:</p> <ul> <li><code>converterMediaType</code></li> <li><code>outputFormat</code></li> <li>Metadaten</li> <li>Track-/Titelwahl bei Video/ISO</li> <li>User-Preset und HandBrake-Preset bei Video</li> <li>Pre-/Post-Encode-Skripte und Ketten</li> </ul> <p>Spezifika:</p> <ul> <li>Video/ISO durchlaufen eine Review \u00e4hnlich zum Disc-Flow</li> <li>Audio wird direkt \u00fcber Format und Audio-Optionen konfiguriert</li> </ul>"},{"location":"gui/converter/#ausgabe-pfade","title":"Ausgabe-Pfade","text":""},{"location":"gui/converter/#video-iso","title":"Video / ISO","text":"<ul> <li>Zielordner: <code>converter_movie_dir</code></li> <li>Dateiname: <code>Output-Template (Video)</code></li> <li>Endung: aus dem gew\u00e4hlten Ausgabeformat</li> </ul>"},{"location":"gui/converter/#audio","title":"Audio","text":"<ul> <li>Zielordner: <code>converter_audio_dir</code></li> <li>Dateiname/Ordner: <code>Output-Template (Audio)</code></li> <li>bei Shared- oder Folder-Jobs entsteht eine Ordnerstruktur mit mehreren Track-Dateien</li> </ul> <p>Relevante Settings:</p> <ul> <li><code>converter_movie_dir</code></li> <li><code>converter_audio_dir</code></li> <li><code>converter_output_template_video</code></li> <li><code>converter_output_template_audio</code></li> <li><code>converter_movie_dir_owner</code></li> <li><code>converter_audio_dir_owner</code></li> </ul>"},{"location":"gui/converter/#queue-und-start","title":"Queue und Start","text":"<p>Converter-Jobs laufen \u00fcber dieselbe globale Pipeline-Queue wie Ripper und Audiobooks.</p> <p>Das bedeutet:</p> <ul> <li>sofortiger Start, wenn Limits frei sind</li> <li>sonst Einreihung in die Warteschlange</li> </ul> <p>Relevante Settings:</p> <ul> <li><code>Parallele Jobs</code></li> <li><code>Max. Encodes gesamt (medienunabh\u00e4ngig)</code></li> </ul>"},{"location":"gui/converter/#typische-einsatzfalle","title":"Typische Einsatzf\u00e4lle","text":"<ul> <li>vorhandene MKV/MP4-Dateien mit neuem Preset encodieren</li> <li>ISO-Dateien in einen Video-Workflow \u00fcberf\u00fchren</li> <li>Musikdateien gesammelt in einen Audio-Ordner-Job packen</li> <li>Medien auf anderem Storage per Upload oder Dateibaum vorbereiten</li> </ul>"},{"location":"gui/converter/#abgrenzung-zu-audiobooks","title":"Abgrenzung zu Audiobooks","text":"<ul> <li><code>Converter</code>: beliebige Audio-, Video- und ISO-Dateien</li> <li><code>Audiobooks</code>: spezialisierter AAX-Workflow mit Activation Bytes, Kapitelmetadaten und Kapiteltemplates</li> </ul>"},{"location":"gui/database/","title":"Database (Expert)","text":"<p><code>/database</code> ist die Recovery- und Expertensicht f\u00fcr F\u00e4lle, in denen Dateisystem und Historie nicht mehr sauber zusammenpassen.</p>"},{"location":"gui/database/#zugriff","title":"Zugriff","text":"<ul> <li>direkte Route: <code>/database</code></li> <li>nicht Teil der Standardnavigation</li> </ul>"},{"location":"gui/database/#bereich-gefundene-raw-eintrage","title":"Bereich <code>Gefundene RAW-Eintr\u00e4ge</code>","text":"<p>Dieser Bereich listet RAW-Verzeichnisse ohne zugeordneten Historie-Job.</p> <p>Aktionen:</p> <ul> <li><code>RAW pr\u00fcfen</code>: scannt konfigurierte RAW-Wurzeln</li> <li><code>Job anlegen</code>: erstellt aus einem orphan RAW einen neuen Historie-Job</li> </ul>"},{"location":"gui/database/#was-bei-job-anlegen-passiert","title":"Was bei <code>Job anlegen</code> passiert","text":"<ul> <li>RAW-Pfad wird als Importquelle registriert</li> <li>Job wird in die Historie geschrieben</li> <li>anschlie\u00dfende Analyse l\u00e4uft als RAW-basierter Einstieg (ohne klassischen Disc-Read)</li> </ul> <p>Typischer Einsatz:</p> <ul> <li>manuelle Dateioperationen au\u00dferhalb der UI</li> <li>Migrationen</li> <li>Wiederherstellung nach abgebrochenen L\u00e4ufen</li> </ul>"},{"location":"gui/database/#sicherheits-und-betriebsregeln","title":"Sicherheits- und Betriebsregeln","text":"<ul> <li>Aktionen wirken direkt auf produktive Historie/Dateipfade.</li> <li>Vor Import oder L\u00f6schung immer Pfad und Ziel pr\u00fcfen.</li> <li>Diese Seite nur f\u00fcr Recovery-Szenarien nutzen, nicht f\u00fcr normalen Tagesbetrieb.</li> </ul>"},{"location":"gui/downloads/","title":"Downloads","text":"<p>Auf <code>Downloads</code> werden ZIP-Archive f\u00fcr Historie-Artefakte erstellt und bereitgestellt.</p>"},{"location":"gui/downloads/#was-heruntergeladen-werden-kann","title":"Was heruntergeladen werden kann","text":"<p>Ein Download-Eintrag referenziert immer einen Historie-Job und genau ein Ziel:</p> <ul> <li><code>RAW</code></li> <li><code>Output</code></li> </ul> <p>Erzeugt wird ein ZIP-Archiv im Download-Verzeichnis des Backends.</p>"},{"location":"gui/downloads/#statusmodell","title":"Statusmodell","text":"Status Bedeutung <code>queued</code> Eintrag erstellt, wartet auf Verarbeitung <code>processing</code> ZIP wird gerade gebaut <code>ready</code> Archiv fertig, Download-Link aktiv <code>failed</code> Erzeugung oder Zugriff fehlgeschlagen"},{"location":"gui/downloads/#eintrag-anlegen","title":"Eintrag anlegen","text":"<p>Startpunkt ist die <code>Historie</code>:</p> <ol> <li>Job \u00f6ffnen.</li> <li>Download einreihen.</li> <li>Ziel (<code>RAW</code> oder <code>Output</code>) w\u00e4hlen.</li> <li>Status in <code>Downloads</code> verfolgen.</li> </ol>"},{"location":"gui/downloads/#wichtige-laufzeitdetails","title":"Wichtige Laufzeitdetails","text":"<ul> <li>Wenn bereits ein passendes, aktuelles Archiv existiert, kann der Eintrag wiederverwendet werden.</li> <li>Nach Backend-Neustart werden unterbrochene <code>queued</code>/<code>processing</code>-Eintr\u00e4ge gepr\u00fcft und fortgesetzt.</li> <li>Fehlt eine erwartete ZIP-Datei bei <code>ready</code>, wird der Eintrag auf <code>failed</code> gesetzt.</li> </ul>"},{"location":"gui/downloads/#download-auslosen","title":"Download ausl\u00f6sen","text":"<p>Bei Status <code>ready</code>:</p> <ul> <li>Download-Button l\u00e4dt die ZIP direkt aus <code>/api/downloads/:id/file</code>.</li> </ul>"},{"location":"gui/downloads/#eintrage-entfernen","title":"Eintr\u00e4ge entfernen","text":"<p><code>L\u00f6schen</code> entfernt:</p> <ul> <li>Queue-Metadaten</li> <li>zugeh\u00f6rige Archivdatei</li> </ul> <p>Nicht erlaubt:</p> <ul> <li>L\u00f6schen w\u00e4hrend <code>queued</code>/<code>processing</code></li> </ul>"},{"location":"gui/downloads/#echtzeitaktualisierung","title":"Echtzeitaktualisierung","text":"<p>Die Seite reagiert auf <code>DOWNLOADS_UPDATED</code> per WebSocket. Dadurch sind Statuswechsel ohne Reload sichtbar.</p>"},{"location":"gui/hardware/","title":"Hardware","text":"<p>Die Seite <code>Hardware</code> ist die ausf\u00fchrliche Detailansicht f\u00fcr das Live-Monitoring aus dem <code>Ripper</code>.</p>"},{"location":"gui/hardware/#was-die-seite-zeigt","title":"Was die Seite zeigt","text":"<ul> <li>aktuelle CPU-Auslastung</li> <li>RAM-Auslastung</li> <li>GPU-Auslastung und VRAM, falls vorhanden</li> <li>Temperaturen</li> <li>Verlaufshistorie f\u00fcr Auslastung und Temperatur</li> <li>Zeitfenster f\u00fcr <code>1h</code>, <code>6h</code>, <code>24h</code>, <code>4d</code></li> </ul>"},{"location":"gui/hardware/#live-bereich","title":"Live-Bereich","text":"<p>Oben zeigt die Seite:</p> <ul> <li>ob Monitoring aktiv ist</li> <li>aktuelles Polling-Intervall</li> <li>Zeitpunkt der letzten Messung</li> </ul> <p>Wenn Monitoring deaktiviert ist, f\u00fchrt die Seite direkt zu <code>Settings</code>.</p>"},{"location":"gui/hardware/#historie","title":"Historie","text":"<p>Die Historie l\u00e4dt Messpunkte aus dem Backend und zeigt:</p> <ul> <li>Auslastung als Linienchart</li> <li>Temperatur als Linienchart</li> <li>umschaltbare Serien f\u00fcr CPU, RAM und GPU</li> </ul> <p>Das ist besonders n\u00fctzlich bei:</p> <ul> <li>mehreren parallelen Encodes</li> <li>Fehlersuche bei Hitzespitzen</li> <li>Absch\u00e4tzung, ob weitere Jobs sinnvoll gestartet werden k\u00f6nnen</li> </ul>"},{"location":"gui/hardware/#relevante-settings","title":"Relevante Settings","text":"<ul> <li><code>Hardware Monitoring aktiviert</code></li> <li><code>Hardware Monitoring Intervall (ms)</code></li> </ul> <p>Au\u00dferdem sinnvoll:</p> <ul> <li><code>Externe Speicher</code>, damit Speicherst\u00e4nde im <code>Ripper</code> sinnvoll angezeigt werden</li> </ul>"},{"location":"gui/history/","title":"Historie","text":"<p><code>Historie</code> ist die Kontroll- und Nachbearbeitungsoberfl\u00e4che f\u00fcr alle bereits angelegten Jobs.</p>"},{"location":"gui/history/#hauptansicht","title":"Hauptansicht","text":"<p>Filter und Arbeitsmittel:</p> <ul> <li>Suche</li> <li>Statusfilter</li> <li>Mediumfilter</li> <li>Sortierung</li> <li>Listen-/Grid-Layout</li> </ul> <p>Jeder Eintrag zeigt auf einen Blick:</p> <ul> <li>Titel, Jahr, Poster oder Cover</li> <li>Status und Zeitstempel</li> <li>RAW- und Output-Verf\u00fcgbarkeit</li> <li>Medien- und Containerhinweise</li> </ul>"},{"location":"gui/history/#detaildialog","title":"Detaildialog","text":"<p>Der Detaildialog b\u00fcndelt:</p> <ul> <li>Metadaten</li> <li>Jobstatus und Fehlertexte</li> <li>RAW- und Output-Pfade</li> <li>Encode-Plan und Trackauswahl</li> <li>ausgef\u00fchrte Kommandos</li> <li>Prozesslog</li> <li>verf\u00fcgbare Folgeaktionen</li> </ul> <p>Bei Seriencontainern und Multipart-Jobs wird container- und child-orientiert dargestellt.</p>"},{"location":"gui/history/#nachbearbeitungsaktionen","title":"Nachbearbeitungsaktionen","text":"Aktion Typischer Einsatz Technische Wirkung <code>TMDb neu zuweisen</code> falsches Match, anderer Film, andere Staffel Metadaten werden neu geschrieben; Poster, Jahr und ggf. Ordnername werden best effort aktualisiert <code>Review neu starten</code> neue Track-/Titelbewertung n\u00f6tig Review wird aus vorhandenem RAW neu aufgebaut <code>RAW neu encodieren</code> neuer Encode mit vorhandenem RAW startet Encode ohne neuen Disc-Rip <code>Encode neu starten</code> gleiche best\u00e4tigte Auswahl erneut fahren letzter best\u00e4tigter Plan wird geladen <code>Retry Rippen</code> Rip oder Analyse erneut ansto\u00dfen neuer Rip-Lauf inklusive RAW-Phase <p>Relevante Settings:</p> <ul> <li><code>handbrake_restart_delete_incomplete_output</code></li> <li><code>generate_nfo_after_encode</code></li> </ul>"},{"location":"gui/history/#loschaktionen-und-vorschau","title":"L\u00f6schaktionen und Vorschau","text":"<p>Vor dem endg\u00fcltigen L\u00f6schen zeigt Ripster eine Vorschau mit:</p> <ul> <li>RAW-Kandidaten</li> <li>Movie-/Episode-Kandidaten</li> <li>Related-Scope f\u00fcr Container, Kinder und verbundene Jobs</li> </ul> <p>Wichtige Punkte:</p> <ul> <li>Pfade sind selektierbar</li> <li>bei mehreren RAW-Kandidaten muss mindestens ein RAW-Pfad gew\u00e4hlt werden</li> <li>Schutzlogik verhindert L\u00f6schungen au\u00dferhalb erlaubter Root-Verzeichnisse</li> </ul>"},{"location":"gui/history/#serien-und-multipart-sicht","title":"Serien- und Multipart-Sicht","text":""},{"location":"gui/history/#serien","title":"Serien","text":"<ul> <li>Container zeigt den aggregierten Zustand der Child-Jobs</li> <li>Disk- und Episodenaktionen k\u00f6nnen child-spezifisch ausgef\u00fchrt werden</li> <li><code>Im Ripper \u00f6ffnen</code> hilft bei offenen Reviews</li> </ul>"},{"location":"gui/history/#multipart","title":"Multipart","text":"<ul> <li>gemeinsamer Container mit Disc-Childs</li> <li>Disc-Nummern bleiben pro Child nachvollziehbar</li> <li>Delete-Preview kann Related-Pfade gemeinsam aufl\u00f6sen</li> </ul>"},{"location":"gui/history/#logs-sinnvoll-nutzen","title":"Logs sinnvoll nutzen","text":"<ul> <li><code>Tail laden</code> f\u00fcr schnellen Fehlerkontext</li> <li><code>Vollst\u00e4ndiges Log laden</code> f\u00fcr tiefe Analyse</li> </ul> <p>Empfehlung:</p> <ol> <li>erst den Tail pr\u00fcfen</li> <li>dann die Stelle im Log eingrenzen</li> <li>anschlie\u00dfend die passende Wiederanlauf-Aktion w\u00e4hlen</li> </ol>"},{"location":"gui/ripper/","title":"Ripper","text":"<p>Die Seite <code>Ripper</code> ist die Live-Steuerung der Disc-Pipeline. Hier laufen Disc-Erkennung, Queue, manuelle Entscheidungen, Review und aktive Jobs zusammen.</p>"},{"location":"gui/ripper/#seitenaufbau","title":"Seitenaufbau","text":"<p>Die wichtigsten Bereiche:</p> <ol> <li><code>Hardware</code></li> <li><code>Job Queue</code></li> <li><code>Skript- / Cron-Status</code></li> <li><code>Job \u00dcbersicht</code></li> <li><code>Disk-Information</code></li> </ol>"},{"location":"gui/ripper/#1-hardware","title":"1. Hardware","text":"<p>Die Hardware-Karte zeigt live:</p> <ul> <li>CPU</li> <li>RAM</li> <li>GPU, falls vorhanden</li> <li>freie Speicherst\u00e4nde der konfigurierten Pfade</li> </ul> <p>Aktionen:</p> <ul> <li>Klick auf das Hardware-Symbol \u00f6ffnet die Seite Hardware</li> </ul> <p>Relevante Settings:</p> <ul> <li><code>Hardware Monitoring aktiviert</code></li> <li><code>Hardware Monitoring Intervall (ms)</code></li> <li><code>Externe Speicher</code></li> </ul>"},{"location":"gui/ripper/#2-job-queue","title":"2. Job Queue","text":"<p>Es gibt zwei operative Zonen:</p> <ul> <li>laufende Jobs</li> <li>Warteschlange</li> </ul> <p>M\u00f6gliche Queue-Eintr\u00e4ge:</p> <ul> <li>normale Job-Starts</li> <li><code>Retry Rippen</code></li> <li><code>RAW neu encodieren</code></li> <li><code>Encode neu starten</code></li> <li><code>Review neu starten</code></li> <li><code>Audio CD starten</code></li> <li><code>Skript</code></li> <li><code>Skriptkette</code></li> <li><code>Warten</code></li> </ul> <p>Wichtige Regeln:</p> <ul> <li>Reihenfolge ist per Drag-and-Drop \u00e4nderbar</li> <li><code>Warten</code> blockiert nachfolgende Starts, bis keine aktive Verarbeitung mehr l\u00e4uft</li> <li>Queue-Eintr\u00e4ge k\u00f6nnen auch ohne Medienjob existieren</li> </ul> <p>Relevante Settings:</p> <ul> <li><code>Parallele Jobs</code></li> <li><code>Max. parallele Audio CD Jobs</code></li> <li><code>Max. Encodes gesamt (medienunabh\u00e4ngig)</code></li> <li><code>Audio CDs: Queue-Reihenfolge \u00fcberspringen</code></li> </ul>"},{"location":"gui/ripper/#3-skript-cron-status","title":"3. Skript- / Cron-Status","text":"<p>Zeigt Runtime-Aktivit\u00e4ten:</p> <ul> <li>laufende Skripte</li> <li>laufende Ketten</li> <li>Cron-Ausf\u00fchrungen</li> <li>k\u00fcrzlich abgeschlossene Aktivit\u00e4ten</li> </ul> <p>Aktionen:</p> <ul> <li><code>N\u00e4chster Schritt</code> bei Ketten</li> <li><code>Abbrechen</code></li> <li><code>Liste leeren</code></li> </ul>"},{"location":"gui/ripper/#4-job-ubersicht","title":"4. Job \u00dcbersicht","text":"<p>Die Jobliste ist der zentrale Arbeitsbereich. Ein Klick \u00f6ffnet den jeweiligen <code>Pipeline-Status</code>.</p>"},{"location":"gui/ripper/#zustandsabhangige-hauptaktionen","title":"Zustandsabh\u00e4ngige Hauptaktionen","text":"Zustand Typische Aktion Ergebnis <code>Medium erkannt</code> <code>Analyse starten</code> MakeMKV-Analyse beginnt <code>Metadatenauswahl</code> <code>Metadaten \u00f6ffnen</code> TMDb-Dialog f\u00fcr Film/Serie <code>Warte auf Auswahl</code> Entscheidung best\u00e4tigen Flow geht an die passende Stelle weiter <code>Startbereit</code> <code>Job starten</code> Rip oder RAW-basierte Pr\u00fcfung startet <code>Bereit zum Encodieren</code> <code>Encoding starten</code> HandBrake startet mit best\u00e4tigter Auswahl laufend <code>Abbrechen</code> Job wird gestoppt <code>Fehler</code> / <code>Abgebrochen</code> <code>Retry Rippen</code> neuer Rip-Anlauf"},{"location":"gui/ripper/#was-warte-auf-auswahl-heute-bedeuten-kann","title":"Was <code>Warte auf Auswahl</code> heute bedeuten kann","text":"<p>Der Status ist nicht nur f\u00fcr eine einzige Entscheidung da. Im aktuellen Stand gibt es drei typische F\u00e4lle:</p>"},{"location":"gui/ripper/#vorhandenes-raw","title":"Vorhandenes RAW","text":"<p>Ripster hat zu den Metadaten bereits ein passendes RAW gefunden. Dann entscheidest du:</p> <ul> <li>mit RAW weiterarbeiten</li> <li>RAW l\u00f6schen und neu rippen</li> <li>in passenden Film-F\u00e4llen optional Multipart mit Orphan-RAW bilden</li> </ul>"},{"location":"gui/ripper/#playlist-auswahl","title":"Playlist-Auswahl","text":"<p>Bei mehrdeutigen Blu-rays oder bestimmten DVD-F\u00e4llen musst du eine Playlist best\u00e4tigen. Die Liste zeigt unter anderem:</p> <ul> <li>Playlist-Datei</li> <li>Titel-ID</li> <li>Laufzeit</li> <li>Score</li> <li>Empfehlung</li> <li>Segment- und Audio-Vorschau</li> </ul> <p>Relevante Settings:</p> <ul> <li><code>Minimale Titell\u00e4nge (Minuten)</code></li> <li><code>TMDb Runtime-Abzug f\u00fcr Playlistfilter (%)</code></li> <li><code>Bei manueller Auswahl senden</code> f\u00fcr PushOver</li> </ul>"},{"location":"gui/ripper/#titelauswahl-playall-grenzfall","title":"Titelauswahl / PlayAll-Grenzfall","text":"<p>Wenn Ripster mehrere HandBrake-Titel als plausibel erkannt hat, musst du einen oder mehrere Titel best\u00e4tigen. Bei Serien kann das der Grenzfall <code>PlayAll oder Doppelfolge?</code> sein.</p>"},{"location":"gui/ripper/#5-review-bereich-bereit-zum-encodieren","title":"5. Review-Bereich (<code>Bereit zum Encodieren</code>)","text":"<p>Hier triffst du die eigentliche Encode-Entscheidung.</p> <p>Du legst fest:</p> <ul> <li>welchen Titel Ripster encodieren soll</li> <li>welche Audio-Spuren \u00fcbernommen werden</li> <li>welche Untertitel \u00fcbernommen, erzwungen oder eingebrannt werden</li> <li>welches User-Preset oder HandBrake-Preset verwendet wird</li> <li>welche Pre-/Post-Encode-Skripte oder Ketten mitlaufen</li> </ul> <p>Wichtig:</p> <ul> <li>ohne diese Best\u00e4tigung startet kein produktiver Encode</li> <li>bei Multipart-Locks k\u00f6nnen Einstellungen von einer Referenz-Disc \u00fcbernommen und gesperrt sein</li> </ul>"},{"location":"gui/ripper/#welche-settings-hier-direkt-sichtbar-werden","title":"Welche Settings hier direkt sichtbar werden","text":"<ul> <li><code>HandBrake Preset</code></li> <li><code>HandBrake Extra Args</code></li> <li><code>Review Audio-Sprachen (...)</code></li> <li><code>Review UT-Sprachen (...)</code></li> <li><code>Ausgabeformat</code></li> <li>Standard-Zuordnungen aus <code>Settings -&gt; Encode-Presets</code></li> </ul>"},{"location":"gui/ripper/#raw-ordnerphasen","title":"RAW-Ordnerphasen","text":"<p>Der Ripper arbeitet mit drei RAW-Zust\u00e4nden:</p> <ul> <li><code>Incomplete_...</code> w\u00e4hrend eines unvollst\u00e4ndigen Rips</li> <li><code>Rip_Complete_...</code> nach erfolgreichem Rip, vor dem finalen Encode</li> <li>ohne Prefix nach erfolgreichem Encode</li> </ul> <p>Das ist wichtig f\u00fcr:</p> <ul> <li>Recovery</li> <li>RAW-Wiederverwendung</li> <li>Delete-Preview in <code>Historie</code></li> </ul>"},{"location":"gui/ripper/#disk-information","title":"Disk-Information","text":"<p>Zeigt aktuelle Laufwerksdaten:</p> <ul> <li>Device-Pfad</li> <li>Modell</li> <li>Disc-Label</li> <li>Mount-Informationen</li> </ul> <p>Aktionen:</p> <ul> <li><code>Laufwerk neu lesen</code></li> <li><code>Disk neu analysieren</code></li> <li>Metadaten-Dialog \u00f6ffnen</li> </ul> <p>Hinweis:</p> <ul> <li><code>Laufwerk neu lesen</code> ist nicht mehr an einen festen Pipeline-State gebunden</li> </ul>"},{"location":"gui/ripper/#wichtige-dialoge","title":"Wichtige Dialoge","text":""},{"location":"gui/ripper/#metadaten-auswahlen","title":"Metadaten ausw\u00e4hlen","text":"<p>Im Dialog best\u00e4tigst du Film- oder Serienmetadaten aus TMDb.</p> <p>Sonderf\u00e4lle:</p> <ul> <li>Film-Duplikat: <code>\u00dcbernahme erzwingen</code> oder <code>Multipart movie</code></li> <li>Serie: <code>Disc-Nummer</code> ist Pflicht</li> </ul>"},{"location":"gui/ripper/#vorhandenes-raw-erkannt","title":"Vorhandenes RAW erkannt","text":"<p>Wenn zu den Metadaten bereits RAW existiert, fordert Ripster eine explizite Entscheidung:</p> <ul> <li>vorhandenes RAW verwenden</li> <li>RAW verwerfen/l\u00f6schen und neu rippen</li> </ul>"},{"location":"gui/ripper/#queue-eintrag-einfugen","title":"Queue-Eintrag einf\u00fcgen","text":"<p>Du kannst gezielt ab Position einf\u00fcgen:</p> <ul> <li>Skript</li> <li>Skriptkette</li> <li>Wartezeit</li> </ul>"},{"location":"gui/ripper/#audible-activation-bytes-eintragen","title":"Audible Activation Bytes eintragen","text":"<p>Wenn f\u00fcr eine AAX-Datei keine Activation Bytes verf\u00fcgbar sind, \u00f6ffnet Ripster einen Dialog zur manuellen Eingabe.</p> <ul> <li>Format: genau 8 Hex-Zeichen, z. B. <code>1a2b3c4d</code></li> <li>Speicherung: lokal im Activation-Bytes-Cache</li> <li>Wirkung: der Audiobook-Flow kann anschlie\u00dfend fortgesetzt werden</li> </ul>"},{"location":"gui/ripper/#siehe-auch","title":"Siehe auch","text":"<ul> <li>Hardware</li> <li>Settings</li> <li>Workflows aus Nutzersicht</li> </ul>"},{"location":"gui/settings/","title":"Settings","text":"<p>Die Seite <code>Settings</code> ist das Kontrollzentrum f\u00fcr Laufzeitverhalten, Standardwerte und Automatisierung. Alles, was sp\u00e4tere Jobs automatisch tun oder vorschlagen, wird hier vorbereitet.</p>"},{"location":"gui/settings/#tab-uberblick","title":"Tab-\u00dcberblick","text":"Tab Zweck <code>Konfiguration</code> alle fachlichen Einstellungen aus der GUI <code>Scripte</code> einzelne Bash-Skripte anlegen, testen und sortieren <code>Skriptketten</code> mehrstufige Abl\u00e4ufe aus Skript- und Warte-Schritten bauen <code>Encode-Presets</code> eigene Video-Presets und Standard-Zuordnungen pflegen <code>Cronjobs</code> zeitgesteuerte Ausf\u00fchrung von Skripten oder Ketten"},{"location":"gui/settings/#tab-konfiguration","title":"Tab <code>Konfiguration</code>","text":""},{"location":"gui/settings/#bedienlogik","title":"Bedienlogik","text":"<ol> <li>Felder \u00e4ndern</li> <li><code>\u00c4nderungen speichern</code> klicken</li> <li>erst dann gelten die neuen Werte f\u00fcr k\u00fcnftige Starts, Reviews oder Scheduler</li> </ol> <p>Ausnahmen:</p> <ul> <li><code>Expertenmodus</code> wird sofort gespeichert</li> <li>Buttons wie <code>PushOver Test</code>, <code>Coverarts pr\u00fcfen</code> oder der MakeMKV-Betakey-Import l\u00f6sen direkte Aktionen aus</li> </ul>"},{"location":"gui/settings/#toolbar-aktionen","title":"Toolbar-Aktionen","text":"<ul> <li><code>\u00c4nderungen speichern</code>: schreibt nur ge\u00e4nderte Felder</li> <li><code>\u00c4nderungen verwerfen</code>: setzt den Formularzustand zur\u00fcck</li> <li><code>Neu laden</code>: l\u00e4dt Schema und Werte neu</li> <li><code>PushOver Test</code>: sendet eine Testnachricht mit den aktuellen PushOver-Werten</li> <li><code>Coverarts pr\u00fcfen</code>: startet den Coverart-Recovery-Lauf sofort</li> </ul>"},{"location":"gui/settings/#was-die-kategorien-im-alltag-steuern","title":"Was die Kategorien im Alltag steuern","text":""},{"location":"gui/settings/#benachrichtigungen","title":"Benachrichtigungen","text":"<p>Hier steuerst du zwei Dinge:</p> <ul> <li>ob und wohin Ripster PushOver-Nachrichten sendet</li> <li>bei welchen Ereignissen Ripster \u00fcberhaupt benachrichtigt</li> </ul> <p>Wichtig:</p> <ul> <li><code>PushOver aktiviert</code> ist der Master-Schalter</li> <li><code>Bei manueller Auswahl senden</code> ist besonders relevant f\u00fcr Playlist-, RAW- oder Titelentscheidungen</li> <li>der <code>Expertenmodus</code> blendet zus\u00e4tzliche technische Felder in der gesamten Settings-Seite ein</li> </ul>"},{"location":"gui/settings/#laufwerk","title":"Laufwerk","text":"<p>Diese Kategorie beeinflusst, wie Ripster optische Laufwerke findet und \u00fcberwacht.</p> <p>Typische Fragen:</p> <ul> <li>Soll Ripster Laufwerke automatisch erkennen?</li> <li>Soll ein bestimmtes Laufwerk fest an einen MakeMKV-Index gebunden werden?</li> <li>Soll das Laufwerk nach erfolgreichem Rip automatisch auswerfen?</li> </ul> <p>Das ist vor allem wichtig bei:</p> <ul> <li>mehreren Laufwerken</li> <li>USB-SATA-Adaptern</li> <li>Hosts mit instabilen Device-Namen</li> </ul>"},{"location":"gui/settings/#logging","title":"Logging","text":"<p>Diese Felder \u00e4ndern nicht die Job-Logs auf Platte, sondern die Ausgabe im Server-Terminal.</p> <p>Damit steuerst du zum Beispiel:</p> <ul> <li>ob <code>start.sh</code> oder ein Terminal-Run sehr gespr\u00e4chig sein darf</li> <li>ob HTTP-Requests im Terminal sichtbar sein sollen</li> <li>ob DEBUG/INFO/WARN/ERROR dort mitlaufen</li> </ul>"},{"location":"gui/settings/#metadaten","title":"Metadaten","text":"<p>Hier legst du fest, wie Ripster mit TMDb, Covern und NFO-Dateien umgeht.</p> <p>Besonders wichtig:</p> <ul> <li>ohne <code>TMDb Read Access Token</code> funktionieren Film-/Seriensuche und Neu-Zuordnung nur eingeschr\u00e4nkt oder gar nicht</li> <li><code>Film-Sprache</code> und <code>Fallback Sprache</code> bestimmen, welche Titel, Beschreibungen und Staffelinformationen bevorzugt werden</li> <li><code>Coverart-Nachladen aktiv</code> hilft bei nachtr\u00e4glich fehlenden Postern/Covern</li> </ul>"},{"location":"gui/settings/#monitoring","title":"Monitoring","text":"<p>Steuert das Hardware-Monitoring f\u00fcr:</p> <ul> <li>CPU</li> <li>RAM</li> <li>GPU</li> <li>Speicherst\u00e4nde</li> </ul> <p>Diese Werte erscheinen:</p> <ul> <li>kompakt im <code>Ripper</code></li> <li>ausf\u00fchrlich in der Seite <code>Hardware</code></li> </ul>"},{"location":"gui/settings/#pfade","title":"Pfade","text":"<p>Hier legst du fest, wohin Ripster schreibt und wie Dateien benannt werden.</p> <p>Die Felder steuern:</p> <ul> <li>RAW-Verzeichnisse pro Medium</li> <li>Zielordner f\u00fcr Filme, Serien, CDs, Audiobooks, Converter und Downloads</li> <li>Eigent\u00fcmer per <code>user:gruppe</code></li> <li>Templates f\u00fcr Datei- und Ordnernamen</li> </ul> <p>Praxisbeispiele:</p> <ul> <li>Serien getrennt von Filmen ablegen</li> <li>RAW auf gro\u00dfe HDD, Final-Output auf NAS</li> <li>Audiobooks kapitelweise in Unterordnern strukturieren</li> </ul>"},{"location":"gui/settings/#converter","title":"Converter","text":"<p>Diese Kategorie wirkt nur auf die Seite <code>Converter</code>.</p> <p>Sie steuert:</p> <ul> <li>welche Dateiendungen der Upload und der Verzeichnisscan akzeptieren</li> <li>ob der Converter-RAW-Baum automatisch neu gescannt wird</li> <li>wie h\u00e4ufig dieses Polling l\u00e4uft</li> </ul>"},{"location":"gui/settings/#tools","title":"Tools","text":"<p>Diese Kategorie entscheidet \u00fcber das technische Verhalten der eigentlichen Pipeline.</p> <p>Dazu geh\u00f6ren:</p> <ul> <li>Pfade/Befehle f\u00fcr externe Tools</li> <li>MakeMKV-Filter und Rip-Modi</li> <li>HandBrake-Presets und Extra-Args</li> <li>Vorauswahl von Audio-/Untertitelsprachen in der Review</li> <li>Ausgabeformate</li> <li>Queue- und Parallelit\u00e4tsregeln</li> <li>Timeout f\u00fcr Script-Tests</li> </ul> <p>F\u00fcr die Nutzer-Workflows besonders relevant:</p> <ul> <li><code>Minimale Titell\u00e4nge (Minuten)</code></li> <li><code>TMDb Runtime-Abzug f\u00fcr Playlistfilter (%)</code></li> <li><code>HandBrake Preset</code> und <code>HandBrake Extra Args</code></li> <li><code>Review Audio-Sprachen (...)</code></li> <li><code>Review UT-Sprachen (...)</code></li> <li><code>Parallele Jobs</code></li> <li><code>Max. parallele Audio CD Jobs</code></li> <li><code>Max. Encodes gesamt (medienunabh\u00e4ngig)</code></li> </ul>"},{"location":"gui/settings/#kategorie-pfade-besondere-interaktion","title":"Kategorie <code>Pfade</code>: Besondere Interaktion","text":"<p>Die Pfad-Kategorie hat eine eigene Darstellung:</p> <ul> <li>Tabelle <code>Effektive Pfade</code>: zeigt die aktuell wirklich verwendeten Laufzeitpfade inklusive Fallbacks</li> <li>Accordion pro Bereich wie <code>Blu-ray</code>, <code>DVD</code>, <code>CD / Audio</code>, <code>Audiobook</code>, <code>Converter</code>, <code>Downloads</code>, <code>Logs</code></li> <li>Owner-Felder (<code>*_owner</code>) erscheinen direkt beim zugeh\u00f6rigen Pfad</li> <li>Owner-Felder sind deaktiviert, solange der zugeh\u00f6rige Pfad leer ist</li> </ul>"},{"location":"gui/settings/#spezial-editoren","title":"Spezial-Editoren","text":"<ul> <li><code>drive_devices</code>: Editor f\u00fcr mehrere Laufwerke mit Pfad und MakeMKV-Index</li> <li><code>external_storage_paths</code>: Liste aus Anzeigename und Pfad f\u00fcr die Speicheranzeige</li> <li><code>converter_scan_extensions</code>: Auswahl der erlaubten Upload-/Scan-Endungen</li> <li><code>makemkv_registration_key</code>: inkl. Betakey-Hinweis und \u00dcbernahme-Button</li> </ul>"},{"location":"gui/settings/#wichtig-fur-reviews-und-workflows","title":"Wichtig f\u00fcr Reviews und Workflows","text":"<p>Die Seite <code>Settings</code> bestimmt direkt, was Nutzer sp\u00e4ter im Workflow sehen:</p> <ul> <li>Playlist-Kandidaten werden durch <code>Minimale Titell\u00e4nge</code> und <code>TMDb Runtime-Abzug ...</code> beeinflusst</li> <li>Audio-/Untertitel-Vorauswahlen in <code>Bereit zum Encodieren</code> h\u00e4ngen an den Review-Sprachfeldern</li> <li>automatisch vorgeschlagene Presets h\u00e4ngen an den Standard-Zuordnungen unter <code>Encode-Presets</code></li> <li>Queue-Verhalten im <code>Ripper</code> h\u00e4ngt an den drei Parallelit\u00e4tsfeldern plus <code>Audio CDs: Queue-Reihenfolge \u00fcberspringen</code></li> </ul>"},{"location":"gui/settings/#tab-scripte","title":"Tab <code>Scripte</code>","text":"<p>Funktionen:</p> <ul> <li>Skript anlegen</li> <li>Skript bearbeiten</li> <li>Skript l\u00f6schen</li> <li>Skript testen</li> <li>Reihenfolge per Drag-and-Drop \u00e4ndern</li> <li>Favorit markieren</li> </ul> <p>Das Testergebnis zeigt:</p> <ul> <li>Erfolg oder Fehler</li> <li>Exit-Code</li> <li>Dauer</li> <li>stdout/stderr</li> <li>Timeout, falls <code>Script-Test Timeout (ms)</code> greift</li> </ul>"},{"location":"gui/settings/#tab-skriptketten","title":"Tab <code>Skriptketten</code>","text":"<p>Skriptketten bestehen aus Schritten:</p> <ul> <li><code>Skript</code></li> <li><code>Warten (Sekunden)</code></li> </ul> <p>Funktionen:</p> <ul> <li>Ketten anlegen, bearbeiten, l\u00f6schen</li> <li>Reihenfolge der Ketten \u00e4ndern</li> <li>einzelne Ketten testen</li> <li>Schritte innerhalb der Kette per Drag-and-Drop sortieren</li> </ul> <p>Wichtig:</p> <ul> <li>dieselben Skripte k\u00f6nnen sowohl in Jobs als auch in Ketten und Cronjobs wiederverwendet werden</li> </ul>"},{"location":"gui/settings/#tab-encode-presets","title":"Tab <code>Encode-Presets</code>","text":"<p>Hier werden Video-Standards f\u00fcr Disc- und Converter-Workflows verwaltet.</p>"},{"location":"gui/settings/#standard-zuordnungen","title":"Standard-Zuordnungen","text":"<p>Es gibt vier feste Slots:</p> <ul> <li><code>Blu-ray Film</code></li> <li><code>Blu-ray Serie</code></li> <li><code>DVD Film</code></li> <li><code>DVD Serie</code></li> </ul> <p>Wenn f\u00fcr einen Workflow hier ein Default gesetzt ist, erscheint dieses User-Preset sp\u00e4ter in der Review bereits vorausgew\u00e4hlt.</p>"},{"location":"gui/settings/#preset-inhalt","title":"Preset-Inhalt","text":"<p>Ein User-Preset besteht aus:</p> <ul> <li>Name</li> <li>Medientyp (<code>all</code>, <code>bluray</code>, <code>dvd</code>)</li> <li>HandBrake-Preset</li> <li>Extra Args</li> <li>optionaler Beschreibung</li> </ul>"},{"location":"gui/settings/#tab-cronjobs","title":"Tab <code>Cronjobs</code>","text":"<p>Funktionen:</p> <ul> <li>Cronjob anlegen, bearbeiten, l\u00f6schen</li> <li>Cron-Ausdruck live validieren</li> <li>Quelle w\u00e4hlen: <code>Skript</code> oder <code>Skriptkette</code></li> <li>Aktiv- und PushOver-Status pro Job setzen</li> <li><code>Jetzt ausf\u00fchren</code></li> <li>Lauf-Logs \u00f6ffnen</li> </ul> <p>Die Runtime-Aktivit\u00e4ten der laufenden Cronjobs werden zus\u00e4tzlich live angezeigt.</p>"},{"location":"gui/settings/#expertenbereich-activation-bytes-cache","title":"Expertenbereich: Activation Bytes Cache","text":"<p>Dieser Block wird nur im Expertenmodus angezeigt.</p> <p>Er zeigt lokal bekannte AAX-Activation-Bytes mit:</p> <ul> <li>Pr\u00fcfsumme</li> <li>Activation Bytes</li> <li>Speicherzeitpunkt</li> </ul> <p>Das hilft bei Audiobook-Workflows, wenn dieselbe Datei oder derselbe Hash sp\u00e4ter erneut auftaucht.</p>"},{"location":"gui/settings/#validierung-von-template-feldern","title":"Validierung von Template-Feldern","text":"<p>Template-Felder akzeptieren nur:</p> <ul> <li>Buchstaben und Ziffern</li> <li>Leerzeichen</li> <li><code>_</code> und <code>-</code></li> <li>Platzhalter in <code>{...}</code> oder <code>${...}</code></li> <li><code>/</code> f\u00fcr Unterordner</li> </ul> <p>Damit verhindert Ripster fehlerhafte Dateinamen schon beim Speichern.</p>"},{"location":"gui/settings/#siehe-auch","title":"Siehe auch","text":"<ul> <li>Alle Einstellungen</li> <li>Ripper</li> <li>Workflows aus Nutzersicht</li> </ul>"},{"location":"gui/tmdb-migration/","title":"TMDb Migration","text":"<p>Die Seite <code>TMDb Migration</code> ist eine Sonderansicht f\u00fcr \u00e4ltere Bestandsjobs, die noch nicht als auf TMDb migriert markiert sind.</p>"},{"location":"gui/tmdb-migration/#zugriff","title":"Zugriff","text":"<ul> <li>Direktlink: <code>/tmdb-migration</code></li> <li>nicht in der normalen Top-Navigation verlinkt</li> </ul>"},{"location":"gui/tmdb-migration/#wofur-die-seite-gedacht-ist","title":"Wof\u00fcr die Seite gedacht ist","text":"<p>Typische Einsatzf\u00e4lle:</p> <ul> <li>Altbestand aus fr\u00fcheren St\u00e4nden bereinigen</li> <li>mehrere Jobs nacheinander auf aktuelle TMDb-Metadaten umstellen</li> <li>Historie konsistent auf den heutigen Metadaten-Workflow bringen</li> </ul>"},{"location":"gui/tmdb-migration/#funktionsweise","title":"Funktionsweise","text":"<p>Die Seite l\u00e4dt offene Migrationskandidaten und zeigt:</p> <ul> <li>Job-ID</li> <li>Titel</li> <li>Jahr</li> <li>Medium</li> <li>aktuellen Status</li> </ul> <p>Aktionen:</p> <ul> <li><code>Liste neu laden</code></li> <li><code>Start</code></li> <li><code>Stop</code></li> </ul>"},{"location":"gui/tmdb-migration/#ablauf-einer-sequenz","title":"Ablauf einer Sequenz","text":"<ol> <li>Jobliste laden</li> <li><code>Start</code></li> <li>der bekannte TMDb-Metadaten-Dialog \u00f6ffnet sich f\u00fcr den ersten Job</li> <li>nach erfolgreicher \u00dcbernahme plant Ripster den n\u00e4chsten Job mit Cooldown</li> </ol> <p>Wichtig:</p> <ul> <li>zwischen zwei Jobs liegt bewusst eine Wartezeit von mindestens 10 Sekunden</li> <li>damit wird die TMDb-API bei Serienmigrationen nicht unn\u00f6tig belastet</li> </ul>"},{"location":"gui/tmdb-migration/#relevante-settings","title":"Relevante Settings","text":"<ul> <li><code>TMDb Read Access Token</code></li> <li><code>Film-Sprache</code></li> <li><code>Fallback Sprache</code></li> </ul> <p>Ohne diese Einstellungen ist die Migration nicht sinnvoll nutzbar.</p>"},{"location":"pipeline/","title":"Anhang: Pipeline intern","text":"<p>Dieser Abschnitt beschreibt die technische Pipeline-Logik hinter den UI-Workflows.</p> <ul> <li> <p> Workflow &amp; Zust\u00e4nde</p> <p>Zustandsmodell, \u00dcberg\u00e4nge, Queue-Verhalten.</p> <p> Workflow</p> </li> <li> <p> Encode-Planung</p> <p>Aufbereitung von Titeln/Tracks und Best\u00e4tigungslogik.</p> <p> Encoding</p> </li> <li> <p> Playlist-Analyse</p> <p>Bewertung mehrdeutiger Blu-ray-Playlists.</p> <p> Playlist-Analyse</p> </li> <li> <p> Pre-/Post-Encode-Ausf\u00fchrungen</p> <p>Skript- und Kettenlauf vor/nach dem Encoding.</p> <p> Encode-Skripte</p> </li> </ul>"},{"location":"pipeline/#zuruck-zum-handbuch","title":"Zur\u00fcck zum Handbuch","text":"<ul> <li>Workflows aus Nutzersicht</li> </ul>"},{"location":"pipeline/encoding/","title":"Encode-Planung &amp; Track-Auswahl","text":"<p>Vor dem eigentlichen Encoding erstellt Ripster einen Encode-Plan und zeigt ihn im Review an.</p>"},{"location":"pipeline/encoding/#ablauf","title":"Ablauf","text":"<pre><code>Quelle bestimmen (Disc/RAW)\n -&gt; HandBrake-Scan (--scan --json)\n -&gt; Plan erstellen (Titel, Audio, Untertitel)\n -&gt; Status: Bereit zum Encodieren\n -&gt; Benutzer bestaetigt Auswahl\n -&gt; finaler HandBrake-Aufruf\n</code></pre>"},{"location":"pipeline/encoding/#review-inhalt-status-bereit-zum-encodieren","title":"Review-Inhalt (Status: <code>Bereit zum Encodieren</code>)","text":"<ul> <li>ausw\u00e4hlbarer Encode-Titel</li> <li>Audio-Track-Auswahl</li> <li>Untertitel-Track-Auswahl inkl. Flags</li> <li><code>burnIn</code></li> <li><code>forced</code></li> <li><code>defaultTrack</code></li> <li>optionale User-Presets (HandBrake Preset + Extra Args)</li> <li>optionale Pre-/Post-Skripte und Ketten</li> </ul>"},{"location":"pipeline/encoding/#bestaetigung-confirm-encode","title":"Bestaetigung (<code>confirm-encode</code>)","text":"<p>Typischer Payload:</p> <pre><code>{\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</code></pre> <p>Die best\u00e4tigte Auswahl wird im Job gespeichert und f\u00fcr Neustarts wiederverwendet.</p>"},{"location":"pipeline/encoding/#handbrake-aufruf","title":"HandBrake-Aufruf","text":"<p>Grundstruktur:</p> <pre><code>HandBrakeCLI \\\n -i &lt;input&gt; \\\n -o &lt;output&gt; \\\n -t &lt;titleId&gt; \\\n -Z \"&lt;preset&gt;\" \\\n &lt;extra-args&gt; \\\n -a &lt;audioTrackIds|none&gt; \\\n -s &lt;subtitleTrackIds|none&gt;\n</code></pre> <p>Untertitel-Flags werden bei Bedarf erg\u00e4nzt:</p> <ul> <li><code>--subtitle-burned=&lt;id&gt;</code></li> <li><code>--subtitle-default=&lt;id&gt;</code></li> <li><code>--subtitle-forced=&lt;id&gt;</code> oder <code>--subtitle-forced</code></li> </ul>"},{"location":"pipeline/encoding/#pre-post-encode-ausfuhrungen","title":"Pre-/Post-Encode-Ausf\u00fchrungen","text":"<ul> <li>Pre-Encode l\u00e4uft vor HandBrake</li> <li>Post-Encode l\u00e4uft nach HandBrake</li> </ul> <p>Fehlerverhalten:</p> <ul> <li>Pre-Encode-Fehler: Job endet mit Status <code>Fehler</code> (Encode startet nicht)</li> <li>Post-Encode-Fehler: Job kann <code>Fertig</code> bleiben, enth\u00e4lt aber Fehlerhinweis/Script-Summary</li> </ul>"},{"location":"pipeline/encoding/#dateinamenordner","title":"Dateinamen/Ordner","text":"<p>Der finale Outputpfad wird aus den Templates in den Settings aufgebaut.</p> <p>Platzhalter:</p> <ul> <li><code>${title}</code></li> <li><code>${year}</code></li> <li><code>${imdbId}</code></li> </ul> <p>Ung\u00fcltige Dateizeichen werden bereinigt.</p>"},{"location":"pipeline/playlist-analysis/","title":"Playlist-Analyse","text":"<p>Ripster analysiert bei Blu-ray-\u00e4hnlichen Quellen Playlists und fordert bei Mehrdeutigkeit eine manuelle Auswahl an.</p>"},{"location":"pipeline/playlist-analysis/#ziel","title":"Ziel","text":"<p>Erkennen, welche Playlist sehr wahrscheinlich der Hauptfilm ist, statt versehentlich eine Fake-/Dummy-Playlist zu verwenden.</p>"},{"location":"pipeline/playlist-analysis/#eingabedaten","title":"Eingabedaten","text":"<p>Die Analyse basiert auf MakeMKV-Infos (u. a. Playlist-/Segment-Struktur, Laufzeiten, Titelzuordnung).</p>"},{"location":"pipeline/playlist-analysis/#auswertung-vereinfacht","title":"Auswertung (vereinfacht)","text":"<p>F\u00fcr Kandidaten werden u. a. ber\u00fccksichtigt:</p> <ul> <li>Laufzeit</li> <li>Segment-Reihenfolge</li> <li>R\u00fcckw\u00e4rtsspr\u00fcnge/gro\u00dfe Spr\u00fcnge</li> <li>Koh\u00e4renz linearer Segmentfolgen</li> <li>Duplikatgruppen mit \u00e4hnlicher Laufzeit</li> </ul> <p>Daraus entstehen intern Kandidatenlisten, Bewertungen und eine Empfehlung.</p>"},{"location":"pipeline/playlist-analysis/#wann-muss-der-benutzer-entscheiden","title":"Wann muss der Benutzer entscheiden?","text":"<p>Wenn nach Filterung mehr als ein relevanter Kandidat \u00fcbrig bleibt, wechselt der Job in der GUI auf:</p> <ul> <li><code>Warte auf Auswahl</code></li> </ul> <p>Dann muss eine Playlist best\u00e4tigt werden, bevor der Workflow weiterl\u00e4uft.</p>"},{"location":"pipeline/playlist-analysis/#konfigurationseinfluss","title":"Konfigurationseinfluss","text":"Feld in <code>Settings</code> Wirkung <code>Minimale Titell\u00e4nge (Minuten)</code> Mindestlaufzeit f\u00fcr Kandidaten aus MakeMKV/Playlist-Analyse <code>TMDb Runtime-Abzug f\u00fcr Playlistfilter (%)</code> lockert bei Bedarf die untere Laufzeitgrenze relativ zur TMDb-Laufzeit, damit leicht k\u00fcrzere Hauptfassungen Kandidaten bleiben <p>Default ist aktuell <code>60</code> Minuten.</p>"},{"location":"pipeline/playlist-analysis/#ui-verhalten","title":"UI-Verhalten","text":"<p>Bei manueller Entscheidung zeigt der <code>Ripper</code> Kandidaten mit:</p> <ul> <li>Playlist-Datei</li> <li>Titel-ID</li> <li>Laufzeit</li> <li>Score</li> <li>Empfehlung</li> <li>Segment- und Audio-Vorschau</li> </ul> <p>Nach Best\u00e4tigung:</p> <ul> <li>mit vorhandenem RAW -&gt; zur\u00fcck zu <code>Mediainfo-Pruefung</code></li> <li>ohne RAW -&gt; Startpfad \u00fcber <code>Startbereit</code> / <code>Rippen</code></li> </ul>"},{"location":"pipeline/post-encode-scripts/","title":"Encode-Skripte (Pre &amp; Post)","text":"<p>Ripster kann Skripte und Skript-Ketten vor und nach dem Encode ausf\u00fchren.</p>"},{"location":"pipeline/post-encode-scripts/#ablauf","title":"Ablauf","text":"<pre><code>Bereit zum Encodieren\n -&gt; Pre-Encode Skripte/Ketten\n -&gt; HandBrake Encoding\n -&gt; Post-Encode Skripte/Ketten\n -&gt; Fertig oder Fehler\n</code></pre>"},{"location":"pipeline/post-encode-scripts/#auswahl-im-review","title":"Auswahl im Review","text":"<p>Im Review-Panel kannst du getrennt w\u00e4hlen:</p> <ul> <li><code>selectedPreEncodeScriptIds</code></li> <li><code>selectedPostEncodeScriptIds</code></li> <li><code>selectedPreEncodeChainIds</code></li> <li><code>selectedPostEncodeChainIds</code></li> </ul>"},{"location":"pipeline/post-encode-scripts/#fehlerverhalten","title":"Fehlerverhalten","text":"<ul> <li>Pre-Encode-Fehler stoppen die Kette und f\u00fchren zu <code>Fehler</code>.</li> <li>Post-Encode-Fehler stoppen die restlichen Post-Schritte; Job kann dennoch <code>Fertig</code> sein (mit Fehlerzusatz im Status/Log).</li> </ul>"},{"location":"pipeline/post-encode-scripts/#verfugbare-umgebungsvariablen","title":"Verf\u00fcgbare Umgebungsvariablen","text":"<p>Beim Script-Run werden gesetzt:</p> <ul> <li><code>RIPSTER_SCRIPT_RUN_AT</code></li> <li><code>RIPSTER_JOB_ID</code></li> <li><code>RIPSTER_JOB_TITLE</code></li> <li><code>RIPSTER_MODE</code></li> <li><code>RIPSTER_INPUT_PATH</code></li> <li><code>RIPSTER_OUTPUT_PATH</code></li> <li><code>RIPSTER_RAW_PATH</code></li> <li><code>RIPSTER_SCRIPT_ID</code></li> <li><code>RIPSTER_SCRIPT_NAME</code></li> <li><code>RIPSTER_SCRIPT_SOURCE</code></li> </ul>"},{"location":"pipeline/post-encode-scripts/#skript-ketten","title":"Skript-Ketten","text":"<p>Ketten unterst\u00fctzen zwei Step-Typen:</p> <ul> <li><code>script</code> (f\u00fchrt ein hinterlegtes Skript aus)</li> <li><code>wait</code> (wartet <code>waitSeconds</code>)</li> </ul> <p>Bei Fehler in einem Script-Step wird die Kette abgebrochen.</p>"},{"location":"pipeline/post-encode-scripts/#testlaufe","title":"Testl\u00e4ufe","text":"<ul> <li>Skript testen: <code>POST /api/settings/scripts/:id/test</code></li> <li>Kette testen: <code>POST /api/settings/script-chains/:id/test</code></li> </ul> <p>Ergebnisse enthalten Erfolg/Exit-Code, Laufzeit und stdout/stderr.</p>"},{"location":"pipeline/workflow/","title":"Workflow &amp; Zust\u00e4nde","text":"<p>Ripster steuert den Ablauf als Zustandsmaschine.</p>"},{"location":"pipeline/workflow/#zustandsdiagramm-vereinfacht","title":"Zustandsdiagramm (vereinfacht)","text":"<pre><code>flowchart LR\n A[Bereit] --&gt; B[Medium erkannt]\n B --&gt; C[Analyse]\n C --&gt; D[Metadatenauswahl]\n D --&gt; E[Startbereit]\n E --&gt; F[Rippen]\n E --&gt; G[Mediainfo-Pruefung]\n G --&gt; H[Warte auf Auswahl]\n H --&gt; G\n G --&gt; I[Bereit zum Encodieren]\n I --&gt; J[Encodieren]\n J --&gt; K[Fertig]\n J --&gt; L[Fehler]\n F --&gt; L\n F --&gt; M[Abgebrochen]</code></pre>"},{"location":"pipeline/workflow/#statusliste-gui-anzeige","title":"Statusliste (GUI-Anzeige)","text":"Status in der GUI Bedeutung <code>Bereit</code> Wartet auf Disc <code>Medium erkannt</code> Disc wurde erkannt <code>Analyse</code> MakeMKV-Analyse l\u00e4uft <code>Metadatenauswahl</code> Metadaten m\u00fcssen best\u00e4tigt werden <code>Warte auf Auswahl</code> Playlist-Auswahl ist erforderlich <code>Warte auf Auswahl</code> auch f\u00fcr RAW-Entscheidung bei vorhandenen Quelldaten genutzt <code>Startbereit</code> kurzer \u00dcbergang vor Start <code>Rippen</code> MakeMKV-Rip l\u00e4uft <code>Mediainfo-Pruefung</code> Titel/Spuren werden ausgewertet <code>Bereit zum Encodieren</code> Review ist bereit <code>Encodieren</code> HandBrake l\u00e4uft <code>CD-Metadatenauswahl</code> CD-Metadaten m\u00fcssen best\u00e4tigt werden <code>CD-Startbereit</code> CD-Job wartet auf Start <code>CD-Analyse</code> CD-Track-/Strukturaufbereitung <code>CD-Rippen</code> Audio-CD-Rip l\u00e4uft <code>CD-Encodieren</code> CD-Encode l\u00e4uft <code>Fertig</code> erfolgreich abgeschlossen <code>Abgebrochen</code> manuell oder technisch abgebrochen <code>Fehler</code> fehlgeschlagen"},{"location":"pipeline/workflow/#typische-pfade","title":"Typische Pfade","text":""},{"location":"pipeline/workflow/#standardfall-kein-vorhandenes-raw","title":"Standardfall (kein vorhandenes RAW)","text":"<ol> <li>Medium erkannt</li> <li>Analyse + Metadaten</li> <li>Rippen</li> <li>Mediainfo-Pruefung</li> <li>Bereit zum Encodieren</li> <li>Encodieren</li> <li>Fertig</li> </ol>"},{"location":"pipeline/workflow/#vorhandenes-raw","title":"Vorhandenes RAW","text":"<p><code>Startbereit</code> springt direkt zu <code>Mediainfo-Pruefung</code> (kein neuer Rip).</p>"},{"location":"pipeline/workflow/#mehrdeutige-blu-ray-playlist","title":"Mehrdeutige Blu-ray-Playlist","text":"<p><code>Mediainfo-Pruefung</code> -&gt; <code>Warte auf Auswahl</code> bis Playlist best\u00e4tigt wurde.</p>"},{"location":"pipeline/workflow/#vorhandenes-raw-mit-nutzerentscheidung","title":"Vorhandenes RAW mit Nutzerentscheidung","text":"<p><code>Metadatenauswahl</code> -&gt; <code>Warte auf Auswahl</code> bis Entscheidung f\u00fcr Weiterverarbeitung (<code>continue</code>) oder Neustart getroffen wurde.</p>"},{"location":"pipeline/workflow/#cd-flow","title":"CD-Flow","text":"<p><code>CD-Metadatenauswahl</code> -&gt; <code>CD-Startbereit</code> -&gt; <code>CD-Rippen</code> -&gt; <code>CD-Encodieren</code> -&gt; <code>Fertig</code></p>"},{"location":"pipeline/workflow/#queue-verhalten","title":"Queue-Verhalten","text":"<p>Wenn der Wert <code>Parallele Jobs</code> erreicht ist:</p> <ul> <li>neue Starts werden als Queue-Eintr\u00e4ge abgelegt</li> <li>die Queue kann zus\u00e4tzlich Nicht-Job-Eintr\u00e4ge enthalten (<code>Skript</code>, <code>Kette</code>, <code>Warten</code>)</li> <li>Reihenfolge ist per UI/API \u00e4nderbar</li> </ul>"},{"location":"pipeline/workflow/#abbruch-wiederaufnahme-neustart","title":"Abbruch, Wiederaufnahme, Neustart","text":"<ul> <li><code>Abbrechen</code>: laufenden Job stoppen oder Queue-Eintrag entfernen</li> <li><code>Retry Rippen</code>: Fehler-/Abbruch-Job erneut starten</li> <li><code>RAW neu encodieren</code>: aus vorhandenem RAW neu encodieren</li> <li><code>Review neu starten</code>: Review aus RAW neu aufbauen</li> <li><code>Encode neu starten</code>: Encoding mit letzter best\u00e4tigter Auswahl neu starten</li> </ul>"},{"location":"tools/","title":"Anhang: Externe Tools","text":"<p>Ripster orchestriert externe CLI-Tools. Dieser Abschnitt erkl\u00e4rt deren Rolle im Gesamtsystem.</p> <ul> <li> <p> MakeMKV</p> <p>Disc-Analyse und Ripping.</p> <p> MakeMKV</p> </li> <li> <p> HandBrake</p> <p>Video-Encoding inklusive Preset-Logik.</p> <p> HandBrake</p> </li> <li> <p> MediaInfo</p> <p>Track-/Containeranalyse f\u00fcr Review und Auswahl.</p> <p> MediaInfo</p> </li> </ul>"},{"location":"tools/handbrake/","title":"HandBrake","text":"<p>Ripster verwendet <code>HandBrakeCLI</code> f\u00fcr Scan und Encode.</p>"},{"location":"tools/handbrake/#verwendete-aufrufe","title":"Verwendete Aufrufe","text":""},{"location":"tools/handbrake/#scan-review-aufbau","title":"Scan (Review-Aufbau)","text":"<pre><code>HandBrakeCLI --scan --json -i &lt;input&gt; -t 0\n</code></pre>"},{"location":"tools/handbrake/#encode-vereinfacht","title":"Encode (vereinfacht)","text":"<pre><code>HandBrakeCLI \\\n -i &lt;input&gt; \\\n -o &lt;output&gt; \\\n -t &lt;titleId&gt; \\\n -Z \"&lt;preset&gt;\" \\\n &lt;extra-args&gt; \\\n -a &lt;audioTrackIds|none&gt; \\\n -s &lt;subtitleTrackIds|none&gt;\n</code></pre> <p>Optional erg\u00e4nzt Ripster:</p> <ul> <li><code>--subtitle-burned=&lt;id&gt;</code></li> <li><code>--subtitle-default=&lt;id&gt;</code></li> <li><code>--subtitle-forced=&lt;id&gt;</code> oder <code>--subtitle-forced</code></li> </ul>"},{"location":"tools/handbrake/#presets-auslesen","title":"Presets auslesen","text":"<p>Ripster liest Presets mit:</p> <pre><code>HandBrakeCLI -z\n</code></pre>"},{"location":"tools/handbrake/#relevante-felder-in-settings","title":"Relevante Felder in <code>Settings</code>","text":"Feldname in der GUI Bedeutung <code>HandBrake Kommando</code> CLI-Binary <code>HandBrake Preset</code> (Blu-ray/DVD) profilspezifisches Preset <code>HandBrake Extra Args</code> (Blu-ray/DVD) profilspezifische Zusatzargumente <code>Ausgabeformat</code> (Blu-ray/DVD) Dateiendung der finalen Datei <code>Encode-Neustart: unvollst\u00e4ndige Ausgabe l\u00f6schen</code> unvollst\u00e4ndige Ausgabe bei Neustart l\u00f6schen"},{"location":"tools/handbrake/#fortschritts-parsing","title":"Fortschritts-Parsing","text":"<p>Ripster parst HandBrake-Stderr (Prozent/ETA/Detail) und sendet WebSocket-Progress (<code>PIPELINE_PROGRESS</code>).</p>"},{"location":"tools/handbrake/#troubleshooting","title":"Troubleshooting","text":"<ul> <li>Preset nicht gefunden: Preset-Namen mit <code>HandBrakeCLI -z</code> pr\u00fcfen</li> <li>sehr langsames Encoding: Preset/Extra-Args pr\u00fcfen (z. B. <code>--encoder-preset</code>)</li> </ul> <p>Das Produktions-Installer-Script <code>install.sh</code> 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.</p>"},{"location":"tools/makemkv/","title":"MakeMKV","text":"<p>Ripster nutzt <code>makemkvcon</code> f\u00fcr Disc-Analyse und Rip.</p>"},{"location":"tools/makemkv/#verwendete-aufrufe","title":"Verwendete Aufrufe","text":""},{"location":"tools/makemkv/#analyse","title":"Analyse","text":"<pre><code>makemkvcon -r info &lt;source&gt;\n</code></pre> <p><code>&lt;source&gt;</code> ist typischerweise:</p> <ul> <li><code>disc:&lt;index&gt;</code> (Auto-Modus)</li> <li><code>dev:/dev/sr0</code> (explicit)</li> <li><code>file:&lt;path&gt;</code> (Datei/Ordner-Analyse)</li> </ul>"},{"location":"tools/makemkv/#rip-mkv-modus","title":"Rip (MKV-Modus)","text":"<pre><code>makemkvcon mkv &lt;source&gt; &lt;title-or-all&gt; &lt;rawDir&gt; [--minlength=...] [...extraArgs]\n</code></pre>"},{"location":"tools/makemkv/#rip-backup-modus","title":"Rip (Backup-Modus)","text":"<pre><code>makemkvcon backup &lt;source&gt; &lt;rawDir&gt; --decrypt\n</code></pre>"},{"location":"tools/makemkv/#registrierungsschlussel-optional","title":"Registrierungsschl\u00fcssel (optional)","text":"<p>Wenn in <code>Settings</code> ein <code>MakeMKV Key</code> gesetzt ist, synchronisiert Ripster ihn nach:</p> <pre><code>~/.MakeMKV/settings.conf\n</code></pre> <p>Format:</p> <pre><code>app_Key = \"product-key\"\n</code></pre> <p>Zus\u00e4tzlich zeigt die UI unterhalb des Feldes den aktuellen Betakey an, der per Button in das Eingabefeld \u00fcbernommen werden kann.</p>"},{"location":"tools/makemkv/#relevante-felder-in-settings","title":"Relevante Felder in <code>Settings</code>","text":"Feldname in der GUI Bedeutung <code>MakeMKV Kommando</code> CLI-Binary <code>MakeMKV Source Index</code> Source-Index im Auto-Modus <code>Minimale Titellaenge (Minuten)</code> Mindestlaufzeitfilter <code>MakeMKV Rip Modus</code> (Blu-ray/DVD) <code>mkv</code> oder <code>backup</code> <code>MakeMKV Analyze Extra Args</code> (Blu-ray/DVD) Zusatzargumente f\u00fcr Analyse <code>MakeMKV Rip Extra Args</code> (Blu-ray/DVD) Zusatzargumente f\u00fcr Rip"},{"location":"tools/makemkv/#hinweise","title":"Hinweise","text":"<ul> <li>Blu-ray-Backups werden oft f\u00fcr robuste Playlist-Analyse genutzt.</li> <li>MakeMKV-Ausgaben werden geparst und als <code>makemkvInfo</code> im Job gespeichert.</li> </ul>"},{"location":"tools/mediainfo/","title":"MediaInfo","text":"<p>Ripster nutzt <code>mediainfo</code> zur JSON-Analyse von Medien-Dateien.</p>"},{"location":"tools/mediainfo/#aufruf","title":"Aufruf","text":"<pre><code>mediainfo --Output=JSON &lt;input&gt;\n</code></pre> <p>Der Input ist typischerweise eine RAW-Datei oder ein vom Workflow gew\u00e4hlter Inputpfad.</p>"},{"location":"tools/mediainfo/#verwendung-in-ripster","title":"Verwendung in Ripster","text":"<ul> <li>Track-/Codec-Metadaten f\u00fcr Review-Plan</li> <li>Fallback-Informationen in bestimmten Analysepfaden</li> <li>Persistenz als <code>mediainfoInfo</code> im Job</li> </ul>"},{"location":"tools/mediainfo/#relevante-settings","title":"Relevante Settings","text":"Key Bedeutung <code>mediainfo_command</code> CLI-Binary <code>mediainfo_extra_args_bluray</code> / <code>_dvd</code> profilspezifische Zusatzargumente"},{"location":"tools/mediainfo/#troubleshooting","title":"Troubleshooting","text":"<ul> <li>JSON-Test: <code>mediainfo --Output=JSON &lt;datei&gt;</code></li> <li>unbekannte Sprache erscheint oft als <code>und</code> (undetermined)</li> </ul>"},{"location":"workflows/","title":"Workflows aus Nutzersicht","text":"<p>Diese Seite beschreibt die produktiven Abl\u00e4ufe aus Sicht der Benutzer: welche Entscheidung wann anf\u00e4llt, welche Jobs oder Container entstehen und welche Settings den Ablauf sichtbar beeinflussen.</p>"},{"location":"workflows/#gemeinsame-grundlagen","title":"Gemeinsame Grundlagen","text":""},{"location":"workflows/#typische-statuskette","title":"Typische Statuskette","text":"<p><code>Medium erkannt</code> -&gt; <code>Analyse</code> -&gt; <code>Metadatenauswahl</code> -&gt; <code>Startbereit</code> -&gt; <code>Rippen</code> -&gt; <code>Mediainfo-Pr\u00fcfung</code> -&gt; <code>Bereit zum Encodieren</code> -&gt; <code>Encodieren</code> -&gt; <code>Fertig</code></p> <p>Wichtige Abweichungen:</p> <ul> <li>bei vorhandenem RAW: Sprung direkt in RAW-Entscheidung oder Review</li> <li>bei mehrdeutigen Blu-rays/DVDs: <code>Warte auf Auswahl</code> f\u00fcr Playlist- oder Titelauswahl</li> <li>bei Fehler oder Abbruch: <code>Fehler</code> oder <code>Abgebrochen</code> mit Folgeaktionen</li> <li>bei Audio-CDs und Audiobooks: eigener Spezialflow innerhalb derselben Gesamtpipeline</li> </ul>"},{"location":"workflows/#welche-settings-fast-uberall-hineinspielen","title":"Welche Settings fast \u00fcberall hineinspielen","text":"<p>Die wichtigsten globalen Einflussfaktoren:</p> <ul> <li><code>Parallele Jobs</code></li> <li><code>Max. parallele Audio CD Jobs</code></li> <li><code>Max. Encodes gesamt (medienunabh\u00e4ngig)</code></li> <li><code>Audio CDs: Queue-Reihenfolge \u00fcberspringen</code></li> <li><code>PushOver</code>-Ereignisse</li> <li>Pfade, Templates und Owner-Felder</li> </ul> <p>F\u00fcr Disc-Video zus\u00e4tzlich:</p> <ul> <li><code>Minimale Titell\u00e4nge (Minuten)</code></li> <li><code>TMDb Runtime-Abzug f\u00fcr Playlistfilter (%)</code></li> <li><code>HandBrake Preset</code></li> <li><code>HandBrake Extra Args</code></li> <li><code>Review Audio-Sprachen (...)</code></li> <li><code>Review UT-Sprachen (...)</code></li> <li>Standard-Zuordnungen aus <code>Settings -&gt; Encode-Presets</code></li> </ul>"},{"location":"workflows/#workflow-a-film-von-disc-blu-ray-dvd","title":"Workflow A: Film von Disc (Blu-ray / DVD)","text":""},{"location":"workflows/#1-disc-analysieren-und-tmdb-metadaten-wahlen","title":"1. Disc analysieren und TMDb-Metadaten w\u00e4hlen","text":"<ol> <li>Im <code>Ripper</code> <code>Analyse starten</code></li> <li>im Metadaten-Dialog Film ausw\u00e4hlen</li> <li><code>Auswahl \u00fcbernehmen</code></li> </ol> <p>Wirkung:</p> <ul> <li>der Job wird als Film-Workflow gef\u00fchrt</li> <li>Film-Metadaten, Poster und Fingerprint werden gesetzt</li> </ul> <p>Relevante Settings:</p> <ul> <li><code>TMDb Read Access Token</code></li> <li><code>Film-Sprache</code></li> <li><code>Fallback Sprache</code></li> </ul>"},{"location":"workflows/#2-duplikatfall-entscheiden","title":"2. Duplikatfall entscheiden","text":"<p>Wenn ein Film mit gleichem Fingerprint bereits existiert:</p> <ol> <li><code>\u00dcbernahme erzwingen</code>: neuer unabh\u00e4ngiger Film-Job</li> <li><code>Multipart movie</code>: neuer Job wird mit bestehendem Film zu einem Multipart-Container verkn\u00fcpft</li> </ol> <p>Bei Multipart gilt:</p> <ul> <li>beide Discs brauchen unterschiedliche Disc-Nummern</li> <li>gleiche Disc-Nummern blockieren den Vorgang</li> </ul>"},{"location":"workflows/#3-raw-verzeichnis-und-raw-entscheidung","title":"3. RAW-Verzeichnis und RAW-Entscheidung","text":"<p>Wenn noch kein passendes RAW vorhanden ist:</p> <ul> <li>Ripster legt ein neues RAW-Verzeichnis an</li> </ul> <p>Wenn bereits ein passendes RAW gefunden wird:</p> <ul> <li>der Job geht in <code>Warte auf Auswahl</code></li> <li>du entscheidest, ob das vorhandene RAW weiterverwendet oder neu gerippt wird</li> </ul> <p>Relevante Settings:</p> <ul> <li><code>raw_dir_bluray</code>, <code>raw_dir_dvd</code></li> <li><code>raw_dir_bluray_owner</code>, <code>raw_dir_dvd_owner</code></li> </ul>"},{"location":"workflows/#4-playlist-oder-titelauswahl","title":"4. Playlist- oder Titelauswahl","text":"<p>Bei bestimmten Discs ist nach der Metadatenphase eine manuelle Auswahl n\u00f6tig:</p> <ul> <li>Playlist-Auswahl</li> <li>HandBrake-Titelauswahl</li> <li>bei Serien-Grenzf\u00e4llen PlayAll- oder Doppelfolgen-Entscheidung</li> </ul> <p>Das ist der aktuelle <code>playlistflow</code>.</p> <p>Relevante Settings:</p> <ul> <li><code>Minimale Titell\u00e4nge (Minuten)</code></li> <li><code>TMDb Runtime-Abzug f\u00fcr Playlistfilter (%)</code></li> <li><code>Bei manueller Auswahl senden</code></li> </ul> <p>Praxis:</p> <ul> <li>zu hoher Mindestwert blendet legitime Alternativfassungen aus</li> <li>ein kleiner Runtime-Abzug hilft bei Discs, deren Hauptfilm minimal unter der TMDb-Laufzeit liegt</li> </ul>"},{"location":"workflows/#5-review-und-encode","title":"5. Review und Encode","text":"<p>Im Zustand <code>Bereit zum Encodieren</code> entscheidest du:</p> <ul> <li>welcher Titel encodiert wird</li> <li>welche Audio-Spuren \u00fcbernommen werden</li> <li>welche Untertitel \u00fcbernommen, erzwungen oder eingebrannt werden</li> <li>welches Preset gilt</li> <li>welche Pre-/Post-Encode-Skripte oder Ketten mitlaufen</li> </ul> <p>Relevante Settings:</p> <ul> <li><code>HandBrake Preset</code></li> <li><code>HandBrake Extra Args</code></li> <li><code>Review Audio-Sprachen (Blu-ray Film)</code> oder <code>Review Audio-Sprachen (DVD Film)</code></li> <li><code>Review UT-Sprachen (Blu-ray Film)</code> oder <code>Review UT-Sprachen (DVD Film)</code></li> <li><code>Ausgabeformat</code></li> <li>Standard-Userpreset f\u00fcr Film unter <code>Settings -&gt; Encode-Presets</code></li> </ul>"},{"location":"workflows/#6-finale-ausgabe","title":"6. Finale Ausgabe","text":"<p>Finale Ausgabe:</p> <ul> <li>Zielordner: <code>movie_dir_bluray</code> oder <code>movie_dir_dvd</code></li> <li>Dateiname und Ordner: <code>output_template_bluray</code> oder <code>output_template_dvd</code></li> </ul> <p>Optional:</p> <ul> <li><code>.nfo</code> direkt nach Encode</li> </ul> <p>Relevante Settings:</p> <ul> <li><code>movie_dir_bluray</code>, <code>movie_dir_dvd</code></li> <li><code>movie_dir_bluray_owner</code>, <code>movie_dir_dvd_owner</code></li> <li><code>output_template_bluray</code>, <code>output_template_dvd</code></li> <li><code>generate_nfo_after_encode</code></li> </ul>"},{"location":"workflows/#workflow-b-serie-von-disc-blu-ray-dvd","title":"Workflow B: Serie von Disc (Blu-ray / DVD)","text":""},{"location":"workflows/#1-serienmodus-festlegen","title":"1. Serienmodus festlegen","text":"<ol> <li>Disc analysieren</li> <li>im Metadaten-Dialog Serienmetadaten w\u00e4hlen</li> <li><code>Disc-Nummer</code> setzen</li> </ol> <p>Wirkung:</p> <ul> <li>Ripster arbeitet als Serien-Workflow</li> <li>Seriencontainer wird gesucht oder angelegt</li> <li>der Job wird als Child unter diesem Container gef\u00fchrt</li> </ul>"},{"location":"workflows/#2-serien-raw-und-staffelkontext","title":"2. Serien-RAW und Staffelkontext","text":"<p>F\u00fcr Serien bevorzugt Ripster eigene Serien-RAW-Verzeichnisse:</p> <ul> <li><code>raw_dir_bluray_series</code></li> <li><code>raw_dir_dvd_series</code></li> </ul> <p>Falls leer:</p> <ul> <li>Fallback auf <code>raw_dir_bluray</code> bzw. <code>raw_dir_dvd</code></li> </ul>"},{"location":"workflows/#3-episodenprufung-und-multi-episode-falle","title":"3. Episodenpr\u00fcfung und Multi-Episode-F\u00e4lle","text":"<p>In der Review werden Episoden oder Mehrfachfolgen aufgel\u00f6st.</p> <p>Ausgabevarianten:</p> <ul> <li>Einzel-Episode</li> <li>Multi-Episode-Datei</li> </ul> <p>Relevante Settings:</p> <ul> <li><code>output_template_bluray_series_episode</code></li> <li><code>output_template_bluray_series_multi_episode</code></li> <li><code>output_template_dvd_series_episode</code></li> <li><code>output_template_dvd_series_multi_episode</code></li> <li><code>series_dir_bluray</code></li> <li><code>series_dir_dvd</code></li> </ul>"},{"location":"workflows/#4-playlistflow-auch-bei-serien","title":"4. Playlistflow auch bei Serien","text":"<p>Auch Serien k\u00f6nnen vor der Review in eine Playlist- oder Titelauswahl laufen.</p> <p>Zus\u00e4tzlich wirken:</p> <ul> <li><code>Review Audio-Sprachen (Blu-ray Serie)</code> / <code>Review Audio-Sprachen (DVD Serie)</code></li> <li><code>Review UT-Sprachen (Blu-ray Serie)</code> / <code>Review UT-Sprachen (DVD Serie)</code></li> <li>Serien-Default-Presets unter <code>Settings -&gt; Encode-Presets</code></li> </ul>"},{"location":"workflows/#workflow-c-multipart-film","title":"Workflow C: Multipart-Film","text":""},{"location":"workflows/#wann-der-flow-gedacht-ist","title":"Wann der Flow gedacht ist","text":"<ul> <li>gleicher Film auf mehreren Discs</li> <li>die Discs sollen in Historie und Detailansichten zusammengeh\u00f6ren</li> </ul>"},{"location":"workflows/#ablauf","title":"Ablauf","text":"<ol> <li>Film-Metadaten w\u00e4hlen</li> <li>Duplikatdialog <code>Multipart movie</code></li> <li>Disc-Nummern f\u00fcr bestehenden und neuen Job festlegen</li> </ol> <p>Wirkung:</p> <ul> <li><code>multipart_movie_container</code> wird angelegt oder wiederverwendet</li> <li>die Discs werden als Child-Jobs darunter gef\u00fchrt</li> <li>zus\u00e4tzlich wird ein Merge-Job vorbereitet</li> </ul> <p>Relevante Settings:</p> <ul> <li><code>mkvmerge_command</code></li> <li>Film-Output-Templates</li> <li>Queue-Limits, falls mehrere Discs parallel weiterverarbeitet werden</li> </ul>"},{"location":"workflows/#workflow-d-audio-cd","title":"Workflow D: Audio-CD","text":""},{"location":"workflows/#1-toc-lesen-und-metadaten-wahlen","title":"1. TOC lesen und Metadaten w\u00e4hlen","text":"<ol> <li>Audio-CD analysieren</li> <li>Tracks pr\u00fcfen</li> <li>Metadaten aus MusicBrainz \u00fcbernehmen oder manuell anpassen</li> </ol>"},{"location":"workflows/#2-trackauswahl-und-format","title":"2. Trackauswahl und Format","text":"<p>Vor dem Start legst du fest:</p> <ul> <li>welche Tracks \u00fcbernommen werden</li> <li>welches Ausgabeformat gilt</li> <li>welche Formatoptionen genutzt werden</li> <li>welche Pre-/Post-Encode-Skripte oder Ketten mitlaufen</li> </ul>"},{"location":"workflows/#3-rip-und-encode","title":"3. Rip und Encode","text":"<p>Die CD l\u00e4uft anschlie\u00dfend als Track-f\u00fcr-Track-Flow:</p> <p><code>CD-Metadatenauswahl</code> -&gt; <code>CD-Startbereit</code> -&gt; <code>CD-Rippen</code> -&gt; <code>CD-Encodieren</code> -&gt; <code>Fertig</code></p> <p>Relevante Settings:</p> <ul> <li><code>raw_dir_cd</code></li> <li><code>movie_dir_cd</code></li> <li><code>raw_dir_cd_owner</code></li> <li><code>movie_dir_cd_owner</code></li> <li><code>cd_output_template</code></li> <li><code>cdparanoia_command</code></li> <li><code>Max. parallele Audio CD Jobs</code></li> <li><code>Audio CDs: Queue-Reihenfolge \u00fcberspringen</code></li> </ul>"},{"location":"workflows/#workflow-e-converter","title":"Workflow E: Converter","text":""},{"location":"workflows/#1-dateien-bereitstellen","title":"1. Dateien bereitstellen","text":"<p>Dateien gelangen in den Converter \u00fcber:</p> <ul> <li>Upload</li> <li>bestehende Ordner im <code>converter_raw_dir</code></li> <li>manuelle Dateiverwaltung im Explorer</li> </ul>"},{"location":"workflows/#2-jobs-aus-auswahl-erzeugen","title":"2. Jobs aus Auswahl erzeugen","text":"<ul> <li>Video und ISO: immer ein Job pro Datei</li> <li>Audio: ein Job pro Datei oder gemeinsamer Audio-Job</li> </ul>"},{"location":"workflows/#3-job-konfigurieren-und-starten","title":"3. Job konfigurieren und starten","text":"<p>Je nach Medium:</p> <ul> <li>Video/ISO: Review mit Track- und Preset-Auswahl</li> <li>Audio: direkte Format- und Zielkonfiguration</li> </ul> <p>Relevante Settings:</p> <ul> <li><code>converter_scan_extensions</code></li> <li><code>converter_polling_enabled</code></li> <li><code>converter_polling_interval</code></li> <li><code>converter_raw_dir</code></li> <li><code>converter_movie_dir</code></li> <li><code>converter_audio_dir</code></li> <li><code>converter_output_template_video</code></li> <li><code>converter_output_template_audio</code></li> <li>globale Queue-Limits</li> </ul>"},{"location":"workflows/#workflow-f-audiobooks","title":"Workflow F: Audiobooks","text":""},{"location":"workflows/#1-aax-hochladen","title":"1. AAX hochladen","text":"<ol> <li>Datei hochladen</li> <li>Metadaten und Kapitel aufbauen lassen</li> <li>bei Bedarf Activation Bytes kl\u00e4ren</li> </ol>"},{"location":"workflows/#2-ausgabeformat-wahlen","title":"2. Ausgabeformat w\u00e4hlen","text":"<ul> <li><code>m4b</code>: eine Datei</li> <li><code>mp3</code>: eine Datei pro Kapitel</li> <li><code>flac</code>: eine Datei pro Kapitel</li> </ul>"},{"location":"workflows/#3-kapitel-und-skripte-prufen","title":"3. Kapitel und Skripte pr\u00fcfen","text":"<p>Vor dem Start anpassbar:</p> <ul> <li>Kapitelnamen</li> <li>Pre-Encode-Skripte und -Ketten</li> <li>Post-Encode-Skripte und -Ketten</li> </ul> <p>Relevante Settings:</p> <ul> <li><code>raw_dir_audiobook</code></li> <li><code>movie_dir_audiobook</code></li> <li><code>audiobook_raw_template</code></li> <li><code>output_template_audiobook</code></li> <li><code>output_chapter_template_audiobook</code></li> <li><code>ffprobe_command</code></li> <li><code>ffmpeg_command</code></li> <li>globale Queue-Limits</li> </ul>"},{"location":"workflows/#workflow-g-nachbearbeitung-in-der-historie","title":"Workflow G: Nachbearbeitung in der Historie","text":"<p>Typische Folgeaktionen:</p> <ul> <li><code>TMDb neu zuweisen</code></li> <li><code>Review neu starten</code></li> <li><code>RAW neu encodieren</code></li> <li><code>Encode neu starten</code></li> <li><code>Retry Rippen</code></li> <li><code>Download</code> als ZIP einreihen</li> </ul> <p>Besonders wichtig:</p> <ul> <li><code>Encode neu starten</code> verwendet den letzten best\u00e4tigten Plan</li> <li><code>handbrake_restart_delete_incomplete_output</code> entscheidet, ob unvollst\u00e4ndige Ausgaben vorher gel\u00f6scht werden</li> </ul>"},{"location":"workflows/#workflow-h-downloads-und-recovery","title":"Workflow H: Downloads und Recovery","text":""},{"location":"workflows/#downloads","title":"Downloads","text":"<p>Aus <code>Historie</code> k\u00f6nnen ZIPs f\u00fcr:</p> <ul> <li><code>RAW</code></li> <li><code>Output</code></li> </ul> <p>erstellt werden.</p> <p>Relevante Settings:</p> <ul> <li><code>download_dir</code></li> <li><code>download_dir_owner</code></li> </ul>"},{"location":"workflows/#database-expert","title":"Database (Expert)","text":"<p>Die Recovery-Seite hilft bei orphan RAW:</p> <ul> <li><code>RAW pr\u00fcfen</code></li> <li><code>Job anlegen</code></li> </ul> <p>So lassen sich vorhandene RAW-Verzeichnisse wieder in einen normalen Workflow zur\u00fcckf\u00fchren.</p>"},{"location":"workflows/#tmdb-migration","title":"TMDb Migration","text":"<p>F\u00fcr \u00e4ltere Bestandsjobs gibt es die Sonderseite <code>/tmdb-migration</code>, um mehrere Jobs nacheinander auf den heutigen TMDb-Stand zu bringen.</p>"}]}