docs: Doku für Skript-Integration und neue Pipeline-Zustände

This commit is contained in:
2026-03-05 10:28:21 +00:00
parent fe2ffbbe07
commit 23acea4773
5 changed files with 268 additions and 70 deletions

View File

@@ -29,23 +29,33 @@ Das Backend ist in Node.js/Express geschrieben und in **Services** aufgeteilt, d
### Zustandsübergänge ### Zustandsübergänge
<div class="pipeline-diagram">
```mermaid ```mermaid
stateDiagram-v2 flowchart LR
[*] --> IDLE START(( )) --> IDLE
IDLE --> ANALYZING: analyzeDisc() IDLE -->|analyzeDisc()| ANALYZING[ANALYZING]
ANALYZING --> METADATA_SELECTION: MakeMKV fertig ANALYZING -->|MakeMKV fertig| META[METADATA\nSELECTION]
METADATA_SELECTION --> READY_TO_START: selectMetadata() META -->|selectMetadata()| RTS[READY_TO\nSTART]
READY_TO_START --> RIPPING: startJob() RTS -->|startJob()| RIP[RIPPING]
RIPPING --> MEDIAINFO_CHECK: MKV erstellt RIP -->|MKV erstellt| MIC[MEDIAINFO\nCHECK]
MEDIAINFO_CHECK --> READY_TO_ENCODE: Tracks analysiert MIC -->|Tracks analysiert| RTE[READY_TO\nENCODE]
READY_TO_ENCODE --> ENCODING: confirmEncode() RTE -->|confirmEncode()| ENC[ENCODING]
ENCODING --> FINISHED: HandBrake fertig ENC -->|HandBrake fertig| FIN([FINISHED])
ENCODING --> ERROR: Fehler ENC -->|Fehler| ERR([ERROR])
RIPPING --> ERROR: Fehler RIP -->|Fehler| ERR
ERROR --> IDLE: retryJob() / cancel ERR -->|retryJob() / cancel| IDLE
FINISHED --> IDLE: cancel / neue Disc FIN -->|cancel / neue Disc| IDLE
style FIN fill:#e8f5e9,stroke:#66bb6a,color:#2e7d32
style ERR fill:#ffebee,stroke:#ef5350,color:#c62828
style ENC fill:#f3e5f5,stroke:#ab47bc,color:#6a1b9a
style RIP fill:#e3f2fd,stroke:#42a5f5,color:#1565c0
style MIC fill:#e3f2fd,stroke:#42a5f5,color:#1565c0
``` ```
</div>
--- ---
## diskDetectionService.js ## diskDetectionService.js

View File

@@ -6,25 +6,107 @@ Nach der [Installation](installation.md) und [Konfiguration](configuration.md) f
## Übersicht: Pipeline-Zustände ## Übersicht: Pipeline-Zustände
<div class="pipeline-steps">
<div class="pipeline-step">
<div class="pipeline-step-badge step-idle">●</div>
<div class="pipeline-step-label">IDLE</div>
<div class="pipeline-step-sub">Warten</div>
</div>
<div class="pipeline-step">
<div class="pipeline-step-badge step-idle">1</div>
<div class="pipeline-step-label">DISC_DETECTED</div>
<div class="pipeline-step-sub">Disc erkannt</div>
</div>
<div class="pipeline-step">
<div class="pipeline-step-badge step-running">2</div>
<div class="pipeline-step-label">METADATA_SELECTION</div>
<div class="pipeline-step-sub">Scan &amp; Metadaten</div>
</div>
<div class="pipeline-step">
<div class="pipeline-step-badge step-wait">⚠</div>
<div class="pipeline-step-label">WAITING_FOR_USER_DECISION</div>
<div class="pipeline-step-sub">Playlist wählen<br><em>(nur bei Obfusk.)</em></div>
</div>
<div class="pipeline-step">
<div class="pipeline-step-badge step-user">3</div>
<div class="pipeline-step-label">READY_TO_START</div>
<div class="pipeline-step-sub">Bereit</div>
</div>
<div class="pipeline-step">
<div class="pipeline-step-badge step-running">4</div>
<div class="pipeline-step-label">RIPPING</div>
<div class="pipeline-step-sub">MakeMKV</div>
</div>
<div class="pipeline-step">
<div class="pipeline-step-badge step-running">5</div>
<div class="pipeline-step-label">MEDIAINFO_CHECK</div>
<div class="pipeline-step-sub">HandBrake-Scan</div>
</div>
<div class="pipeline-step">
<div class="pipeline-step-badge step-user">6</div>
<div class="pipeline-step-label">READY_TO_ENCODE</div>
<div class="pipeline-step-sub">Track-Review</div>
</div>
<div class="pipeline-step">
<div class="pipeline-step-badge step-encode">7</div>
<div class="pipeline-step-label">ENCODING</div>
<div class="pipeline-step-sub">HandBrake</div>
</div>
<div class="pipeline-step">
<div class="pipeline-step-badge step-encode">8</div>
<div class="pipeline-step-label">POST_ENCODE_SCRIPTS</div>
<div class="pipeline-step-sub">Skripte<br><em>(optional)</em></div>
</div>
<div class="pipeline-step">
<div class="pipeline-step-badge step-done">✓</div>
<div class="pipeline-step-label">FINISHED</div>
<div class="pipeline-step-sub">Fertig</div>
</div>
</div>
**Legende:** <span style="color:#546e7a">● Warten</span> &nbsp;|&nbsp; <span style="color:#1565c0">■ Läuft automatisch</span> &nbsp;|&nbsp; <span style="color:#3949ab">■ Benutzeraktion</span> &nbsp;|&nbsp; <span style="color:#e65100">⚠ Optional</span> &nbsp;|&nbsp; <span style="color:#6a1b9a">■ Encodierung</span> &nbsp;|&nbsp; <span style="color:#2e7d32">✓ Fertig</span>
??? note "Vollständiges Zustandsdiagramm (inkl. Fehler- &amp; Alternativpfade)"
<div class="pipeline-diagram">
```mermaid ```mermaid
stateDiagram-v2 flowchart LR
direction LR START(( )) --> IDLE
[*] --> IDLE
IDLE --> DISC_DETECTED: Disc eingelegt IDLE -->|Disc erkannt| DD[DISC_DETECTED]
DISC_DETECTED --> METADATA_SELECTION: Analyse gestartet DD -->|Analyse starten| META[METADATA\nSELECTION]
METADATA_SELECTION --> READY_TO_START: Metadaten bestätigt\n(keine Obfuskierung)
METADATA_SELECTION --> WAITING_FOR_USER_DECISION: Obfuskierung erkannt\n→ Playlist wählen META -->|1 Kandidat| RTS[READY_TO\nSTART]
WAITING_FOR_USER_DECISION --> READY_TO_START: Playlist bestätigt META -->|mehrere Kandidaten| WUD[WAITING_FOR\nUSER_DECISION]
READY_TO_START --> MEDIAINFO_CHECK: Vorhandene Raw-Datei\ngefunden WUD -->|Playlist bestätigt| RTS
READY_TO_START --> RIPPING: Ripping starten
RIPPING --> MEDIAINFO_CHECK: MakeMKV fertig RTS -->|Raw vorhanden| MIC[MEDIAINFO\nCHECK]
MEDIAINFO_CHECK --> READY_TO_ENCODE: Track-Review bereit RTS -->|Ripping starten| RIP[RIPPING]
READY_TO_ENCODE --> ENCODING: Encode bestätigt RIP -->|MKV fertig| MIC
ENCODING --> FINISHED: Erfolg RIP -->|Fehler| ERR
ENCODING --> ERROR: Fehler
RIPPING --> ERROR: Fehler MIC --> RTE[READY_TO\nENCODE]
RTE -->|bestätigt| ENC[ENCODING]
ENC -->|mit Skripten| PES[POST_ENCODE\nSCRIPTS]
ENC -->|ohne Skripte| FIN([FINISHED])
ENC -->|Fehler| ERR
PES -->|Erfolg| FIN
PES -->|Fehler| ERR
ERR([ERROR]) -->|Retry / Cancel| IDLE
style FIN fill:#e8f5e9,stroke:#66bb6a,color:#2e7d32
style ERR fill:#ffebee,stroke:#ef5350,color:#c62828
style WUD fill:#fff8e1,stroke:#ffa726,color:#e65100
style PES fill:#f3e5f5,stroke:#ab47bc,color:#6a1b9a
style ENC fill:#f3e5f5,stroke:#ab47bc,color:#6a1b9a
``` ```
</div>
--- ---
## Schritt 1 Ripster starten ## Schritt 1 Ripster starten

View File

@@ -112,19 +112,31 @@ open http://localhost:5173
## Pipeline-Überblick ## Pipeline-Überblick
<div class="pipeline-diagram">
```mermaid ```mermaid
stateDiagram-v2 flowchart LR
[*] --> IDLE IDLE --> DD[DISC_DETECTED]
IDLE --> ANALYZING: Disc erkannt DD --> META[METADATA\nSELECTION]
ANALYZING --> METADATA_SELECTION: Analyse abgeschlossen META -->|1 Kandidat| RTS[READY_TO\nSTART]
METADATA_SELECTION --> READY_TO_START: Metadaten bestätigt META -->|Obfuskierung| WUD[WAITING_FOR\nUSER_DECISION]
READY_TO_START --> RIPPING: Start gedrückt WUD --> RTS
RIPPING --> MEDIAINFO_CHECK: MKV erstellt RTS --> RIP[RIPPING]
MEDIAINFO_CHECK --> READY_TO_ENCODE: Tracks analysiert RTS -->|Raw vorhanden| MIC
READY_TO_ENCODE --> ENCODING: Encode bestätigt RIP --> MIC[MEDIAINFO\nCHECK]
ENCODING --> FINISHED: Encoding fertig MIC --> RTE[READY_TO\nENCODE]
ENCODING --> ERROR: Fehler RTE --> ENC[ENCODING]
RIPPING --> ERROR: Fehler ENC --> PES[POST_ENCODE\nSCRIPTS]
ERROR --> [*] ENC -->|keine Skripte| FIN([FINISHED])
FINISHED --> [*] PES --> FIN
ENC --> ERR([ERROR])
RIP --> ERR
style FIN fill:#e8f5e9,stroke:#66bb6a,color:#2e7d32
style ERR fill:#ffebee,stroke:#ef5350,color:#c62828
style WUD fill:#fff8e1,stroke:#ffa726,color:#e65100
style PES fill:#f3e5f5,stroke:#ab47bc,color:#6a1b9a
style ENC fill:#f3e5f5,stroke:#ab47bc,color:#6a1b9a
``` ```
</div>

View File

@@ -6,40 +6,48 @@ Der Ripping-Workflow von Ripster ist als **State Machine** implementiert. Jeder
## Zustandsdiagramm ## Zustandsdiagramm
<div class="pipeline-diagram">
```mermaid ```mermaid
stateDiagram-v2 flowchart LR
direction TB START(( )) --> IDLE
[*] --> IDLE
IDLE --> DISC_DETECTED: Disc erkannt IDLE -->|Disc erkannt| DD[DISC_DETECTED]
DISC_DETECTED --> METADATA_SELECTION: Analyse starten DD -->|Analyse starten| META[METADATA\nSELECTION]
METADATA_SELECTION --> READY_TO_START: Kein Obfuskierungsverdacht\n(ein Kandidat) META -->|1 Kandidat| RTS[READY_TO\nSTART]
METADATA_SELECTION --> WAITING_FOR_USER_DECISION: Mehrere Playlist-Kandidaten\n→ manuelle Auswahl nötig META -->|mehrere Kandidaten| WUD[WAITING_FOR\nUSER_DECISION]
WUD -->|Playlist bestätigt| RTS
WAITING_FOR_USER_DECISION --> READY_TO_START: Playlist bestätigt RTS -->|Raw vorhanden| MIC[MEDIAINFO\nCHECK]
RTS -->|Ripping starten| RIP[RIPPING]
RIP -->|MKV fertig| MIC
RIP -->|Fehler| ERR
READY_TO_START --> RIPPING: Starten\n(kein Raw vorhanden) MIC --> RTE[READY_TO\nENCODE]
READY_TO_START --> MEDIAINFO_CHECK: Starten\n(Raw bereits vorhanden) RTE -->|Tracks + Skripte\nbestätigt| ENC[ENCODING]
RIPPING --> MEDIAINFO_CHECK: MKV/Backup erstellt ENC -->|mit Skripten| PES[POST_ENCODE\nSCRIPTS]
ENC -->|ohne Skripte| FIN([FINISHED])
ENC -->|Fehler| ERR
MEDIAINFO_CHECK --> READY_TO_ENCODE: Track-Scan\nabgeschlossen PES -->|Erfolg| FIN
PES -->|Fehler| ERR
READY_TO_ENCODE --> ENCODING: Tracks + Skripte\nbestätigt ERR([ERROR]) -->|Retry / Cancel| IDLE
FIN -->|Neue Disc| IDLE
ENCODING --> POST_ENCODE_SCRIPTS: Erfolg\n(Skripte konfiguriert) style FIN fill:#e8f5e9,stroke:#66bb6a,color:#2e7d32
ENCODING --> FINISHED: Erfolg\n(keine Skripte) style ERR fill:#ffebee,stroke:#ef5350,color:#c62828
POST_ENCODE_SCRIPTS --> FINISHED: Alle Skripte\nerfolgt style WUD fill:#fff8e1,stroke:#ffa726,color:#e65100
style PES fill:#f3e5f5,stroke:#ab47bc,color:#6a1b9a
RIPPING --> ERROR: Fehler style ENC fill:#f3e5f5,stroke:#ab47bc,color:#6a1b9a
ENCODING --> ERROR: Fehler style RIP fill:#e3f2fd,stroke:#42a5f5,color:#1565c0
POST_ENCODE_SCRIPTS --> ERROR: Skript-Fehler style MIC fill:#e3f2fd,stroke:#42a5f5,color:#1565c0
ERROR --> IDLE: Abbrechen / Retry
FINISHED --> IDLE: Neue Disc
``` ```
</div>
--- ---
## Zustandsbeschreibungen ## Zustandsbeschreibungen

View File

@@ -37,13 +37,99 @@
font-size: 0.85em; font-size: 0.85em;
} }
/* Mermaid diagrams */ /* Mermaid diagrams standard */
.md-typeset .mermaid { .md-typeset .mermaid {
display: flex; display: flex;
justify-content: center; justify-content: center;
margin: 1.5rem 0; margin: 1.5rem 0;
} }
/* Large pipeline flowchart: horizontal scroll + min-height */
.pipeline-diagram {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
margin: 1.5rem 0;
padding-bottom: 0.5rem;
}
.pipeline-diagram .mermaid {
min-width: 900px;
justify-content: flex-start;
}
.pipeline-diagram .mermaid svg {
min-width: 900px;
height: auto;
}
/* Pipeline step track */
.pipeline-steps {
display: flex;
flex-wrap: nowrap;
gap: 0;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
padding: 1rem 0 1.5rem 0;
margin: 1.5rem 0;
scrollbar-width: thin;
}
.pipeline-step {
display: flex;
flex-direction: column;
align-items: center;
min-width: 110px;
flex: 0 0 auto;
position: relative;
}
.pipeline-step:not(:last-child)::after {
content: '→';
position: absolute;
right: -14px;
top: 22px;
font-size: 1.2rem;
color: var(--md-default-fg-color--light);
z-index: 1;
}
.pipeline-step-badge {
width: 44px;
height: 44px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.75rem;
font-weight: 700;
margin-bottom: 0.5rem;
border: 2px solid transparent;
}
.pipeline-step-label {
font-size: 0.7rem;
text-align: center;
line-height: 1.2;
max-width: 90px;
color: var(--md-default-fg-color);
}
.pipeline-step-sub {
font-size: 0.6rem;
color: var(--md-default-fg-color--light);
text-align: center;
margin-top: 0.2rem;
}
/* Step colors */
.step-idle { background: #eceff1; color: #546e7a; border-color: #90a4ae; }
.step-user { background: #e8eaf6; color: #3949ab; border-color: #7986cb; }
.step-running { background: #e3f2fd; color: #1565c0; border-color: #42a5f5; }
.step-wait { background: #fff8e1; color: #e65100; border-color: #ffa726; }
.step-encode { background: #f3e5f5; color: #6a1b9a; border-color: #ab47bc; }
.step-done { background: #e8f5e9; color: #2e7d32; border-color: #66bb6a; }
.step-error { background: #ffebee; color: #c62828; border-color: #ef5350; }
/* Table improvements */ /* Table improvements */
.md-typeset table:not([class]) { .md-typeset table:not([class]) {
width: 100%; width: 100%;