Features:
- Import-Jobs: Persistierung in DB, Jobs beim Laden wiederherstellen
- Ordner loeschen: Button in Browser-Ansicht mit Modal-Dialog
- Serien konvertieren: Alle Episoden einer Serie in Queue senden
- Serien aufraumen: Alte Codec-Versionen nach Konvertierung loeschen
- Server-Log: Live-Ansicht in Admin mit Auto-Scroll
- Toast-Benachrichtigungen statt Browser-Alerts
- Bessere Fehlerbehandlung und Feedback
API:
- POST /api/library/delete-folder
- POST /api/library/series/{id}/convert
- GET /api/library/series/{id}/convert-status
- POST /api/library/series/{id}/cleanup
- GET /api/logs
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
307 lines
13 KiB
Markdown
307 lines
13 KiB
Markdown
# 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, HEVC, H.264) ueber Intel A380
|
|
- **CPU-Encoding**: SVT-AV1, x265, x264 als Fallback
|
|
- **Konfigurierbare Presets**: GPU/CPU, verschiedene Codecs und Qualitaetsstufen
|
|
- **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-Bibliothek
|
|
- **Ordner-Scan**: Konfigurierbare Scan-Pfade fuer Serien und Filme
|
|
- **Serien-Erkennung**: Automatisch via Ordnerstruktur (`S01E01`, `1x02`, `Staffel/Season XX`)
|
|
- **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
|
|
- **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
|
|
├── docker-compose.yml # GPU + CPU Profile
|
|
├── requirements.txt # Python-Abhaengigkeiten
|
|
├── 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
|
|
|
|
### 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.
|
|
|
|
### Konfiguration
|
|
In `app/cfg/settings.yaml` anpassen:
|
|
```yaml
|
|
database:
|
|
host: "192.168.155.11"
|
|
port: 3306
|
|
user: "video"
|
|
password: "dein_passwort"
|
|
database: "video_converter"
|
|
|
|
encoding:
|
|
mode: "cpu" # "gpu" | "cpu" | "auto"
|
|
gpu_device: "/dev/dri/renderD128"
|
|
default_preset: "cpu_av1"
|
|
max_parallel_jobs: 1
|
|
|
|
files:
|
|
target_container: "webm" # "webm" | "mkv" | "mp4"
|
|
delete_source: false
|
|
recursive_scan: true
|
|
|
|
library:
|
|
enabled: true
|
|
tvdb_api_key: "" # Von thetvdb.com
|
|
tvdb_pin: "" # Subscriber PIN (optional)
|
|
tvdb_language: "deu" # deu, eng, fra, spa, ita, jpn
|
|
import_default_mode: "copy" # "copy" | "move"
|
|
import_naming_pattern: "{series} - S{season:02d}E{episode:02d} - {title}.{ext}"
|
|
import_season_pattern: "Season {season:02d}"
|
|
```
|
|
|
|
### 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 |
|
|
| 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 |
|
|
|
|
### 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 |
|
|
|
|
### 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
|
|
&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, Episoden-Titel
|
|
|
|
### tvdb_episode_cache
|
|
Zwischenspeicher fuer TVDB-Episodendaten (Serie, Staffel, Episode, Name, Ausstrahlung).
|
|
|
|
|
|
## Docker Volumes
|
|
|
|
| Volume | Container-Pfad | Beschreibung |
|
|
|--------|---------------|-------------|
|
|
| `./app/cfg` | `/opt/video-konverter/app/cfg` | Konfiguration (persistent) |
|
|
| `./data` | `/opt/video-konverter/data` | Queue-Persistierung |
|
|
| `./logs` | `/opt/video-konverter/logs` | Server-Logs |
|
|
| `/mnt` | `/mnt` | Medien-Pfade (1:1 durchgereicht) |
|
|
|
|
|
|
## Lizenz
|
|
|
|
Privates Projekt von Eddy (Eduard Wisch).
|