docs: Doku für Skript-Integration und neue Pipeline-Zustände
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -6,24 +6,106 @@ Nach der [Installation](installation.md) und [Konfiguration](configuration.md) f
|
||||
|
||||
## Übersicht: Pipeline-Zustände
|
||||
|
||||
```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
|
||||
```
|
||||
<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 & 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> | <span style="color:#1565c0">■ Läuft automatisch</span> | <span style="color:#3949ab">■ Benutzeraktion</span> | <span style="color:#e65100">⚠ Optional</span> | <span style="color:#6a1b9a">■ Encodierung</span> | <span style="color:#2e7d32">✓ Fertig</span>
|
||||
|
||||
??? note "Vollständiges Zustandsdiagramm (inkl. Fehler- & Alternativpfade)"
|
||||
|
||||
<div class="pipeline-diagram">
|
||||
|
||||
```mermaid
|
||||
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>
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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%;
|
||||
|
||||
Reference in New Issue
Block a user