# VideoKonverter

Web-basierter Video-Konverter mit GPU-Beschleunigung (Intel VAAPI), Video-Bibliotheksverwaltung und TVDB-Integration. Laeuft als Docker-Container auf Unraid oder lokal.

## Features

### Video-Konvertierung
- **GPU-Encoding**: Intel VAAPI (AV1, AV1 10-Bit, HEVC, H.264) ueber Intel A380
- **CPU-Encoding**: SVT-AV1, x265, x264 als Fallback
- **AV1 10-Bit Standard**: Bessere Qualitaet bei gleichem Speed (p010 Pixel-Format)
- **Konfigurierbare Presets**: 7 Presets (4x GPU + 3x CPU)
- **Parallele Jobs**: Mehrere Videos gleichzeitig konvertieren
- **Audio-Handling**: Alle Spuren behalten (DE+EN), kein Downmix, Opus-Transcoding
- **Live-Fortschritt**: WebSocket-basierte Echtzeit-Updates im Dashboard
- **Queue-Management**: Drag-and-Drop, Pause, Abbruch, Prioritaeten

### Video-Player
- **Browser-Streaming**: Direktes Abspielen mit ffmpeg-Transcoding (EAC3/DTS/AC3 -> AAC)
- **Play-Buttons**: In Serien-, Film- und Ordner-Ansichten
- **Delete-Buttons**: Einzelne Videos loeschen (DB + Datei)

### Video-Bibliothek
- **Ordner-Scan**: Konfigurierbare Scan-Pfade fuer Serien und Filme
- **Serien-Erkennung**: Automatisch via Ordnerstruktur (`S01E01`, `1x02`, `Staffel/Season XX`)
- **Doppel-Episoden**: Erkennung von Multi-Episoden-Dateien (`S01E01E02`, `S01E01-E02`, `1x01-02`)
- **Episoden-Titel**: Automatische Extraktion aus Dateinamen (ohne Qualitaets-Tags)
- **Film-Erkennung**: Ein Video pro Ordner = Film, Ordnername als Filmtitel
- **ffprobe-Analyse**: Codec, Aufloesung, Bitrate, Audio-Spuren, Untertitel, HDR/10-Bit
- **TVDB-Integration**: Serien + Filme, Poster, Episoden-Titel, fehlende Episoden
- **TVDB Review-Modal**: Vorschlaege pruefen statt blindem Auto-Match, manuelle Suche
- **TVDB-Sprachkonfiguration**: Metadaten in Deutsch, Englisch oder anderen Sprachen
- **Schnellfilter**: Vordefinierte Filter (Nicht konvertiert, Alte Formate, Fehlende Episoden)
- **Filter-Presets**: Eigene Filter speichern und als Standard setzen
- **Fehlende Episoden**: Uebersicht aller fehlenden Episoden ueber alle Serien
- **Filter**: Video-Codec, Aufloesung, Container, Audio-Sprache, Kanaele, 10-Bit
- **Duplikat-Finder**: Gleiche Episode in verschiedenen Formaten erkennen
- **Import-Service**: Videos einsortieren mit Serien-Erkennung und TVDB-Lookup
- **Clean-Service**: Nicht-Video-Dateien (NFO, JPG, SRT etc.) finden und entfernen
- **Direkt-Konvertierung**: Videos aus der Bibliothek direkt in die Queue senden

### Administration
- **Web-UI**: Responsive Dashboard, Bibliothek, Einstellungen, Statistik
- **Settings**: Encoding-Modus, Ziel-Container, Audio-/Untertitel-Sprachen, Cleanup
- **TVDB-Verwaltung**: API-Key/PIN konfigurieren, Sprache waehlen, Serien + Filme zuordnen
- **Scan-Pfad-Management**: Pfade hinzufuegen/loeschen/scannen ueber Admin-UI
- **Statistik**: Konvertierungs-Historie mit Groessen-Ersparnis, Dauer, Codec-Verteilung


## Architektur

```
┌────────────────────────────────────────────────────┐
│  Browser (Dashboard / Bibliothek / Admin / Stats)  │
├──────────────┬──────────────┬──────────────────────┤
│   HTMX/JS    │  WebSocket   │      REST API        │
├──────────────┴──────────────┴──────────────────────┤
│                aiohttp Server                       │
│  ┌──────────┐ ┌────────────┐ ┌──────────────────┐  │
│  │ Queue    │ │ Encoder    │ │ LibraryService   │  │
│  │ Service  │ │ Service    │ │ (Scan, Filter,   │  │
│  │          │ │ (ffmpeg)   │ │  Serien + Filme) │  │
│  ├──────────┤ ├────────────┤ ├──────────────────┤  │
│  │ Scanner  │ │ Probe      │ │ TVDBService      │  │
│  │ Service  │ │ Service    │ │ (API v4, i18n)   │  │
│  ├──────────┤ │ (ffprobe)  │ ├──────────────────┤  │
│  │ Importer │ └────────────┘ │ CleanerService   │  │
│  │ Service  │                │ (Junk-Scan)      │  │
│  └──────────┘                └──────────────────┘  │
├─────────────────────────────────────────────────────┤
│  MariaDB (statistics, library_*, tvdb_episode_cache)│
└─────────────────────────────────────────────────────┘
```

### Technologie-Stack

| Komponente | Technologie |
|------------|-------------|
| Backend | Python 3.12, aiohttp (async) |
| Templates | Jinja2 + HTMX |
| Datenbank | MariaDB (aiomysql) |
| Video | FFmpeg + FFprobe |
| GPU | Intel VAAPI (iHD-Treiber) |
| Metadaten | TVDB API v4 (tvdb-v4-official) |
| Container | Docker (Ubuntu 24.04) |
| Echtzeit | WebSocket |


## Projektstruktur

```
video-konverter/
├── __main__.py              # Einstiegspunkt
├── Dockerfile               # Ubuntu 24.04 + ffmpeg + Intel GPU
├── entrypoint.sh            # Default-Configs in Volumes kopieren
├── docker-compose.yml       # GPU + CPU Profile
├── requirements.txt         # Python-Abhaengigkeiten
├── unraid/
│   └── my-VideoKonverter.xml # Unraid Docker-Template
├── app/
│   ├── server.py            # Haupt-Server (aiohttp Application)
│   ├── config.py            # Settings + Presets laden
│   ├── cfg/
│   │   ├── settings.yaml    # Laufzeit-Einstellungen
│   │   └── presets.yaml     # Encoding-Presets (7 Stueck)
│   ├── models/
│   │   ├── media.py         # MediaFile, VideoStream, AudioStream
│   │   └── job.py           # ConvertJob, JobStatus
│   ├── services/
│   │   ├── library.py       # Bibliothek: Scan, Filter, Duplikate (1747 Z.)
│   │   ├── tvdb.py          # TVDB: Auth, Suche, Episoden, Sprache (1005 Z.)
│   │   ├── importer.py      # Import: Erkennung, TVDB-Lookup, Kopieren (734 Z.)
│   │   ├── cleaner.py       # Clean: Junk-Scan, Nicht-Video-Dateien (155 Z.)
│   │   ├── queue.py         # Job-Queue mit MariaDB-Persistierung (541 Z.)
│   │   ├── encoder.py       # FFmpeg-Wrapper (GPU + CPU)
│   │   ├── probe.py         # FFprobe-Analyse
│   │   ├── scanner.py       # Dateisystem-Scanner
│   │   └── progress.py      # Encoding-Fortschritt parsen
│   ├── routes/
│   │   ├── api.py           # REST API (Queue, Jobs, Convert)
│   │   ├── library_api.py   # REST API (Bibliothek, TVDB, Scan) (998 Z.)
│   │   ├── pages.py         # HTML-Seiten (Dashboard, Admin, etc.)
│   │   └── ws.py            # WebSocket-Manager
│   ├── templates/
│   │   ├── base.html        # Basis-Layout mit Navigation
│   │   ├── dashboard.html   # Queue + aktive Jobs
│   │   ├── library.html     # Bibliothek mit Filtern
│   │   ├── admin.html       # Einstellungen + TVDB + Scan-Pfade
│   │   ├── statistics.html  # Konvertierungs-Statistik
│   │   └── partials/
│   │       └── stats_table.html
│   └── static/
│       ├── css/style.css    # Komplettes Styling (1554 Z.)
│       └── js/
│           ├── library.js   # Bibliothek-UI (1912 Z.)
│           ├── websocket.js # WebSocket-Client
│           └── filebrowser.js # Datei-Browser
├── data/                    # Queue-Persistierung
├── logs/                    # Server-Logs
└── testmedia/               # Test-Dateien
```


## Installation

### Voraussetzungen
- Docker + Docker Compose
- MariaDB-Server (extern, z.B. auf Unraid)
- Optional: Intel GPU fuer Hardware-Encoding (Intel A380 empfohlen)

### MariaDB einrichten
```sql
CREATE DATABASE video_converter CHARACTER SET utf8mb4;
CREATE USER 'video'@'%' IDENTIFIED BY 'dein_passwort';
GRANT ALL PRIVILEGES ON video_converter.* TO 'video'@'%';
FLUSH PRIVILEGES;
```
Die Tabellen werden automatisch beim ersten Start erstellt.

### Unraid-Installation

1. Docker-Image laden (Unraid Web-Terminal):
```bash
docker load -i /mnt/user/downloads/videokonverter-cpu.tar
```

2. XML-Template kopieren:
```bash
cp /mnt/user/downloads/my-VideoKonverter.xml /boot/config/plugins/dockerMan/templates-user/
```

3. In der Unraid Docker-WebGUI: "Container hinzufuegen" → Template waehlen → Werte anpassen → Starten

Das Template enthält alle Variablen mit korrekten Defaults.

### Konfiguration

Alle Einstellungen sind per **Umgebungsvariablen** (VK_*) konfigurierbar.
ENV-Variablen ueberschreiben immer die `settings.yaml`.

| Variable | Default | Beschreibung |
|----------|---------|-------------|
| `VK_DB_HOST` | `192.168.155.11` | MariaDB Host |
| `VK_DB_PORT` | `3306` | MariaDB Port |
| `VK_DB_USER` | `video` | MariaDB Benutzer |
| `VK_DB_PASSWORD` | - | MariaDB Passwort |
| `VK_DB_NAME` | `video_converter` | Datenbank-Name |
| `VK_MODE` | `cpu` | Encoding-Modus: `gpu`, `cpu`, `auto` |
| `VK_GPU_DEVICE` | `/dev/dri/renderD129` | GPU Render-Device |
| `VK_DEFAULT_PRESET` | `gpu_av1_10bit` | Standard Encoding-Preset |
| `VK_MAX_JOBS` | `1` | Max. parallele Jobs |
| `VK_TVDB_API_KEY` | - | TVDB API Key |
| `VK_TVDB_LANGUAGE` | `deu` | TVDB Sprache |
| `VK_LOG_LEVEL` | `INFO` | Log-Level |

Alternativ kann `app/cfg/settings.yaml` direkt bearbeitet werden.
Bei Erstinstallation werden Default-Konfigdateien automatisch ins cfg-Volume kopiert.

### GPU-Device ermitteln

Auf dem Host pruefen welches renderD* die Intel GPU ist:
```bash
cat /sys/class/drm/renderD*/device/uevent | grep -B1 DRIVER
```
Beispiel: `renderD128` = AMD, `renderD129` = Intel → `VK_GPU_DEVICE=/dev/dri/renderD129`

### Starten

**GPU-Modus** (Produktion auf Unraid):
```bash
docker compose --profile gpu up --build -d
```

**CPU-Modus** (lokal testen):
```bash
PUID=1000 PGID=1000 docker compose --profile cpu up --build -d
```

Web-UI: http://localhost:8080


## Encoding-Presets

| Preset | Codec | Container | Qualitaet | Modus |
|--------|-------|-----------|-----------|-------|
| GPU AV1 | av1_vaapi | WebM | QP 30 | GPU |
| GPU AV1 10-Bit | av1_vaapi | WebM | QP 30 | GPU |
| GPU HEVC | hevc_vaapi | MKV | QP 28 | GPU |
| GPU H.264 | h264_vaapi | MP4 | QP 23 | GPU |
| CPU AV1/SVT | libsvtav1 | WebM | CRF 30 | CPU |
| CPU HEVC/x265 | libx265 | MKV | CRF 28 | CPU |
| CPU H.264/x264 | libx264 | MP4 | CRF 23 | CPU |


## API Referenz

### Konvertierung
| Methode | Pfad | Beschreibung |
|---------|------|-------------|
| POST | `/api/convert` | Dateien/Ordner zur Queue hinzufuegen |
| GET | `/api/queue` | Queue-Status abrufen |
| DELETE | `/api/jobs/{id}` | Job entfernen/abbrechen |

### Bibliothek
| Methode | Pfad | Beschreibung |
|---------|------|-------------|
| GET | `/api/library/paths` | Scan-Pfade auflisten |
| POST | `/api/library/paths` | Scan-Pfad hinzufuegen |
| DELETE | `/api/library/paths/{id}` | Scan-Pfad loeschen |
| POST | `/api/library/scan` | Alle Pfade scannen |
| POST | `/api/library/scan/{id}` | Einzelnen Pfad scannen |
| GET | `/api/library/scan-status` | Scan-Fortschritt |
| GET | `/api/library/videos` | Videos filtern (siehe Filter-Params) |
| GET | `/api/library/series` | Alle Serien |
| GET | `/api/library/series/{id}` | Serie mit Episoden |
| GET | `/api/library/series/{id}/missing` | Fehlende Episoden einer Serie |
| GET | `/api/library/missing-episodes` | Alle fehlenden Episoden (paginated) |
| GET | `/api/library/filter-presets` | Filter-Presets laden |
| POST | `/api/library/filter-presets` | Neues Preset speichern |
| PUT | `/api/library/filter-presets` | Presets aktualisieren |
| DELETE | `/api/library/filter-presets/{id}` | Preset loeschen |
| PUT | `/api/library/default-view` | Standard-Ansicht setzen |
| POST | `/api/library/series/{id}/tvdb-match` | TVDB-ID zuordnen |
| POST | `/api/library/series/{id}/convert` | Alle Episoden konvertieren |
| GET | `/api/library/series/{id}/convert-status` | Codec-Status der Serie |
| POST | `/api/library/series/{id}/cleanup` | Alte Dateien loeschen |
| GET | `/api/library/duplicates` | Duplikate finden |
| POST | `/api/library/videos/{id}/convert` | Direkt konvertieren |
| POST | `/api/library/delete-folder` | Ordner komplett loeschen |
| GET | `/api/library/stats` | Bibliotheks-Statistiken |
| GET | `/api/library/movies` | Filme auflisten |
| POST | `/api/library/movies/{id}/tvdb-match` | Film-TVDB-Zuordnung |
| POST | `/api/library/tvdb-auto-match` | Review-Vorschlaege sammeln |
| POST | `/api/library/tvdb-confirm` | TVDB-Match bestaetigen |
| POST | `/api/library/tvdb-refresh-episodes` | Episoden-Cache aktualisieren |
| GET | `/api/tvdb/search?q=` | TVDB-Suche |
| GET | `/api/tvdb/language` | TVDB-Sprache lesen |
| PUT | `/api/tvdb/language` | TVDB-Sprache aendern |

### Streaming
| Methode | Pfad | Beschreibung |
|---------|------|-------------|
| GET | `/api/library/videos/{id}/stream` | Video-Transcoding-Stream (ffmpeg pipe) |
| DELETE | `/api/library/videos/{id}` | Video loeschen (DB + Datei) |

### Import
| Methode | Pfad | Beschreibung |
|---------|------|-------------|
| GET | `/api/library/import` | Alle Import-Jobs auflisten |
| POST | `/api/library/import` | Neuen Import-Job erstellen |
| GET | `/api/library/import/{id}` | Import-Job Status mit Items |
| POST | `/api/library/import/{id}/analyze` | Import analysieren |
| POST | `/api/library/import/{id}/execute` | Import ausfuehren |
| POST | `/api/library/import/{id}/assign` | Item manuell zuordnen |
| POST | `/api/library/import/{id}/skip` | Item ueberspringen |

### System
| Methode | Pfad | Beschreibung |
|---------|------|-------------|
| GET | `/api/logs` | Server-Logs abrufen |
| GET | `/api/system` | System-Info (GPU, Jobs) |

### Video-Filter (`/api/library/videos`)
```
?video_codec=hevc         # h264, hevc, av1, mpeg4
&min_width=1920           # Mindest-Aufloesung
&container=mkv            # mkv, mp4, avi, webm
&audio_lang=ger           # Audio-Sprache
&audio_channels=6         # Kanal-Anzahl (2=Stereo, 6=5.1)
&is_10bit=1               # Nur 10-Bit
&not_converted=1          # Nicht im Zielformat (Container + Codec)
&exclude_codec=av1        # Codec ausschliessen
&exclude_container=webm   # Container ausschliessen
&search=breaking          # Dateiname-Suche
&sort=file_size           # Sortierung
&order=desc               # asc | desc
&page=1&limit=50          # Pagination
```


## Datenbank-Schema

### library_paths
Konfigurierte Scan-Pfade fuer Serien- und Film-Ordner.

### library_series
Erkannte Serien mit optionaler TVDB-Verknuepfung (Poster, Beschreibung, Episoden-Zaehler).

### library_movies
Erkannte Filme mit optionaler TVDB-Verknuepfung (Poster, Beschreibung, Jahr).

### library_videos
Jedes Video mit vollstaendigen ffprobe-Metadaten:
- Video: Codec, Aufloesung, Framerate, Bitrate, 10-Bit, HDR
- Audio: JSON-Array mit Spuren (`[{"codec":"eac3","lang":"ger","channels":6,"bitrate":256000}]`)
- Untertitel: JSON-Array (`[{"codec":"subrip","lang":"ger"}]`)
- Serien: Staffel/Episode-Nummer, episode_end (fuer Doppel-Episoden), Episoden-Titel

### tvdb_episode_cache
Zwischenspeicher fuer TVDB-Episodendaten (Serie, Staffel, Episode, Name, Ausstrahlung).


## Docker Volumes

| Volume (Host) | Container-Pfad | Beschreibung |
|----------------|---------------|-------------|
| `./app/cfg` (lokal) / `/mnt/user/appdata/videokonverter/cfg` (Unraid) | `/opt/video-konverter/app/cfg` | Konfiguration (persistent, Defaults werden automatisch kopiert) |
| `./data` (lokal) / `/mnt/user/appdata/videokonverter/data` (Unraid) | `/opt/video-konverter/data` | Queue-Persistierung |
| `./logs` (lokal) / `/mnt/user/appdata/videokonverter/logs` (Unraid) | `/opt/video-konverter/logs` | Server-Logs |
| `/mnt` (lokal) / `/mnt/user` (Unraid) | `/mnt` | Medien-Pfade |
| `/dev/dri` | `/dev/dri` | GPU-Devices (fuer VAAPI) |


## Lizenz

Privates Projekt von Eddy (Eduard Wisch).
