Tenjin

Ein Media Server, der Ihnen gehört: eigene Bibliotheken, eigene Nutzerverwaltung, optionales Relay für den Zugriff von unterwegs.

Version 0.1.0 · In Entwicklung

Windows · macOS · Linux · Android · Android TV · Fire TV

Tenjin-Desktop-Client: Startseite mit der Reihe „Weiterschauen“ und den Bibliotheken

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.

tenjin-client Desktop, Phone, Tablet, TV nativer Player, lokaler Proxy tenjin-relay öffentlich, Let's-Encrypt-Zertifikat prüft Tokens offline tenjin-server Bibliotheken, Nutzer, Tokens eigenes Ed25519-Schlüsselpaar Weg A · direkt · QUIC/TLS 1.3 · Ende-zu-Ende Weg B · Relay-Passthrough (Standard) Relay leitet nur verschlüsselte Pakete weiter Weg C · Relay-Terminierung · nur auf Freigabe des Admins TLS Client ↔ Relay und Relay ↔ Server, Cache möglich ausgehender Steuerkanal, keine Portfreigabe A: direkt, Relay sieht nichts B: durchgereicht, Relay sieht nur Pakete C: terminiert, Relay sieht Inhalte
Drei Komponenten, drei Verbindungswege · KomponentendiagrammIn voller Größe öffnen
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, Modelle
  • ViewModels · Zustand und Aktionen der Seiten, ohne Qt Quick
  • QML 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.