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
<div class="pipeline-diagram">
```mermaid
stateDiagram-v2
[*] --> IDLE
IDLE --> ANALYZING: analyzeDisc()
ANALYZING --> METADATA_SELECTION: MakeMKV fertig
METADATA_SELECTION --> READY_TO_START: selectMetadata()
READY_TO_START --> RIPPING: startJob()
RIPPING --> MEDIAINFO_CHECK: MKV erstellt
MEDIAINFO_CHECK --> READY_TO_ENCODE: Tracks analysiert
READY_TO_ENCODE --> ENCODING: confirmEncode()
ENCODING --> FINISHED: HandBrake fertig
ENCODING --> ERROR: Fehler
RIPPING --> ERROR: Fehler
ERROR --> IDLE: retryJob() / cancel
FINISHED --> IDLE: cancel / neue Disc
flowchart LR
START(( )) --> IDLE
IDLE -->|analyzeDisc()| ANALYZING[ANALYZING]
ANALYZING -->|MakeMKV fertig| META[METADATA\nSELECTION]
META -->|selectMetadata()| RTS[READY_TO\nSTART]
RTS -->|startJob()| RIP[RIPPING]
RIP -->|MKV erstellt| MIC[MEDIAINFO\nCHECK]
MIC -->|Tracks analysiert| RTE[READY_TO\nENCODE]
RTE -->|confirmEncode()| ENC[ENCODING]
ENC -->|HandBrake fertig| FIN([FINISHED])
ENC -->|Fehler| ERR([ERROR])
RIP -->|Fehler| ERR
ERR -->|retryJob() / cancel| IDLE
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

View File

@@ -6,25 +6,107 @@ Nach der [Installation](installation.md) und [Konfiguration](configuration.md) f
## Ü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
stateDiagram-v2
direction LR
[*] --> IDLE
IDLE --> DISC_DETECTED: Disc eingelegt
DISC_DETECTED --> METADATA_SELECTION: Analyse gestartet
METADATA_SELECTION --> READY_TO_START: Metadaten bestätigt\n(keine Obfuskierung)
METADATA_SELECTION --> WAITING_FOR_USER_DECISION: Obfuskierung erkannt\n→ Playlist wählen
WAITING_FOR_USER_DECISION --> READY_TO_START: Playlist bestätigt
READY_TO_START --> MEDIAINFO_CHECK: Vorhandene Raw-Datei\ngefunden
READY_TO_START --> RIPPING: Ripping starten
RIPPING --> MEDIAINFO_CHECK: MakeMKV fertig
MEDIAINFO_CHECK --> READY_TO_ENCODE: Track-Review bereit
READY_TO_ENCODE --> ENCODING: Encode bestätigt
ENCODING --> FINISHED: Erfolg
ENCODING --> ERROR: Fehler
RIPPING --> ERROR: Fehler
flowchart LR
START(( )) --> IDLE
IDLE -->|Disc erkannt| DD[DISC_DETECTED]
DD -->|Analyse starten| META[METADATA\nSELECTION]
META -->|1 Kandidat| RTS[READY_TO\nSTART]
META -->|mehrere Kandidaten| WUD[WAITING_FOR\nUSER_DECISION]
WUD -->|Playlist bestätigt| RTS
RTS -->|Raw vorhanden| MIC[MEDIAINFO\nCHECK]
RTS -->|Ripping starten| RIP[RIPPING]
RIP -->|MKV fertig| MIC
RIP -->|Fehler| ERR
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

View File

@@ -112,19 +112,31 @@ open http://localhost:5173
## Pipeline-Überblick
<div class="pipeline-diagram">
```mermaid
stateDiagram-v2
[*] --> IDLE
IDLE --> ANALYZING: Disc erkannt
ANALYZING --> METADATA_SELECTION: Analyse abgeschlossen
METADATA_SELECTION --> READY_TO_START: Metadaten bestätigt
READY_TO_START --> RIPPING: Start gedrückt
RIPPING --> MEDIAINFO_CHECK: MKV erstellt
MEDIAINFO_CHECK --> READY_TO_ENCODE: Tracks analysiert
READY_TO_ENCODE --> ENCODING: Encode bestätigt
ENCODING --> FINISHED: Encoding fertig
ENCODING --> ERROR: Fehler
RIPPING --> ERROR: Fehler
ERROR --> [*]
FINISHED --> [*]
flowchart LR
IDLE --> DD[DISC_DETECTED]
DD --> META[METADATA\nSELECTION]
META -->|1 Kandidat| RTS[READY_TO\nSTART]
META -->|Obfuskierung| WUD[WAITING_FOR\nUSER_DECISION]
WUD --> RTS
RTS --> RIP[RIPPING]
RTS -->|Raw vorhanden| MIC
RIP --> MIC[MEDIAINFO\nCHECK]
MIC --> RTE[READY_TO\nENCODE]
RTE --> ENC[ENCODING]
ENC --> PES[POST_ENCODE\nSCRIPTS]
ENC -->|keine Skripte| FIN([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
<div class="pipeline-diagram">
```mermaid
stateDiagram-v2
direction TB
[*] --> IDLE
flowchart LR
START(( )) --> IDLE
IDLE --> DISC_DETECTED: Disc erkannt
DISC_DETECTED --> METADATA_SELECTION: Analyse starten
IDLE -->|Disc erkannt| DD[DISC_DETECTED]
DD -->|Analyse starten| META[METADATA\nSELECTION]
METADATA_SELECTION --> READY_TO_START: Kein Obfuskierungsverdacht\n(ein Kandidat)
METADATA_SELECTION --> WAITING_FOR_USER_DECISION: Mehrere Playlist-Kandidaten\n→ manuelle Auswahl nötig
META -->|1 Kandidat| RTS[READY_TO\nSTART]
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)
READY_TO_START --> MEDIAINFO_CHECK: Starten\n(Raw bereits vorhanden)
MIC --> RTE[READY_TO\nENCODE]
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)
ENCODING --> FINISHED: Erfolg\n(keine Skripte)
POST_ENCODE_SCRIPTS --> FINISHED: Alle Skripte\nerfolgt
RIPPING --> ERROR: Fehler
ENCODING --> ERROR: Fehler
POST_ENCODE_SCRIPTS --> ERROR: Skript-Fehler
ERROR --> IDLE: Abbrechen / Retry
FINISHED --> IDLE: Neue Disc
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
style RIP fill:#e3f2fd,stroke:#42a5f5,color:#1565c0
style MIC fill:#e3f2fd,stroke:#42a5f5,color:#1565c0
```
</div>
---
## Zustandsbeschreibungen

View File

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