Initial commit mit MkDocs-Dokumentation

This commit is contained in:
2026-03-04 14:18:33 +00:00
parent 6115090da1
commit 31d3e36597
97 changed files with 27518 additions and 1 deletions

222
docs/api/history.md Normal file
View File

@@ -0,0 +1,222 @@
# History API
Endpunkte für die Job-Histoire, Dateimanagement und Orphan-Import.
---
## GET /api/history
Gibt eine Liste aller Jobs zurück, optional gefiltert.
**Query-Parameter:**
| Parameter | Typ | Beschreibung |
|----------|-----|-------------|
| `status` | string | Filtert nach Status (z.B. `FINISHED`, `ERROR`) |
| `search` | string | Sucht in Filmtiteln |
**Beispiel:**
```
GET /api/history?status=FINISHED&search=Inception
```
**Response:**
```json
{
"jobs": [
{
"id": 42,
"status": "FINISHED",
"title": "Inception",
"imdb_id": "tt1375666",
"omdb_year": "2010",
"omdb_type": "movie",
"omdb_poster": "https://...",
"raw_path": "/mnt/nas/raw/Inception_t00.mkv",
"output_path": "/mnt/nas/movies/Inception (2010).mkv",
"created_at": "2024-01-15T10:00:00.000Z",
"updated_at": "2024-01-15T12:30:00.000Z"
}
],
"total": 1
}
```
---
## GET /api/history/:id
Gibt Detail-Informationen für einen einzelnen Job zurück.
**URL-Parameter:** `id` Job-ID
**Query-Parameter:**
| Parameter | Typ | Standard | Beschreibung |
|----------|-----|---------|-------------|
| `includeLogs` | boolean | `false` | Log-Inhalte einschließen |
| `includeLiveLog` | boolean | `false` | Aktuellen Live-Log einschließen |
**Response:**
```json
{
"id": 42,
"status": "FINISHED",
"title": "Inception",
"imdb_id": "tt1375666",
"encode_plan": { ... },
"makemkv_output": { ... },
"mediainfo_output": { ... },
"handbrake_log": "/path/to/log",
"logs": {
"handbrake": "Encoding: task 1 of 1, 100.0%\n..."
},
"created_at": "2024-01-15T10:00:00.000Z",
"updated_at": "2024-01-15T12:30:00.000Z"
}
```
---
## GET /api/history/database
Gibt alle rohen Datenbankzeilen zurück (Debug-Ansicht).
**Response:**
```json
{
"jobs": [ { "id": 1, "status": "FINISHED", ... } ],
"total": 15
}
```
---
## GET /api/history/orphan-raw
Findet Raw-Ordner, die nicht als Jobs in der Datenbank registriert sind.
**Response:**
```json
{
"orphans": [
{
"path": "/mnt/nas/raw/UnknownMovie_2023-12-01",
"size": "45.2 GB",
"modifiedAt": "2023-12-01T15:00:00.000Z",
"files": ["t00.mkv", "t01.mkv"]
}
]
}
```
---
## POST /api/history/orphan-raw/import
Importiert einen Orphan-Raw-Ordner als Job in die Datenbank.
**Request:**
```json
{
"path": "/mnt/nas/raw/UnknownMovie_2023-12-01"
}
```
**Response:**
```json
{
"ok": true,
"jobId": 99,
"message": "Orphan-Ordner als Job importiert"
}
```
Nach dem Import kann dem Job über `/api/history/:id/omdb/assign` Metadaten zugewiesen werden.
---
## POST /api/history/:id/omdb/assign
Weist einem bestehenden Job OMDb-Metadaten nachträglich zu.
**URL-Parameter:** `id` Job-ID
**Request:**
```json
{
"imdbId": "tt1375666",
"title": "Inception",
"year": "2010",
"type": "movie",
"poster": "https://..."
}
```
**Response:**
```json
{ "ok": true }
```
---
## POST /api/history/:id/delete-files
Löscht die Dateien eines Jobs (Raw und/oder Output), behält den Job-Eintrag.
**URL-Parameter:** `id` Job-ID
**Request:**
```json
{
"deleteRaw": true,
"deleteOutput": false
}
```
**Response:**
```json
{
"ok": true,
"deleted": {
"raw": "/mnt/nas/raw/Inception_t00.mkv",
"output": null
}
}
```
---
## POST /api/history/:id/delete
Löscht den Job-Eintrag aus der Datenbank, optional auch die Dateien.
**URL-Parameter:** `id` Job-ID
**Request:**
```json
{
"deleteFiles": true
}
```
**Response:**
```json
{ "ok": true, "message": "Job gelöscht" }
```
!!! warning "Unwiderruflich"
Das Löschen von Jobs und Dateien ist nicht rückgängig zu machen.

85
docs/api/index.md Normal file
View File

@@ -0,0 +1,85 @@
# API-Referenz
Ripster bietet eine **REST-API** für alle Operationen sowie einen **WebSocket-Endpunkt** für Echtzeit-Updates.
---
## Basis-URL
```
http://localhost:3001
```
Konfigurierbar über die Umgebungsvariable `PORT`.
---
## API-Gruppen
<div class="grid cards" markdown>
- :material-pipe: **Pipeline API**
---
Pipeline-Steuerung: Analyse starten, Metadaten setzen, Ripping und Encoding steuern.
[:octicons-arrow-right-24: Pipeline API](pipeline.md)
- :material-cog: **Settings API**
---
Einstellungen lesen und schreiben.
[:octicons-arrow-right-24: Settings API](settings.md)
- :material-history: **History API**
---
Job-Geschichte abfragen, Jobs löschen, Orphan-Ordner importieren.
[:octicons-arrow-right-24: History API](history.md)
- :material-lightning-bolt: **WebSocket Events**
---
Echtzeit-Events für Pipeline-Status, Fortschritt und Disc-Erkennung.
[:octicons-arrow-right-24: WebSocket](websocket.md)
</div>
---
## Authentifizierung
Die API hat **keine Authentifizierung**. Sie ist für den Einsatz im lokalen Netzwerk konzipiert.
!!! warning "Produktionsbetrieb"
Falls Ripster öffentlich erreichbar sein soll, schütze die API mit einem Reverse-Proxy (z. B. nginx mit Basic Auth oder OAuth).
---
## Fehlerformat
Alle API-Fehler werden im folgenden Format zurückgegeben:
```json
{
"error": "Job nicht gefunden",
"details": "Kein Job mit ID 999 vorhanden"
}
```
HTTP-Statuscodes:
| Code | Bedeutung |
|-----|-----------|
| `200` | Erfolg |
| `400` | Ungültige Anfrage |
| `404` | Ressource nicht gefunden |
| `409` | Konflikt (z.B. Pipeline bereits aktiv) |
| `500` | Interner Serverfehler |

249
docs/api/pipeline.md Normal file
View File

@@ -0,0 +1,249 @@
# Pipeline API
Alle Endpunkte zur Steuerung des Ripping-Workflows.
---
## GET /api/pipeline/state
Gibt den aktuellen Pipeline-Zustand zurück.
**Response:**
```json
{
"state": "ENCODING",
"jobId": 42,
"job": {
"id": 42,
"title": "Inception",
"status": "ENCODING",
"imdb_id": "tt1375666",
"omdb_year": "2010"
},
"progress": 73.5,
"eta": "00:12:34",
"updatedAt": "2024-01-15T14:30:00.000Z"
}
```
**States:**
| Wert | Beschreibung |
|------|-------------|
| `IDLE` | Wartet auf Disc |
| `ANALYZING` | MakeMKV analysiert |
| `METADATA_SELECTION` | Wartet auf Benutzer |
| `READY_TO_START` | Bereit zum Starten |
| `RIPPING` | Rippen läuft |
| `MEDIAINFO_CHECK` | Track-Analyse |
| `READY_TO_ENCODE` | Wartet auf Bestätigung |
| `ENCODING` | Encoding läuft |
| `FINISHED` | Abgeschlossen |
| `ERROR` | Fehler |
---
## POST /api/pipeline/analyze
Startet eine manuelle Disc-Analyse (ohne Disc-Detection-Trigger).
**Request:** Kein Body erforderlich
**Response:**
```json
{ "ok": true, "message": "Analyse gestartet" }
```
**Fehlerfälle:**
- `409` Pipeline bereits aktiv
---
## POST /api/pipeline/rescan-disc
Erzwingt eine erneute Disc-Erkennung.
**Response:**
```json
{ "ok": true }
```
---
## GET /api/pipeline/omdb/search
Sucht in der OMDb-API nach einem Filmtitel.
**Query-Parameter:**
| Parameter | Typ | Beschreibung |
|----------|-----|-------------|
| `q` | string | Suchbegriff (Filmtitel) |
| `type` | string | `movie` oder `series` (optional) |
**Beispiel:**
```
GET /api/pipeline/omdb/search?q=Inception&type=movie
```
**Response:**
```json
{
"results": [
{
"imdbId": "tt1375666",
"title": "Inception",
"year": "2010",
"type": "movie",
"poster": "https://m.media-amazon.com/images/..."
}
]
}
```
---
## POST /api/pipeline/select-metadata
Bestätigt Metadaten und Playlist-Auswahl für den aktuellen Job.
**Request:**
```json
{
"jobId": 42,
"omdb": {
"imdbId": "tt1375666",
"title": "Inception",
"year": "2010",
"type": "movie",
"poster": "https://..."
},
"playlist": "00800.mpls"
}
```
`playlist` ist optional und nur bei Blu-rays relevant.
**Response:**
```json
{ "ok": true }
```
---
## POST /api/pipeline/start/:jobId
Startet den Ripping-Prozess für einen vorbereiteten Job.
**URL-Parameter:** `jobId` ID des Jobs
**Response:**
```json
{ "ok": true, "message": "Ripping gestartet" }
```
**Fehlerfälle:**
- `404` Job nicht gefunden
- `409` Job nicht im Status `READY_TO_START`
---
## POST /api/pipeline/confirm-encode/:jobId
Bestätigt die Encode-Konfiguration mit Track-Auswahl.
**URL-Parameter:** `jobId` ID des Jobs
**Request:**
```json
{
"audioTracks": [1, 2],
"subtitleTracks": [1]
}
```
Track-Indizes entsprechen den 1-basierten Track-Nummern aus dem Encode-Plan.
**Response:**
```json
{ "ok": true, "message": "Encoding gestartet" }
```
---
## POST /api/pipeline/cancel
Bricht den aktuellen Pipeline-Prozess ab.
**Response:**
```json
{ "ok": true, "message": "Pipeline abgebrochen" }
```
Der laufende Prozess wird mit SIGINT beendet (Fallback: SIGKILL nach Timeout).
---
## POST /api/pipeline/retry/:jobId
Wiederholt einen fehlgeschlagenen Job.
**URL-Parameter:** `jobId` ID des Jobs
**Response:**
```json
{ "ok": true, "message": "Job wird wiederholt" }
```
**Fehlerfälle:**
- `404` Job nicht gefunden
- `409` Job nicht im Status `ERROR`
---
## POST /api/pipeline/resume-ready/:jobId
Setzt einen Job im Status `READY_TO_ENCODE` zurück in die aktive Pipeline.
**URL-Parameter:** `jobId` ID des Jobs
**Response:**
```json
{ "ok": true }
```
---
## POST /api/pipeline/reencode/:jobId
Startet ein erneutes Encoding für einen abgeschlossenen Job (ohne erneutes Ripping).
**URL-Parameter:** `jobId` ID des Jobs
**Request:**
```json
{
"audioTracks": [1, 2],
"subtitleTracks": [1]
}
```
**Response:**
```json
{ "ok": true, "message": "Re-Encoding gestartet" }
```

140
docs/api/settings.md Normal file
View File

@@ -0,0 +1,140 @@
# Settings API
Endpunkte zum Lesen und Schreiben der Anwendungseinstellungen.
---
## GET /api/settings
Gibt alle Einstellungen kategorisiert zurück.
**Response:**
```json
{
"paths": {
"raw_dir": {
"value": "/mnt/nas/raw",
"schema": {
"type": "string",
"label": "Raw-Verzeichnis",
"description": "Speicherort für rohe MKV-Dateien",
"required": true
}
},
"movie_dir": {
"value": "/mnt/nas/movies",
"schema": { ... }
}
},
"tools": { ... },
"encoding": { ... },
"drive": { ... },
"makemkv": { ... },
"omdb": { ... },
"notifications": { ... }
}
```
---
## PUT /api/settings/:key
Aktualisiert eine einzelne Einstellung.
**URL-Parameter:** `key` Einstellungs-Schlüssel
**Request:**
```json
{
"value": "/mnt/storage/raw"
}
```
**Response:**
```json
{ "ok": true, "key": "raw_dir", "value": "/mnt/storage/raw" }
```
**Fehlerfälle:**
- `400` Ungültiger Wert (Validierungsfehler)
- `404` Einstellung nicht gefunden
!!! note "Encode-Review-Refresh"
Wenn eine encoding-relevante Einstellung geändert wird (z.B. `handbrake_preset`), wird der Encode-Plan für den aktuell wartenden Job automatisch neu berechnet.
---
## PUT /api/settings
Aktualisiert mehrere Einstellungen auf einmal.
**Request:**
```json
{
"raw_dir": "/mnt/storage/raw",
"movie_dir": "/mnt/storage/movies",
"handbrake_preset": "H.265 MKV 720p30"
}
```
**Response:**
```json
{
"ok": true,
"updated": ["raw_dir", "movie_dir", "handbrake_preset"],
"errors": []
}
```
---
## POST /api/settings/pushover/test
Sendet eine Test-Benachrichtigung über PushOver.
**Request:** Kein Body erforderlich (verwendet gespeicherte Zugangsdaten)
**Response (Erfolg):**
```json
{ "ok": true, "message": "Test-Benachrichtigung gesendet" }
```
**Response (Fehler):**
```json
{ "ok": false, "error": "Ungültiger API-Token" }
```
---
## Einstellungs-Schlüssel Referenz
Eine vollständige Liste aller Einstellungs-Schlüssel:
| Schlüssel | Kategorie | Typ | Beschreibung |
|---------|----------|-----|-------------|
| `raw_dir` | paths | string | Raw-MKV Verzeichnis |
| `movie_dir` | paths | string | Ausgabe-Verzeichnis |
| `log_dir` | paths | string | Log-Verzeichnis |
| `makemkv_command` | tools | string | MakeMKV-Befehl |
| `handbrake_command` | tools | string | HandBrake-Befehl |
| `mediainfo_command` | tools | string | MediaInfo-Befehl |
| `handbrake_preset` | encoding | string | HandBrake-Preset-Name |
| `handbrake_extra_args` | encoding | string | Zusatz-Argumente |
| `output_extension` | encoding | string | Dateiendung (z.B. `mkv`) |
| `filename_template` | encoding | string | Dateiname-Template |
| `drive_mode` | drive | select | `auto` oder `explicit` |
| `drive_device` | drive | string | Geräte-Pfad |
| `disc_poll_interval_ms` | drive | number | Polling-Intervall (ms) |
| `makemkv_min_length_minutes` | makemkv | number | Min. Titellänge (Minuten) |
| `makemkv_backup_mode` | makemkv | boolean | Backup-Modus aktivieren |
| `omdb_api_key` | omdb | string | OMDb API-Key |
| `omdb_default_type` | omdb | select | Standard-Suchtyp |
| `pushover_user_key` | notifications | string | PushOver User-Key |
| `pushover_api_token` | notifications | string | PushOver API-Token |

225
docs/api/websocket.md Normal file
View File

@@ -0,0 +1,225 @@
# WebSocket Events
Ripster verwendet WebSockets für Echtzeit-Updates. Der Endpunkt ist `/ws`.
---
## Verbindung
```js
const ws = new WebSocket('ws://localhost:3001/ws');
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log(message.type, message.data);
};
```
---
## Nachrichten-Format
Alle Nachrichten folgen diesem Schema:
```json
{
"type": "EVENT_TYPE",
"data": { ... }
}
```
---
## Event-Typen
### PIPELINE_STATE_CHANGE
Wird gesendet, wenn der Pipeline-Zustand wechselt.
```json
{
"type": "PIPELINE_STATE_CHANGE",
"data": {
"state": "ENCODING",
"jobId": 42,
"job": {
"id": 42,
"title": "Inception",
"status": "ENCODING"
}
}
}
```
---
### PROGRESS_UPDATE
Wird während aktiver Prozesse (Ripping/Encoding) regelmäßig gesendet.
```json
{
"type": "PROGRESS_UPDATE",
"data": {
"progress": 73.5,
"eta": "00:12:34",
"speed": "45.2 fps",
"phase": "ENCODING"
}
}
```
**Felder:**
| Feld | Typ | Beschreibung |
|-----|-----|-------------|
| `progress` | number | Fortschritt 0100 |
| `eta` | string | Geschätzte Restzeit (`HH:MM:SS`) |
| `speed` | string | Encoding-Geschwindigkeit (nur beim Encoding) |
| `phase` | string | Aktuelle Phase (`RIPPING` oder `ENCODING`) |
---
### DISC_DETECTED
Wird gesendet, wenn eine Disc erkannt wird.
```json
{
"type": "DISC_DETECTED",
"data": {
"device": "/dev/sr0"
}
}
```
---
### DISC_REMOVED
Wird gesendet, wenn eine Disc ausgeworfen wird.
```json
{
"type": "DISC_REMOVED",
"data": {
"device": "/dev/sr0"
}
}
```
---
### JOB_COMPLETE
Wird gesendet, wenn ein Job erfolgreich abgeschlossen wurde.
```json
{
"type": "JOB_COMPLETE",
"data": {
"jobId": 42,
"title": "Inception",
"outputPath": "/mnt/nas/movies/Inception (2010).mkv"
}
}
```
---
### ERROR
Wird gesendet, wenn ein Fehler aufgetreten ist.
```json
{
"type": "ERROR",
"data": {
"jobId": 42,
"message": "HandBrake ist abgestürzt",
"details": "Exit code: 1\nStderr: ..."
}
}
```
---
### METADATA_REQUIRED
Wird gesendet, wenn Benutzer-Eingabe für Metadaten benötigt wird.
```json
{
"type": "METADATA_REQUIRED",
"data": {
"jobId": 42,
"makemkvData": { ... },
"playlistAnalysis": { ... }
}
}
```
---
### ENCODE_REVIEW_REQUIRED
Wird gesendet, wenn der Benutzer den Encode-Plan bestätigen soll.
```json
{
"type": "ENCODE_REVIEW_REQUIRED",
"data": {
"jobId": 42,
"encodePlan": {
"audioTracks": [ ... ],
"subtitleTracks": [ ... ]
}
}
}
```
---
## Reconnect-Verhalten
Der Frontend-Hook `useWebSocket.js` implementiert automatisches Reconnect:
```
Verbindung verloren
Warte 1s → Reconnect-Versuch
↓ (Fehlschlag)
Warte 2s → Reconnect-Versuch
↓ (Fehlschlag)
Warte 4s → ...
Max. 30s Wartezeit
```
---
## Beispiel: React-Hook
```js
import { useEffect, useState } from 'react';
function usePipelineState() {
const [state, setState] = useState({ state: 'IDLE' });
useEffect(() => {
const ws = new WebSocket(import.meta.env.VITE_WS_URL + '/ws');
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'PIPELINE_STATE_CHANGE') {
setState(msg.data);
}
};
return () => ws.close();
}, []);
return state;
}
```