Drei Komponenten, drei Wege
Tenjin besteht aus dem Media Server, dem optionalen Relay-Server und den Clients, alle in C++ mit Qt. Ein Client erreicht einen Server auf einem von drei Wegen; der Relay ist nur für B und C nötig. Beliebig viele Server können sich an einem Relay registrieren, ein Server auch an mehreren.
| Weg | Wann | Verschlüsselung | Relay sieht Inhalte |
|---|---|---|---|
| A · Direkt | LAN, Server von außen erreichbar (Portfreigabe, UPnP) oder erfolgreiches Hole Punching | QUIC/TLS 1.3, Ende-zu-Ende | nein |
| B · Relay-Passthrough (Standard) | Direktweg scheitert | QUIC/TLS 1.3 Ende-zu-Ende, das Relay leitet nur weiter (TURN-Prinzip) | nein |
| C · Relay-Terminierung | Vom Relay-Admin aktiviert, z. B. für einen Cache | TLS Client ↔ Relay und Relay ↔ Server, Anmeldung per signiertem Token | ja |
Der Client versucht zuerst Weg A (lokale Adressen, dann öffentliche), parallel startet das Hole Punching über das Relay. Gelingt nichts in einem Zeitfenster von etwa drei Sekunden, fällt er auf B bzw. C zurück.
Transport
- QUIC (HTTP/3) mit TLS 1.3 für Steuerung und Streaming, Bibliotheken ngtcp2 und nghttp3, TLS über OpenSSL 3.5 oder neuer; Rückfall auf TCP mit TLS 1.3 (HTTP/2), falls UDP gesperrt ist. Das Relay terminiert kein QUIC und kommt mit OpenSSL 3.0 aus.
- Paketgröße: UDP-Nutzlast standardmäßig 1.350 Byte, damit VPN- und Tunnel-Header Platz haben; der Administrator kann auf dynamische Pfad-MTU-Suche bis 1.452 Byte oder eine feste Größe von 1.200 bis 1.452 Byte wechseln.
- NAT: Adresskandidaten werden ICE-ähnlich über das Relay vermittelt; gegen NATs, die je Ziel einen neuen Port vergeben, gibt es eine Portsuche mit vielen Client-Sockets.
- Netzwechsel: Der Client erkennt einen Wechsel an seinen Adressen, bricht die QUIC-Verbindung ab und baut den Weg neu auf (direkt, Hole Punching, Relay). Ein still abgerissener Weg gilt nach acht Sekunden ohne Paket als tot.
Module des Media Servers
Der Media Server ist ein Hintergrunddienst aus Modulen, die über Schnittstellen kommunizieren und einzeln testbar sind.
| Modul | Aufgabe |
|---|---|
| Core / Service-Host | Start als Windows-Dienst, Daemon oder Container, Konfiguration, Logging |
| Net | QUIC/HTTP-3-Server, API-Routing, Relay-Steuerkanal, mDNS |
| Auth | Konten, Rechte, Tokens, Geräte, Kontoverknüpfung |
| Storage | Einheitliche Dateisystem-Abstraktion über lokale und entfernte Quellen |
| Library | Scanner, Erkennung der Ordnerstruktur, Zuordnung zu Metadaten |
| Metadata | Provider-Kette, Rate Limiting, Bild-Cache, Suche |
| Analysis | Vorschaubilder, Kapitel, Intro/Outro, Lautheit |
| Streaming | Wiedergabe-Entscheidung, HLS-Paketierung, Transcode-Sitzungen |
| Scheduler | Geplante und manuelle Aufgaben mit Fortschritt |
| Sync | Abgleich von Favoriten und Fortschritt über das Relay |
| Plugins | Laden, Versionieren, Isolieren von Erweiterungen |
| Telemetry | Aktivitäten, Lastmetriken, Stream-Details für die Verwaltung |
Nebenläufigkeit und Prozesse: getrennte Thread-Pools für I/O, CPU-Arbeit und Netz; SQLite im WAL-Modus mit genau einem Schreib-Thread und mehreren Leseverbindungen. Alles, was Mediendateien dekodiert, läuft in eigenen Prozessen (Media-Worker, Transcoding), damit eine defekte Datei oder ein Treiberfehler nie den Server mitreißt.
Speicherquellen
Inhalte liegen lokal oder auf Freigaben im eigenen Netz; Cloud-Speicher wird nicht unterstützt. Beim Polling werden nur Verzeichnislisten verglichen, nie Dateiinhalte gelesen; das Intervall passt sich an.
| Quelle | Zugriff | Änderungserkennung |
|---|---|---|
| Lokal | direkt | Echtzeit: ReadDirectoryChangesW, inotify, FSEvents |
| SMB | UNC-Pfad, libsmb2 oder Mount | SMB2 Change Notify, sonst Polling |
| NFS | Mount oder libnfs | Polling |
| WebDAV | HTTP(S) | PROPFIND mit ETag und Last-Modified |
Wiedergabe-Entscheidung
Direct Play. Die Datei wird unverändert gestreamt, wenn Container, Codecs und Spuren zu den Fähigkeiten des Geräts passen und die Bitrate unter dem wirksamen Limit liegt.
Remux. Nur der Container wird umgepackt, Video und Audio bleiben unberührt; etwa wenn das Gerät den Codec kann, aber nicht den Container.
Transcode. Erst wenn nötig: Video- oder Audiospur neu kodieren, mit Hardware-Beschleunigung (NVIDIA, Intel, AMD) und wählbaren Qualitätsstufen.
Das wirksame Limit ist das Minimum aus Gerätefähigkeit, Nutzer-Limit, Geräte-Limit und Client-Einstellung; der Upload-Balancer verteilt die Internet-Bandbreite auf externe Streams.
Metadaten
Je Medientyp gilt eine globale Reihenfolge der Provider (TMDB, OMDb, …); findet der erste nichts, wird der nächste gefragt. Rate Limits gelten je Provider statt pauschal. Texte und IDs liegen in SQLite, Bilder je nach Bibliothek im Metadaten-Ordner oder neben der Mediendatei in der Kodi/Jellyfin-Konvention (poster.jpg, fanart.jpg, season01-poster.jpg), damit andere Programme sie ebenfalls finden. Vorhandene Trickplay-Bilder von Jellyfin werden direkt weiterverwendet.
Client
client-core· Qt-freie Logik: Verbindungsaufbau, Sitzung, Wiedergabe-Entscheidung, ModelleViewModels· Zustand und Aktionen der Seiten, ohne Qt QuickQML je Formfaktor· Desktop (Seitenleiste), Tablet (Nav-Rail), Phone (untere Leiste, Querformat), TV (10-Fuß, Fokus)Player· libmpv (Desktop), Media3/ExoPlayer (Android), AVPlayer (Apple)lokaler Proxy· der Player holt den Stream über einen lokalen Proxy des Clients, der TLS und Token übernimmt
Ein Client-Programm deckt alle Formfaktoren ab; der Bild-Cache speichert nur versionierte Adressen (?v=<updated_at>), die der Server mit immutable ausliefert.
Betrieb
- Windows 10/11 und Windows Server: Media Server als Dienst; SMB-Quellen als UNC-Pfad mit hinterlegten Zugangsdaten, weil Dienste keine Laufwerksbuchstaben sehen.
- Linux: vor allem als Docker-Container (
tenjin-server,tenjin-relay, Basis Debian 13), alternativ systemd; OpenSSL 3.5 oder neuer ist Voraussetzung für Server und App. - macOS und QNAP (QTS): als Agent bzw. Daemon geplant.
- Clients: Windows, macOS, Linux; Android 9 und neuer für Phone, Tablet, Android TV; Fire TV mit 32-Bit-Paket.
Teststrategie
Unit
Kernlogik in UI-freien Bibliotheken mit Unit-Tests; Qt Quick nur als Darstellung.
Integration
Server, Relay und Client im Verbund, Import aus Plex und Jellyfin mit Probelauf.
UI-Tests
265 Oberflächentests (ctest -L ui) über alle Formfaktoren, mit Vorschau-Harness für Desktop, Phone, Querformat und TV.
Geräte
Nvidia Shield, Fire TV Cube und Smartphones im Netz; Ruckeln wird mit dumpsys SurfaceFlinger gemessen.
