Tenjin
Einrichtungshandbuch
Media Server installieren, Bibliotheken anlegen, App einrichten, Zugriff von unterwegs, Relay betreiben, Konten verknüpfen, Betrieb und Fehlersuche.
This content is currently only available in German.
1. Voraussetzungen
| Komponente | Benötigt |
|---|---|
| Bauen (Windows) | Visual Studio 2022 (C++), Qt 6.12 msvc2022_64 unter D:\QT, CMake 3.30 und Ninja (D:\QT\Tools), vcpkg unter C:\vcpkg\vcpkg |
| Android-App | Qt 6.12 android_arm64_v8a, Android SDK mit NDK 27 (%LOCALAPPDATA%\Android\Sdk), JDK 21, adb |
| Media Server (Laufzeit) | Windows 10/11 x64 oder Linux x64 – unter Linux zwingend OpenSSL ≥ 3.5 (Debian 13, Ubuntu 25.10, Fedora 42, Arch; nicht Ubuntu 24.04 LTS/Debian 12) und Qt ≥ 6.8, oder das Docker-Image tenjin-server (bringt alles mit, Abschnitt 2.1); FFmpeg (Windows: mitgebaut unter bin\ffmpeg\, Linux: Paket ffmpeg); optional NVIDIA/Intel/AMD-GPU für Hardware-Transcoding |
| Relay (Laufzeit) | Öffentlich erreichbarer Host mit fester Adresse oder DNS-Namen, freier TCP- und UDP-Port (Standard 7900); Windows, Linux x64 (OpenSSL ≥ 3.0, Qt ≥ 6.8) oder Docker-Image tenjin-relay |
| Metadaten | TMDB-API-Schlüssel (kostenlos, https://www.themoviedb.org/settings/api); optional OMDb-Schlüssel (https://www.omdbapi.com/apikey.aspx, Free oder Patreon-Premium) |
2. Bauen
scripts\vcpkg-install.cmd # einmalig (ca. 30 min): OpenSSL, libsodium, nlohmann-json, FFmpeg (Feature media), ngtcp2/nghttp3 (Feature quic)
scripts\fetch-mpv.cmd # einmalig: libmpv für den Desktop-Player nach third_party\mpv\windows (braucht 7-Zip)
scripts\build.cmd all msvc-release # configure + build + Tests
scripts\deploy.cmd msvc-release # dist\msvc-release\{server,client,relay} mit allen Laufzeitdateien
scripts\build.cmd all msvc-releaseFull # Windows-Client ohne Installation: build\msvc-releaseFull\bin
Android:
scripts\vcpkg-install-android.cmd # einmalig (arm64-v8a, mit QUIC)
scripts\build-android.cmd build # signierte APK: build\android-arm64\apps\tenjin-client\android-build\tenjin-client.apk
scripts\build-android.cmd install # adb install -r auf das verbundene Gerät
scripts\vcpkg-install-android.cmd armv7 # einmalig: 32-Bit-Satz für Fire OS (Amazon Fire TV Cube)
scripts\build-android.cmd build armv7 # 32-Bit-APK: build\android-armv7\apps\tenjin-client\android-build\tenjin-client.apk
Amazon Fire TV (Fire OS 7, nur armeabi-v7a): das 32-Bit-Paket installieren (adb -s <ip>:5555 install -r …\android-armv7\…);
das arm64-Paket scheitert mit INSTALL_FAILED_NO_MATCHING_ABIS. Beide Pakete tragen dieselbe Paket-ID und Signatur.
build-android.cmd endet auch dann mit Exit-Code 0, wenn ninja abgebrochen hat – nach dem Bau den Zeitstempel der APK prüfen.
Der NDK-Clang ist strenger als MSVC: ein Default-Argument const Nested &f = {} an einer Methode der umschließenden Klasse
scheitert, wenn die geschachtelte Struktur Member-Initialisierer hat („default member initializer … needed within definition
of enclosing class“) – stattdessen eine Überladung ohne den Parameter anlegen.
Die APK wird mit einem lokalen Entwicklungs-Keystore (%APPDATA%\Tenjin\android-dev.keystore) signiert, damit
Updates über die installierte App gelegt werden können. Für die Shield: Entwickleroptionen → Netzwerk-Debugging,
dann adb connect <ip>:5555; Fire TV Cube: Einstellungen → Mein Fire TV → Entwickleroptionen → ADB-Debugging, dann ebenso.
Fire TV Cube (seit 21.10.2026): Bedienung wie auf der Shield (D-Pad, OK, Zurück, Play/Pause, Spulen). Zusätzlich öffnet die Menü-Taste (☰) der Fire-TV-Fernbedienung das Kontextmenü des markierten Posters bzw. der Detailseite (auf der Shield weiter OK halten). OK auf einem Textfeld öffnet die Fire-TV-Bildschirmtastatur (mit QR-Code zum Tippen am Handy); „Weiter“ übernimmt den Text, Zurück schließt sie. Beide Wege gelten nur auf Fire OS (Erkennung über den Gerätehersteller „Amazon“) – Shield, Handy und PC sind unverändert. Bekannt: Bildschirmfotos per adb sind während einer Wiedergabe leer (Fire OS), das Bild am Fernseher ist davon nicht betroffen.
Linux (Server, Relay und Desktop-App, über Docker Desktop oder ein Linux-System):
scripts\build-linux.cmd all Release # baut das Build-Image (Debian 13, Qt 6.8, OpenSSL 3.5, ngtcp2/nghttp3), kompiliert, testet, kopiert nach dist\linux\Release
scripts\build-linux.cmd images Release # Laufzeit-Images tenjin-server und tenjin-relay aus dist\linux\Release, gespeichert als dist\docker\*.tar
scripts\build-linux.cmd smoke Release # startet die App unter Xvfb (OpenGL über Mesa) und speichert client-smoke.png
scripts\build-linux.cmd shell # Shell im Build-Container (Quellen unter /src, Build-Baum unter /work)
# ohne Docker auf einem Linux-Rechner (Debian 13 o. Ä. mit OpenSSL >= 3.5; ngtcp2 1.25 und nghttp3 1.18 wie in
# platform/linux/Dockerfile statisch nach /usr/local bauen, sonst baut CMake ohne QUIC): apt install build-essential cmake ninja-build pkg-config git qt6-base-dev \
# qt6-httpserver-dev qt6-websockets-dev libqt6sql6-sqlite libssl-dev libsodium-dev nlohmann-json3-dev libchromaprint-dev ffmpeg \
# qt6-declarative-dev qt6-svg-dev qt6-svg-plugins qt6-multimedia-dev qt6-tools-dev qt6-l10n-tools libgl-dev libmpv-dev libsecret-1-dev
# (nur Server/Relay: TENJIN_BUILD_CLIENT=OFF)
TENJIN_SRC=. TENJIN_WORK=/tmp/tenjin scripts/build-linux.sh all Release
Ergebnis: dist\linux\Release\tenjin-server, tenjin-relay, tenjin-client (braucht zur Laufzeit Qt 6 Quick/QML-Module, qt6-svg-plugins für die Icons, libmpv2 und libsecret-1-0; die Anmelde-Tokens
verschlüsselt er mit einem Schlüssel im Schlüsselbund des Desktops – GNOME-Schlüsselbund oder KWallet –, ohne Desktop-Sitzung mit einer
Schlüsseldatei unter ~/.config/Tenjin/ nur für den eigenen Nutzer) und die systemd-Unit tenjin-server.service
(Installation: Binary nach /opt/tenjin, Nutzer tenjin in den Gruppen render/video, Daten unter /var/lib/tenjin,
systemctl enable --now tenjin-server). Zur Laufzeit braucht der Server die Qt-6-Bibliotheken (Core, Network, Sql mit
SQLite-Plugin, HttpServer, WebSockets), OpenSSL ≥ 3.5, libsodium, chromaprint und ffmpeg/ffprobe im PATH.
Seit 08.10.2026 mit QUIC/HTTP-3: ngtcp2 1.25 und nghttp3 1.18 sind statisch eingebunden (Lizenztexte unter
dist\linux\Release\LICENSES\), OpenSSL kommt vom System – Sicherheitsupdates von OpenSSL kommen damit über die Distribution.
Linux-Tests: 26/26 (wie Windows, mit test_quic und test_punch).
UI-Tests der App (nur Windows-Debug-Build, offscreen): ctest -L ui im Ordner build\msvc-debug – 230 Tests, rund 2 Minuten.
Jede Seite wird auf Desktop, Handy hoch und quer, TV und nach dem Drehen geprüft (keine QML-Fehler, nichts ragt aus dem Fenster,
kein zusammengedrückter Text, Dialoge im Fenster), dazu Regressionsszenarien gemeldeter Fehler (tests\ui\README.md).
2.1 Linux: Voraussetzung OpenSSL 3.5, Installation und Docker
OpenSSL ≥ 3.5 ist auf Linux Pflicht für Server und App. Der QUIC-Teil (ngtcp2 mit OpenSSL-Anbindung) nutzt die
QUIC-Schnittstelle von OpenSSL 3.5; die Programme sind gegen OPENSSL_3.5.0 gebunden und starten mit einem älteren
OpenSSL gar nicht (Fehler des Laders: „version OPENSSL_3.5.0' not found“). Prüfen: openssl version`.
| System | OpenSSL | Server / App | Relay |
|---|---|---|---|
| Debian 13 „trixie“ | 3.5 | ja | ja |
| Ubuntu 25.10 | 3.5 | ja | ja |
| Fedora 42, Arch | 3.5 | ja | ja |
| Ubuntu 24.04 LTS, Debian 12 | 3.0 | nein (Docker-Image nehmen) | ja |
Das Relay terminiert kein QUIC (es leitet die Pakete nur weiter) und braucht nur OpenSSL 3.0. Qt muss ≥ 6.8 sein (QtHttpServer); die Binärdateien sind auf Debian 13 gebaut und laufen auf Systemen mit gleicher oder neuerer glibc.
Direkt auf der Distribution (systemd):
sudo useradd --system --home-dir /var/lib/tenjin --shell /usr/sbin/nologin tenjin
sudo usermod -aG render,video tenjin # Hardware-Transcoding
sudo apt install ffmpeg libqt6network6 libqt6sql6-sqlite libqt6httpserver6 libqt6websockets6 libsodium23 libchromaprint1
sudo install -D -m 755 tenjin-server /opt/tenjin/tenjin-server
sudo install -d -o tenjin -g tenjin /var/lib/tenjin
sudo cp tenjin-server.service /etc/systemd/system/ && sudo systemctl daemon-reload && sudo systemctl enable --now tenjin-server
journalctl -u tenjin-server # Einrichtungscode beim ersten Start; Log auch unter /var/lib/tenjin/logs
Relay entsprechend mit tenjin-relay und tenjin-relay.service (Daten unter /var/lib/tenjin-relay). Firewall: TCP und
UDP 7800 (Server) bzw. 7900 (Relay).
Docker (Hauptweg für Linux): zwei Images, beide auf debian:trixie-slim (OpenSSL 3.5, Qt 6.8, FFmpeg), Programm unter
/opt/tenjin, läuft als Nutzer tenjin, Lizenztexte unter /opt/tenjin/LICENSES.
scripts\build-linux.cmd all Release && scripts\build-linux.cmd images Release # Images tenjin-server/-relay:<Version> und :latest
docker load -i tenjin-server-0.1.0.tar # auf dem Zielsystem (z. B. QNAP Container Station)
docker run -d --name tenjin-server --restart unless-stopped \
-p 7800:7800/tcp -p 7800:7800/udp \
-v tenjin-data:/var/lib/tenjin -v /pfad/zu/medien:/media:ro \
tenjin-server --port 7800 --name Wohnzimmer
docker logs tenjin-server # Einrichtungscode („setup code“) für die App
docker run -d --name tenjin-relay --restart unless-stopped \
-p 7900:7900/tcp -p 7900:7900/udp -v tenjin-relay-data:/var/lib/tenjin-relay tenjin-relay
docker exec tenjin-relay /opt/tenjin/tenjin-relay --data-dir /var/lib/tenjin-relay --new-code
- Ohne
--nameheißt der Server wie der Container-Hostname (eine zufällige ID). - Datenvolumes behalten: Sie enthalten Schlüssel und Zertifikat (Pins der Apps) bzw. die Identität des Relays.
- UDP-Port immer mitveröffentlichen, sonst kein QUIC (kein Hole Punching, Apps fallen auf HTTPS zurück).
- GPU:
--device /dev/dri(VAAPI/Quick Sync) bzw.--gpus allmit dem NVIDIA Container Toolkit; ohne GPU kodiert der Server in Software (Log „video encoders: libx264, libx265 …“). - Medienpfade im Container (z. B.
/media/Filme) als Bibliotheksordner anlegen.
Docker Compose: Media Server
Datei platform/docker/docker-compose.server.yml (liegt nach scripts\build-linux.cmd images auch in dist\docker\). Start mit
docker compose -f docker-compose.server.yml up -d, Einrichtungscode mit docker compose -f docker-compose.server.yml logs tenjin-server.
# Tenjin media server as a Docker container (docs/Einrichtungshandbuch.md, section 2.1 - every parameter explained there).
# Image: scripts\build-linux.cmd images -> dist\docker\tenjin-server-<version>.tar, on the target: docker load -i <tar>
# Requirement of the image: none on the host (Debian 13 inside: OpenSSL 3.5, Qt 6.8, FFmpeg).
# Start: docker compose -f docker-compose.server.yml up -d · setup code: docker compose logs tenjin-server
services:
tenjin-server:
image: tenjin-server:latest
container_name: tenjin-server
restart: unless-stopped
# Program options (the image always adds --data-dir /var/lib/tenjin).
command:
- --port=7800 # TCP (API, HTTPS) and UDP (QUIC/HTTP-3) port inside the container
- --name=Wohnzimmer # server name in the apps (default: the container's hostname, a random ID)
# - --bind=0.0.0.0 # listen address (default: all)
# - --verbose # debug logging
# - --no-tls # plain HTTP - only for tests in a trusted network
ports:
- "7800:7800/tcp" # host:container - keep both numbers equal (the server announces its QUIC port to the apps)
- "7800:7800/udp" # QUIC/HTTP-3 and hole punching; without it the apps fall back to HTTPS over TCP
volumes:
- tenjin-data:/var/lib/tenjin # database, keys, certificate, metadata, logs - keep it (the apps pin the certificate)
- /srv/media/filme:/media/filme:ro # media folders, read-only; add them in the app as /media/filme
- /srv/media/serien:/media/serien:ro
environment:
TZ: Europe/Berlin # time zone for schedules (tasks at 04:00) and log times
# TENJIN_WATCH_MAX_DIRS: "2000" # max. folders watched for changes (default 2000)
# Hardware transcoding, Intel/AMD (VAAPI, Quick Sync): pass the device and the host's "render" group ID.
# devices:
# - /dev/dri:/dev/dri
# group_add:
# - "105" # getent group render (on the host)
# Hardware transcoding, NVIDIA (NVENC/NVDEC): NVIDIA Container Toolkit on the host.
# deploy:
# resources:
# reservations:
# devices:
# - driver: nvidia
# count: all
# capabilities: [gpu, video]
# Discovery in the LAN (mDNS, "Im Netzwerk gefunden" in the apps) and UPnP need the host network; then drop "ports".
# network_mode: host
volumes:
tenjin-data:
| Parameter | Bedeutung |
|---|---|
image |
Das geladene Image (docker load -i tenjin-server-<version>.tar); :latest oder eine feste Version wie :0.1.0. |
container_name |
Name für docker logs/docker exec. |
restart: unless-stopped |
Startet nach Absturz und Neustart des Hosts wieder, nicht aber nach einem bewussten docker stop. |
command |
Programm-Optionen von tenjin-server. Das Image setzt --data-dir /var/lib/tenjin immer selbst (Entrypoint). |
--port=<n> |
TCP-Port der API (HTTPS) und UDP-Port für QUIC/HTTP-3. Standard 7800. |
--name=<name> |
Servername in den Apps und am Relay. Ohne Angabe der Hostname des Containers (eine zufällige ID). |
--bind=<adresse> |
Nur auf dieser Adresse lauschen. Standard 0.0.0.0 (alle) – im Container so lassen. |
--verbose |
Ausführliches Protokoll (Fehlersuche). |
--no-tls |
Reines HTTP ohne Verschlüsselung – nur für Tests im vertrauenswürdigen Netz; die Apps pinnen sonst das Zertifikat. |
ports |
Veröffentlichung Host:Container. TCP und UDP freigeben; beide Zahlen gleich lassen und gleich --port, weil der Server den Apps seinen QUIC-Port mitteilt (bei 17800:7800 suchten die Apps QUIC auf 7800). Fehlt UDP: kein QUIC, kein Hole Punching, die Apps nehmen HTTPS über TCP bzw. den Relay-Tunnel. |
volumes: tenjin-data:/var/lib/tenjin |
Daten des Servers: Datenbank, Schlüssel und TLS-Zertifikat, Metadaten, Bilder, Logs. Behalten – ein neues Volume bedeutet neue Identität und neues Zertifikat (Apps müssen neu koppeln). Sicherung = dieses Volume sichern. |
volumes: <host-pfad>:/media/…:ro |
Medienordner, nur lesend. In der App unter Verwaltung → Bibliotheken als Ordner /media/… anlegen. Netzlaufwerke auf dem Host einhängen und hier durchreichen (oder in Tenjin direkt als SMB/NFS-Quelle anlegen). |
environment: TZ |
Zeitzone für Zeitpläne der Aufgaben (z. B. „täglich 04:00“) und Zeitangaben in der Verwaltung. |
environment: TENJIN_WATCH_MAX_DIRS |
Höchstzahl der Ordner, die auf Änderungen überwacht werden (Standard 2000). Bei sehr großen Bibliotheken erhöhen; jeder Ordner belegt eine inotify-Überwachung. |
devices: /dev/dri + group_add |
Hardware-Transcoding mit Intel/AMD (VAAPI, Quick Sync). group_add ist die Gruppen-ID von render auf dem Host (getent group render), weil der Server im Container nicht als root läuft. |
deploy … driver: nvidia |
Hardware-Transcoding mit NVIDIA (NVENC/NVDEC); braucht das NVIDIA Container Toolkit auf dem Host. video in capabilities ist für NVENC nötig. |
network_mode: host |
Container im Netz des Hosts (dann ports weglassen). Nötig für das automatische Finden im LAN („Im Netzwerk gefunden“, mDNS) und für UPnP (Verwaltung → Netzwerk). Ohne: in der App die Adresse https://<host>:7800 eingeben. |
Einmalige Befehle im laufenden Container, z. B. docker compose -f docker-compose.server.yml exec tenjin-server /opt/tenjin/tenjin-server --version.
Das Admin-Konto legt man in der App mit dem Einrichtungscode an (--setup auf der Konsole ist für Installationen ohne App).
Docker Compose: Relay
Datei platform/docker/docker-compose.relay.yml (auch in dist\docker\). Start mit docker compose -f docker-compose.relay.yml up -d.
# Tenjin relay as a Docker container (docs/Einrichtungshandbuch.md, section 2.1 - every parameter explained there).
# Image: scripts\build-linux.cmd images -> dist\docker\tenjin-relay-<version>.tar, on the target: docker load -i <tar>
# Start: docker compose -f docker-compose.relay.yml up -d
# Registration code for a media server:
# docker compose exec tenjin-relay /opt/tenjin/tenjin-relay --data-dir /var/lib/tenjin-relay --new-code
services:
tenjin-relay:
image: tenjin-relay:latest
container_name: tenjin-relay
restart: unless-stopped
# Program options (the image always adds --data-dir /var/lib/tenjin-relay).
command:
- --port=7900 # TCP (TLS, tunnels) and UDP (reflector, QUIC passthrough) port inside the container
# - --bind=0.0.0.0 # listen address (default: all)
# - --cert=/certs/fullchain.pem # own certificate (e.g. Let's Encrypt) instead of the self-signed one in tls/
# - --key=/certs/privkey.pem # private key for --cert
# - --no-tls # plain TCP - only behind a TLS proxy or for tests
- --cache-gb=100 # size limit of the mode C cache in GB (default 100)
# - --cache-days=7 # entries unused for this many days are removed (default 7)
# - --cache-dir=/cache # cache directory (default /var/lib/tenjin-relay/cache; "off" = no cache)
# - --cache-key-file=/var/lib/tenjin-relay/cache.key # keep the cache key on disk (cache survives restarts)
# - --transcode-sessions=2 # parallel ffmpeg sessions for mode C transcoding (default 2)
# - --transcode-encoder=auto # auto | nvenc | qsv | amf | software
# - --no-transcode # never transcode at the relay
# - --ffmpeg=/usr/bin/ffmpeg # ffmpeg binary (default: PATH; the image brings ffmpeg)
# - --upnp # open the port on a home router via UPnP (needs network_mode: host)
# - --verbose # debug logging
ports:
- "7900:7900/tcp" # host:container - keep both numbers equal (servers and apps use the announced port)
- "7900:7900/udp" # reflector for hole punching and QUIC through the relay - required
volumes:
- tenjin-relay-data:/var/lib/tenjin-relay # identity (ID, certificate), registered servers, admin password, cache
# - /etc/letsencrypt/live/relay.example.org:/certs:ro # for --cert/--key
# - /srv/tenjin-cache:/cache # for --cache-dir
environment:
TZ: Europe/Berlin
# Hardware transcoding at the relay: as in docker-compose.server.yml (devices /dev/dri + group_add, or the NVIDIA block).
volumes:
tenjin-relay-data:
| Parameter | Bedeutung |
|---|---|
image, container_name, restart |
wie beim Server (docker load -i tenjin-relay-<version>.tar). |
command |
Programm-Optionen von tenjin-relay; --data-dir /var/lib/tenjin-relay setzt das Image selbst. |
--port=<n> |
TCP-Port (TLS: Steuerkanal der Server, Tunnel der Apps) und UDP-Port (Reflektor für Hole Punching, QUIC durch das Relay). Standard 7900. |
--bind=<adresse> |
Nur auf dieser Adresse lauschen (Standard alle). |
--cert=<datei>, --key=<datei> |
Eigenes Zertifikat, z. B. Let's Encrypt (fullchain.pem, privkey.pem), statt des selbst signierten unter tls/ im Datenvolume. Ordner dafür als Volume einhängen (/certs). |
--no-tls |
Reines TCP – nur hinter einem TLS-Proxy oder für Tests. |
--cache-gb=<n> |
Größe des Modus-C-Caches (terminierte Server, Abschnitt 6.3) in GB. Standard 100. |
--cache-days=<n> |
Cache-Einträge, die so viele Tage nicht genutzt wurden, werden gelöscht. Standard 7. |
--cache-dir=<ordner> |
Eigener Cache-Ordner (z. B. eine schnelle Platte als Volume /cache); off schaltet den Cache ab. Standard /var/lib/tenjin-relay/cache. |
--cache-key-file=<datei> |
Schlüssel des verschlüsselten Caches auf der Platte behalten – sonst liegt er nur im Speicher und jeder Neustart leert den Cache. |
--transcode-sessions=<n> |
Parallele FFmpeg-Sitzungen für das Transcoding am Relay (Modus C). Standard 2. |
--transcode-encoder=<name> |
auto, nvenc, qsv, amf oder software. Standard auto (erste funktionierende GPU, sonst Software). |
--no-transcode |
Am Relay nie transcodieren, auch wenn FFmpeg vorhanden ist. |
--ffmpeg=<pfad> |
FFmpeg-Programm. Standard: aus dem PATH (im Image enthalten). |
--upnp |
Port auf einem Heimrouter per UPnP öffnen – nur mit network_mode: host, auf einem öffentlichen Server nicht nötig. |
--verbose |
Ausführliches Protokoll. |
ports |
TCP und UDP 7900 veröffentlichen, beide Zahlen gleich lassen. Ohne UDP kein Hole Punching und kein QUIC durch das Relay (nur TCP-Tunnel). |
volumes: tenjin-relay-data:/var/lib/tenjin-relay |
Identität des Relays (ID, Zertifikat – die Server pinnen es), registrierte Server, Admin-Passwort, Cache. Behalten, sonst müssen sich alle Server neu registrieren. |
environment: TZ |
Zeitzone für Log-Zeiten. |
Einmalige Befehle (laufen neben dem Relay, gleiche Daten):
docker compose -f docker-compose.relay.yml exec tenjin-relay /opt/tenjin/tenjin-relay --data-dir /var/lib/tenjin-relay --new-code # Registrierungscode (24 h)
docker compose -f docker-compose.relay.yml exec tenjin-relay /opt/tenjin/tenjin-relay --data-dir /var/lib/tenjin-relay --set-admin-password <pw> # Relay-Admin in der App
docker compose -f docker-compose.relay.yml exec tenjin-relay /opt/tenjin/tenjin-relay --data-dir /var/lib/tenjin-relay --list # registrierte Server
docker compose -f docker-compose.relay.yml exec tenjin-relay /opt/tenjin/tenjin-relay --data-dir /var/lib/tenjin-relay --forget <serverId> # Server entfernen
macOS: Quellcode vorbereitet (platform/macos), noch keine Build-Pipeline.
3. Media Server einrichten
3.1 Starten
tenjin-server.exe # Konsole, Daten unter %APPDATA%\Tenjin\tenjin-server, Port 7800, TLS
tenjin-server.exe --data-dir D:\Tenjin --port 7800 --name Wohnzimmer
tenjin-server.exe --install # als Windows-Dienst (Administrator): Autostart, Firewall-Regeln, Daten unter %ProgramData%\Tenjin\Server
tenjin-server.exe --uninstall | --start | --stop
tenjin-server.exe --setup # Admin-Konto auf der Konsole anlegen (ohne App)
tenjin-server.exe --install --service-name Kinder --data-dir D:\TenjinKinder --port 7801 --name Kinder # zweiter Dienst
Weitere Optionen: --bind <adresse>, --no-tls (nur Testnetze), --verbose.
Neuer Server von null (Konsole): tenjin-server.exe --data-dir D:\TenjinNeu --port 7802 --name Neu – der erste Start mit
leerem Verzeichnis legt Datenbanken, Schlüssel und Zertifikat an und zeigt den Einrichtungscode; jeder weitere Start ist derselbe
Befehl. Mehrere Server auf einem PC brauchen je eigenen Port und eigenes Verzeichnis. Für einen Umzug von Jellyfin/Plex auf einen
frischen Server: TMDB-Schlüssel eintragen, Bibliotheken entstehen beim Import (Analysen erst danach einschalten), Quellen
nacheinander importieren (Abschnitt 3.4, „Umstieg von Jellyfin oder Plex“).
Mehrere Server als Dienste (seit 11.10.2026): Der Dienst heißt TenjinServer („Tenjin Media Server“). Mit --service-name <Name>
(Buchstaben, Ziffern, - und _) legt --install einen weiteren Dienst an: Dienstname <Name>, Anzeigename „Tenjin Media Server
(<Name>)“, eigene Firewall-Regeln und ohne --data-dir das Datenverzeichnis %ProgramData%\Tenjin\<Name>. Jeder Dienst braucht
einen eigenen Port (--port), und --uninstall, --start, --stop sowie --setup --data-dir … brauchen denselben
--service-name; der Name steht in der Befehlszeile des Dienstes (sc qc <Name>). Ohne die Option gilt immer der Standarddienst.
Im Datenverzeichnis liegen drei SQLite-Dateien: tenjin.db (Bibliotheken, Metadaten, Nutzerdaten, auch der Katalog der Online-Suche als
versteckte Bibliothek), metrics.db (Lastkurven der Verwaltung) und cache.db (zwischengespeicherte Provider-Antworten und Tagesbudgets;
darf gelöscht werden, kostet dann nur erneute Provider-Anfragen). Bilder liegen nie in der Datenbank, sondern unter metadata\. Für ein
Backup genügt tenjin.db samt server.key, tls\ und metadata\.
Datenverzeichnis verschieben (Verwaltung → Wartung → „Datenverzeichnis“, seit 10.10.2026): Der laufende Server zieht sein Datenverzeichnis auf einen anderen lokalen Pfad oder eine Netzfreigabe (UNC) um – ohne Dienst, Verknüpfung oder Aufrufparameter zu ändern. Ablauf: neuen Pfad eintragen → „Prüfen“ (erreichbar, beschreibbar, leer, freier Platz gegen benötigten Platz, nicht in einem Medienordner) → „Verschieben“. Der Server schaltet in die harte Wartung (Nutzer sehen den Countdown der Abmeldefrist aus den Wartungseinstellungen, Admins bleiben verbunden), kopiert Bilder, Vorschaubilder und Protokolle mit Fortschrittsanzeige, hält kurz an, kopiert, was sich währenddessen geändert hat, dazu Datenbanken, Schlüssel und Zertifikate, prüft alle Größen und startet sich im selben Prozess auf dem neuen Verzeichnis neu (die Verwaltung verbindet sich nach wenigen Sekunden wieder; die Server-ID und das Zertifikat bleiben dieselben). Danach steht der alte Ordner als Sicherung, bis „Altes Verzeichnis löschen“ gedrückt wird.
- Netzfreigabe als Ziel: Die Datenbanken (mit
server.keyundtls\) laufen nie über das Netz – SQLite sperrt dort unzuverlässig, und jede Abfrage der Verwaltung ginge über die Leitung. Die Karte fragt daher, ob sie im bisherigen Verzeichnis bleiben oder in ein zweites, zwingend lokales Verzeichnis ziehen. Das Dienstkonto braucht Schreibrechte auf der Freigabe (Laufwerksbuchstaben gelten im Dienst nicht – immer\\server\freigabeangeben). - Wie der Server den Weg findet: Im Verzeichnis, das der Aufruf nennt (Parameter, Dienst oder Standard), liegt danach
datadir.redirectmit den neuen Pfaden; der Server folgt ihr beim Start. Fehlt das Ziel (Freigabe nicht erreichbar), läuft er mit dem Startverzeichnis weiter und meldet es im Protokoll. Zurück ins Startverzeichnis geht derselbe Weg; die Umleitung verschwindet, sobald das alte Verzeichnis gelöscht ist. - Docker und systemd: dort ist die Karte ausgeblendet – das Volume bzw.
ExecStart/ReadWritePathsder Unit bestimmen den Ort. - Schlägt etwas fehl, bleibt das alte Verzeichnis unangetastet; startet der Server auf dem neuen nicht, nimmt er die Umleitung
zurück und läuft auf dem alten weiter.
transcode\und der Encoder-Cache werden nicht kopiert (Wegwerfdaten),logs\server.logbeginnt am neuen Ort neu.
3.2 Ersteinrichtung
- Beim ersten Start steht ein Einrichtungscode (z. B.
K7F3-9QZ2) auf der Konsole und inlogs/server.log. - App starten, Server aus der Liste wählen (mDNS) oder Adresse eingeben.
- Die App zeigt den SHA-256-Fingerabdruck des Serverzertifikats; mit der Serverkonsole vergleichen und vertrauen.
- Code eingeben, Admin-Konto anlegen.
- Admin → Provider & API-Keys: TMDB-Schlüssel eintragen. Optional OMDb: Schlüssel eintragen und den Tarif wählen (Free = 1.000 Anfragen am Tag, kleinere Poster, keine Folgenbeschreibungen; Premium = kein Limit, Poster-API, Folgenbeschreibungen). Die Karte „Reihenfolge der Provider“ legt je Medientyp fest, wen der Server nach dem Katalog zuerst fragt (▲▼); Provider ohne Schlüssel werden übersprungen, jede Bibliothek folgt der Liste ihres Typs.
- Admin → Bibliotheken: Bibliothek anlegen (Name, Typ Filme/Serien, Pfad; SMB als UNC-Pfad, als Dienst immer UNC). Scan und Metadaten laufen automatisch, Fortschritt unter Admin → Aufgaben.
3.3 Nutzer und Rechte
Admin → Nutzer: Konten mit Bibliotheksfreigaben, FSK-Grenze, Bandbreite lokal/remote, maximale Streams, Downloads, Watch-Together-Einladungen, „Wiedergabelisten für alle bearbeiten“, „Sammlungen bearbeiten“. Admin → Geräte: Limits je gekoppeltem Gerät (Filter nach Nutzer). Änderungen an einem Konto sind ein Entwurf: erst „Speichern“ schickt sie an den Server, „Verwerfen“ holt den gespeicherten Stand zurück. Die Aktualisierung alle 5 s überschreibt einen offenen Entwurf nicht – das gilt auch für den Bild-Cache je Gerät unter „Geräte & Diagnose“. Alle Limits (Konto-Bandbreite, Geräte-Limit, Client-Stream-Limit der Wartung) greifen nach der Bitrate: Eine Datei unter der Bitrate des Limits läuft unverändert, auch in höherer Auflösung; darüber wandelt der Server sie auf Auflösung und Bitrate des Limits um. Der Nutzer sieht auf der Detailseite „Limit vom Server“ mit der Quelle (Konto, Gerät, Wartung, Upload) und kann im Player nur niedriger stellen. Unter dem Konto die Karte „Geräte & Diagnose“: je Gerät des Nutzers, ob es online ist, ob das ausführliche Protokoll an ist, ein Schalter, der es für das Gerät setzt (die App übernimmt ihn bei der nächsten Statusabfrage, spätestens nach 10 s, und zeigt dem Nutzer einen Hinweis), und „Protokoll anfordern“ für Geräte, die online sind und das ausführliche Protokoll an haben: die App lädt dann die letzten 4 MB ihres Protokolls auf den Server, „Herunterladen“ speichert sie im Download-Ordner des Admin-Geräts.
3.4 Wichtige Admin-Einstellungen
Anime-Bibliotheken (Typ „Anime-Serien“/„Anime-Filme“): Texte, Staffeln und Bilder kommen von TMDB, danach trägt der Server die IDs von AniDB, AniList, MyAnimeList, aniSearch und TVDB an Serie und Staffeln ein und übernimmt die Namen von AniList (Romaji, Englisch, Original) als Alternativtitel – die Suche findet „Shingeki no Kyojin“ wie „Attack on Titan“. Grundlage ist die Anime-ID-Liste (Fribb/anime-lists), die die Aufgabe „Anime-IDs aktualisieren“ wöchentlich lädt (beim ersten Start nach zwei Minuten; Quelle änderbar über die Einstellung
anime.ids_url). Abfrage für Admins:GET /api/v1/admin/anime-ids?service=anidb&id=9541. Für große Bibliotheken auf dem NAS beim Anlegen „Untertitel nach dem Analysieren extrahieren“, Lautheit, Kapitel und Intro/Outro abschalten: jede dieser Analysen liest die Dateien ganz oder zu großen Teilen. Seit 21.10.2026 läuft die Untertitel-Extraktion als eigene Aufgabe erst, nachdem alle Dateien analysiert sind (ein ffmpeg-Lauf je Datei für alle Spuren) – „Abspielen“ wartet nicht mehr darauf, die Lesezeit auf dem NAS fällt aber weiterhin an (docs/Offene-Optimierungen.md). Filme findet der Server auch über ihre IMDb-ID, wenn die Liste die TMDB-ID nicht führt. Titel, die die Liste nicht kennt (Nicht-Anime, sehr neue Titel, Specials), behalten nur die TMDB-Daten. AniList braucht keinen Schlüssel. Details:docs/Konzept-Anime.md.Offene Detailseiten laden nach: Fehlen einem Titel beim Öffnen noch Metadaten (gerade kopierter Film, Treffer der Online-Suche) oder einer Person Biografie und Filmografie, holt der Server sie vorrangig – vor den übrigen Einträgen seiner Warteschlangen – und die Seite fragt nach, solange sie offen ist (erst alle 2 s, nach einer Minute alle 5 s); verlässt man sie, hört das Nachfragen auf. Neue Angaben erscheinen ohne Neuöffnen, neue Poster, Darsteller und Videos an Ort und Stelle (gescrollte Reihen und Raster bleiben stehen). Kein Titel wird doppelt geholt: fragt eine offene Seite oder „Metadaten aktualisieren“ nach einem Titel, der gerade geholt wird oder im laufenden Durchgang noch wartet, reiht der Server ihn nicht erneut ein. Scheitert ein Abruf (Provider nicht erreichbar, Tagesbudget), versucht der Server es für diesen Titel erst nach 5 Minuten wieder. Dateien, die noch kopiert werden, wartet die Seite bis zu 10 Minuten ab, dann erscheint „Abspielen“. Verwaltung → Provider & API-Keys → „Laufende Anfragen“ zeigt, wie viele Einträge für offene Seiten vorgezogen sind. Serien aus Suche, Entdecken oder Filmografien bekommen zuerst Poster, Besetzung und Beschreibung; ihre Staffeln holt der Server danach im Hintergrund – sofort, wenn jemand die Serie öffnet. Miniserien (z. B. Netflix-Fassungen von Filmen in Folgen) kennzeichnet die Personenseite als „Miniserie“; den Typ holt der Server für ältere Serien einmal kurz nach dem Start nach.
Trailer & Extras (Admin → Provider & API-Keys → Karte „Trailer & Extras“): Der Server speichert alle Videos, die TMDB zu einem Film oder einer Serie kennt. „Angezeigte Arten“ legt global fest, was die Apps unter der Besetzung zeigen (Standard: Trailer und Teaser; weitere: Clip, Featurette, Hinter den Kulissen, Pannen, Vorspann; keine Art = keine Videos). Reihe „Trailer“: Trailer und Teaser; Reihe „Extras“: die übrigen gewählten Arten – nur, wenn mehr als Trailer und Teaser gewählt ist –, höchstens „Extras in der Reihe“ (1–30, Standard 10), „Zeige alle“ öffnet eine Seite mit allen. Ebenso begrenzt „Trailer in der Reihe“ (1–30, Standard 10) die Reihe „Trailer“; „Zeige alle“ zeigt dort alle Trailer und Teaser. Speichern/Verwerfen wie bei allen Zahlen der Verwaltung. Sortierung: Sprache der Bibliothek, Englisch, Rest. Die Videos kommen mit den Metadaten ohne zusätzliche Anfrage; Titel, die vorher erfasst wurden, holen sie beim ersten Öffnen einmal nach (eine TMDB-Anfrage je Titel). Die Vorschaubilder lädt der Server im Hintergrund von YouTube, wenn ein Titel zum ersten Mal geöffnet wird, nur für die gezeigten Arten (Ordner
metadata/videos/<id>/); die Apps zeigen sie, sobald sie da sind, und speichern sie im Bild-Cache. Auf Android (Shield, Handy) öffnet ein Video direkt die YouTube-App, auch wenn andere Apps Web-Links öffnen könnten. Bis dahin – und dauerhaft, wenn YouTube kein Bild mehr hat – zeigt die Karte den Hintergrund des Titels. Fehlt ein Bild bei YouTube, versucht der Server es nach 5 Minuten und nach 24 Stunden noch einmal und gibt dann auf. Ein Klick öffnet das Video auf YouTube (PC: Browser, Shield und Handy: YouTube-App) – die Wiedergabe läuft nicht über den Server oder das Relay. Voraussetzung: TMDB-Schlüssel und eine TMDB-Zuordnung des Titels.Transcoding (Admin → Transcoding): Hardware-Encoder, Profile, Tone Mapping, temporäres Verzeichnis.
Aufgaben: Zeitpläne und Fenster der Analyse-Tasks; je Bibliothek abschaltbar (Untertitel, Vorschaubilder, Kapitel, Lautheit, Intro/Outro, Episodenbilder).
Wartung: Wartungsmodus (leicht/hart mit Countdown), Analyse-Balancer und Client-Stream-Limit.
Netzwerk: Upload-Balancer (Internet-Upload eintragen; Streams, die das Relay transcodiert, zählen mit ihrer Quelle und werden nicht gedeckelt), QUIC/HTTP-3 (Standard an), Portfreigabe per UPnP (Standard aus) – nur einschalten, wenn der Server bewusst aus dem Internet erreichbar sein soll. Beim Ausschalten entfernt der Server die Freigaben auf dem Router (Log „upnp: mapping removed“ je Port); nachprüfen in der FRITZ!Box unter Internet → Freigaben. Die Freigaben laufen nach einer Stunde von selbst ab, falls der Server abstürzt. Wer Hole Punching testen will, schaltet UPnP aus – sonst verbinden sich Clients über die Freigabe („Direkt (Portfreigabe)“). Paketgröße (Karte QUIC/HTTP-3): Statisch ist Standard (1.350 Byte; erlaubt 1.200–1.452, „Standard“ setzt 1.350 zurück) und passt durch VPN-Tunnel. Dynamisch lässt den Server die größte Paketgröße selbst ermitteln (bis 1.452 Byte) – nur sinnvoll ohne VPN-Zugriffe; über VPN wurden solche Pakete zerlegt und gingen verloren. Speichern wirkt ohne Neustart für neue Verbindungen (Anzeige „Aktiv: …“); bestehende behalten ihre Größe bis zum Neuverbinden.
Analyse-Leselimit (Admin → Aufgaben → Analyse): schont NAS und Netz während Analysen.
Bestätigungen wie „Netzwerkeinstellungen gespeichert“ verschwinden nach 5 s von selbst; Fehlermeldungen bleiben stehen, bis man sie schließt.
Benennung von Serien: „Serie/Staffel NN/Serie - S01E02 …“ ist am sichersten. DVD-Rips mit „title00“, „title01“ … im Staffelordner werden in Ordnerreihenfolge Folge 1, 2, … . Dateien ohne Folgennummer (Specials unter ihrem Titel) erscheinen als Folge ohne Nummer unter „Specials“ (letzte Staffelkarte der Serie) und bekommen beim Metadaten-Abgleich eine Nummer, wenn der Provider in Staffel 0 oder in der Staffel ihres Ordners eine Folge mit diesem Titel kennt (die Folge wandert dann in diese Staffel) – sonst lieber per Hand umbenennen („Serie - S00E05 - Titel“). Die Aktivitäten zeigen solche Dateien als „episode without number“.
Falsche oder fehlende Zuordnung: Titel ohne Treffer bleiben in ihrer Bibliothek und tragen auf dem Poster „Nicht zugeordnet“ (orangefarbener Rahmen). Als Admin über „…“ auf dem Poster (unten rechts; am TV OK lange drücken, auf Touch lange drücken) oder auf der Detailseite → „Zuordnung korrigieren“: Titel und Jahr prüfen, Provider und Metadaten-Sprache wählen, „Suchen“, Treffer wählen, „Zuordnen“. Die bisherige Zuordnung wird entfernt, Metadaten und Bilder werden neu geladen; Provider und Sprache bleiben für diesen Titel gemerkt. „Metadaten aktualisieren“ im selben Menü holt die Daten erneut, „Medien-Info“ zeigt Datei, Spuren und Provider-IDs.
Entdecken (Admin → „Entdecken“): Trends, Streaming, Kinostarts, Genres und neue Trailer von TMDB für alle Konten, Standard an, braucht den TMDB-Schlüssel. Region wählbar (DE, AT, CH, US, GB); Reihen sortieren (▲ ▼), an/aus, Titel je Reihe (5–60), Genre-Reihen hinzufügen – Änderungen gelten erst mit „Speichern“. Umsortieren und Abschalten wirken sofort, eine neue Region sowie neue oder größere Reihen lädt der Server direkt nach dem Speichern. Talkshows und Nachrichten erscheinen nie in Serien-Reihen; „Filme/Serien – Streaming“ zeigen, was in der Region bei Flatrate-Diensten beliebt ist (Daten von JustWatch über TMDB). „Neu auf Netflix / Prime Video / Apple TV / Disney+ / Paramount+“ (je Filme und Serien): Filme der letzten 6 Monate, Serien = Eigenproduktionen des Dienstes mit neuen Folgen der letzten 60 Tage, im Abo in der Region, nach Beliebtheit. „Neu auf Crunchyroll / Animation Digital Network“ (Anime-Filme, Anime-Serien, seit 21.10.2026): Anime (Animation aus Japan) im Abo des Dienstes, Serien mit Folge in 60 Tagen, Filme der letzten 12 Monate. Die Reihen werden alle 6 Stunden neu geladen; eine Minute nach dem Serverstart lädt der Server nach, wenn noch kein Schnappschuss da ist oder eine eingeschaltete Reihe darin fehlt (nur bei eingeschaltetem Entdecken) – eine Reihe ohne Treffer (etwa ADN-Filme) fehlt immer, sie abschalten vermeidet den Lauf beim Start. „Weil du „X“ gesehen hast“ (Filme, Serien) ist je Nutzer: Empfehlungen zum zuletzt gesehenen Titel, im Hintergrund berechnet – nach einem neuen Titel erscheint die Reihe beim nächsten Besuch. Alle neuen Reihen sind nach dem Update an und lassen sich hier abschalten und verschieben; eine gespeicherte Reihenfolge bekommt spätere Dienste einmal hinzu (Generation beim Speichern vermerkt). Was „Entdecken“ in den Katalog legt, bleibt dort, bis jemand „Katalog leeren“ wählt. Karte „Aktualisierung“: wie oft bekannte Serien erneut abgeglichen (Standard 7 Tage) und Trailer erneut gesucht werden (Standard 3 Tage); neue Titel kommen davon unabhängig bei jeder Aktualisierung sofort. 0 = bei jeder Aktualisierung alles neu fragen. Der Server lädt die Reihen alle 6 Stunden (Aufgabe „Entdecken aktualisieren“, sofort mit „Jetzt aktualisieren“); Titel, die nicht auf dem Server liegen, landen im Katalog und lassen sich auf die Wunschliste setzen. Konten mit FSK-Grenze sehen nur Titel mit passender Freigabe. Trailer öffnen auf YouTube (Fernseher: YouTube-App).
Bibliotheken am Fernseher: Oben in der Leiste stehen höchstens zwei Bibliotheken, alle übrigen hinter „Bibliotheken“. Dort öffnet OK auf dem Namen die Bibliothek; ▶ auf die Nadel und OK pinnt sie an oder löst sie (eine dritte ersetzt die am längsten angepinnte). Die Auswahl gilt je Gerät; ohne Auswahl die ersten zwei. Am PC zeigt die Seitenleiste immer alle Bibliotheken und scrollt bei vielen; auf dem Handy führt „Bibliothek“ unten zur Übersicht.
Umstieg von Jellyfin oder Plex: Verwaltung → Import, nur im Desktop-Client. Zwei Quellen nacheinander (gleiche Ordner): die zweite findet alle Titel wieder und ergänzt nur – Sammlungen gleichen Namens werden zusammengelegt, Sehstände je Folge nach der jüngeren Wiedergabe, Favoriten vereinigt; Serien mit gleichem Titel, aber anderem Jahr (Remakes) bleiben getrennt. Die Quellenliste zeigt je Quelle, ob sie nur untersucht oder schon importiert wurde (mit Zahl der Läufe und Zeit des letzten Imports); doppelt angebundene Quellen lassen sich mit „Entfernen“ bereinigen, das löscht nur die Datenbankkopie und die Zuordnungen, nie Titel aus der Bibliothek. Quelltyp wählen und den Datenordner des Jellyfin-Servers (enthält
data/jellyfin.db, ab Jellyfin 10.11) bzw. des Plex Media Servers (enthältPlug-in Support/Databases/com.plexapp.plugins.library.dbundMetadata) angeben – lokal oder als Netzwerkpfad, aus Sicht des Tenjin-Servers: ein lokaler Pfad gilt auf dessen Rechner. Die Quelle wird nur gelesen; Tenjin kopiert ihre Datenbank in seinen Datenordner (import/). „Anbinden und untersuchen“ zeigt das Inventar (Bibliotheken mit Wurzeln und Zählern, Nutzer, Sammlungen). Dann je Wurzel zuordnen: bestehende Tenjin-Bibliothek, neue (Name, Typ) oder überspringen, dazu der Zielpfad, unter dem der Tenjin-Server die Dateien erreicht; je Nutzer: bestehender Tenjin-Nutzer (alle seine Daten werden dorthin umgehängt), neuer (Jellyfin-Kennwort übernehmbar; ohne übernommenes Kennwort ein Startkennwort eintippen – Plex-Konten haben nie eines, ihr Kennwort liegt bei plex.tv) oder überspringen. Plex speichert die Medienpfade seines eigenen Rechners (auf einem NAS z. B./share/CACHEDEV4_DATA/Media/MV): bei jeder Wurzel den Pfad eintragen, unter dem der Tenjin-Server dieselben Dateien erreicht (\\nas\Media\MV). Aus Plex kommen keine Vorschaubilder (Tenjin rechnet sie selbst), keine Favoriten und keine Spurwahl; Bewertungen von Rotten Tomatoes werden nicht übernommen, Lautheitswerte schon. Bereiche ankreuzen, „Probelauf starten“: schreibt nichts, zählt Treffer, listet Titel ohne Treffer und sagt, wie viele der gewählten Sammlungen überhaupt Mitglieder in den zugeordneten Bibliotheken haben (Filmreihen brauchen die Filmbibliothek im selben Lauf). „Import starten“ (Rückfrage) läuft als Aufgabe im Hintergrund und legt neue Bibliotheken, Titel, Dateien und Nutzer an; Bilder, Kapitel, Vorschaubilder und Intro-Marken übernimmt er nur, wo Tenjin noch nichts hat (Kapitel und Folgenbilder mit „Quelle übernehmen“ auch sonst). Metadaten: Tenjin behält eigene Texte und Bilder, „Quelle gewinnt“ überschreibt Texte, Besetzung, Poster, Backdrops, Logos, Folgenbilder und Personenbilder; danach ist nichts gesperrt. Vorschaubilder: liegen sie bei Jellyfin neben den Mediendateien („Trickplay bei den Medien speichern“), verknüpft Tenjin sie ohne Kopie – sie bleiben beim Löschen des alten Servers erhalten; liegen sie in Jellyfins Datenordner, werden die Kachelbilder kopiert. Die Quelle bleibt unverändert; ein zweiter Lauf ergänzt nur, was fehlt. Das Ergebnis zeigt je Bereich, was geschrieben und was behalten wurde, eine Schätzung, wie viel eigene Analyse der Import erspart (Stunden bis Tage bei großen Bibliotheken), und lässt sich mit „Bericht als CSV“ in den Download-Ordner speichern (Lauf, Zähler, alle Fälle; öffnet in Excel mit Semikolon). Dazu die Fälle (fehlende Dateien, abweichende Größen – solche Dateien prüft Tenjin selbst, Disc-Abbilder wie ISO/IMG, die Tenjin nicht abspielt, Nutzer ohne Kennwort). Während des Imports pausieren die Bibliotheks-Scans; danach scannt Tenjin die betroffenen Bibliotheken einmal (findet externe Untertitel und Dateien, die die Quelle nicht kannte) und prüft nur noch, was der Import nicht füllen konnte. Ein großer Bestand (30.000 Dateien) braucht je nach Bereichen eine Viertelstunde und mehr; der Fortschritt steht in der Karte, Abbrechen lässt die bereits geschriebenen Titel stehen. Folgen, denen Jellyfin keine Nummer gegeben hat, bekommen Staffel und Nummer aus dem Dateinamen. Übernommene Jellyfin-Nutzer melden sich mit ihrem alten Kennwort an; Tenjin stellt es beim ersten Login auf sein eigenes Verfahren um. Dateien, deren Größe oder Änderungszeit nicht zur Quelle passt, bekommen keine Prüfdaten aus der Quelle und werden von der Prüf-Aufgabe nachgeholt; dasselbe gilt für Dateien, für die die Quelle keine Bitrate kennt (Plex bei etwa jeder fünften Datei) – Spuren und Dauer kommen aus der Quelle, die Bitrate liest Tenjin selbst nach („ohne Bitrate, Tenjin prüft nach“ im Ergebnis). Beide Quellen können nacheinander importiert werden (eine je Lauf); beim zweiten Lauf gewinnt bei Nutzerdaten der neuere Zeitstempel, alles andere wird nur ergänzt (docs/Konzept-Import.md).Verbindung weg (Server-Neustart, Netzwechsel, Funkloch): Die App bleibt auf ihrer Seite und verbindet von selbst neu (erst nach 3 s, dann 5 s, dann alle 10 s). Dauert das länger als 5 Sekunden, erscheint ein Panel mit Busy-Anzeige und Versuchszähler; „Abbrechen“ führt zur Verbindungsseite, die Anmeldung bleibt gespeichert. Läuft gerade ein Stream und spielt der Player noch aus seinem Puffer, erscheint statt des Panels nur der Hinweis „Verbindung unterbrochen – verbinde neu … Versuch n“ oben rechts (Handy hochkant in zwei Zeilen); er bleibt stehen und zählt die Versuche mit, solange der Stream läuft. Das Panel löst ihn ab, sobald der Player nicht weiterkann; der rote Hinweis des Players selbst („Verbindung unterbrochen – die Wiedergabe wird fortgesetzt …“) erscheint während der Wiederherstellung gar nicht mehr, erst wenn der Player nach 10 Minuten aufgibt (geprüft auf Shield und S26 hochkant und quer). Ein laufender Stream versucht währenddessen, an der letzten Stelle weiterzumachen; war gerade der Countdown „Nächste Folge“ am Laufen, startet die nächste Folge, sobald der Server wieder antwortet. Nach einem Server-Neustart nimmt die App wieder den direkten Weg (LAN, Hole Punching), nicht den Relay-Tunnel – ein Stream über den Tunnel wäre im Heimnetz unnötig langsam.
Größe der Oberfläche am Fernseher: Einstellungen → Darstellung (nur am TV): 80–120 %, Standard 100 % (die Oberfläche passt sich ohnehin der Bildbreite an, nicht der Zollgröße). Gilt je Gerät und wirkt nach „App neu starten“. Über 100 % zeigt die obere Leiste Start, Entdecken und Bibliotheken als Symbole und keine Uhr.
Verwaltung am Fernseher: alle Bereiche sind mit der Fernbedienung bedienbar (▲▼ Bereich, OK öffnet, ◀▶ ändert Zahlen und Auswahlen). Bibliothek löschen, Konto löschen und Relay trennen fragen vorher nach; „Ja“ muss ausdrücklich gewählt werden.
3.5 Firewall und Ports
| Port | Protokoll | Zweck |
|---|---|---|
| 7800 | TCP | HTTPS-API und Streams |
| 7800 | UDP | QUIC/HTTP-3 und Hole Punching |
| 5353 | UDP | mDNS-Ankündigung im LAN |
Der Dienst-Installer legt die Regeln an; bei manuellem Start die Regeln selbst anlegen (Konsole als Administrator:
netsh advfirewall firewall add rule name="Tenjin Server" dir=in action=allow protocol=TCP localport=7800, analog UDP).
Im Router ist für den LAN-Betrieb nichts nötig. Für Zugriff von unterwegs ohne Relay: UDP+TCP 7800 weiterleiten
oder UPnP im Server einschalten.
4. App einrichten
- Windows:
dist\msvc-release\client\tenjin-client.exe(mitlibmpv-2.dll) oder – ohne eigenen Deploy-Schritt – der Ordnerbuild\msvc-releaseFull\bin(Presetmsvc-releaseFull): Er entsteht bei jedem Build des Clients und enthält Qt, QML-Module, Plugins (auch das OpenSSL-TLS-Plugin für die Server-Zertifikate), libmpv, die vcpkg-DLLs, die MSVC-Laufzeit und eine portableqt.conf(Plugins und QML relativ zur exe). Ordner auf einen Windows-10/11-PC (x64) kopieren undtenjin-client.exestarten; nichts muss installiert werden. Die.pdb/.ilk-Dateien (Debug-Symbole) und – nach einem vollständigen Build – Server, Relay und Tests im selben Ordner braucht der Client nicht. Linux:tenjin-clientausdist\linux\Release. Android: APK installieren (Handy, Tablet, Android TV). - Player am Desktop ist libmpv (Hardware-Dekodierung, HDR, Bild-Untertitel direkt). Zum Vergleich startet
TENJIN_PLAYER=qtden Qt-Multimedia-Player; ohne libmpv nimmt die App ihn automatisch. - Erste Verbindung wie in 3.2. Danach merkt sich die App Server, Zertifikat, Tokens (Android: Keystore).
- Sitzungen bleiben angemeldet, solange die App einen Server mindestens alle 30 Tage nutzt. Taucht im Aktivitätslog die Warnung „Ein ersetzter Anmelde-Token … wurde erneut benutzt“ auf, hat jemand eine Kopie der Anmeldedaten dieses Geräts verwendet: der Server hat das Gerät abgemeldet. Das Gerät meldet sich neu an; wer das nicht selbst war, ändert sein Passwort.
- Quick Connect (vor allem für TV, Handy, Tablet ohne Tastatur, auch am Rechner): An der Anmeldemaske „Quick Connect“ wählen; das Gerät zeigt einen sechsstelligen Code mit 5-Minuten-Countdown. Auf einem Rechner, Handy oder Tablet, auf dem man angemeldet ist, im Konto-Menü „Quick Connect“ öffnen (Rechner: links unten, Handy: „Mehr“), den Code eingeben, das angezeigte Gerät prüfen und „Freigeben“ – das Gerät meldet sich von selbst an. Der Server muss auf dem Gerät schon gewählt sein: im Heimnetz unter „Im Netzwerk gefunden“, unterwegs unter „Von unterwegs über ein Relay“ (Relay-Adresse eintippen, Server wählen, Zertifikat bestätigen) – danach geht es auch dort mit Quick Connect weiter. Abschalten: Admin → Nutzer → „Anmeldung & Sitzungen“ → „Quick Connect erlauben“.
- Admin → Nutzer → „Anmeldung & Sitzungen“ (unter der Kontenliste): Erkennung an/aus (Standard an), Kulanzfrist (Standard 30 s) und wie viele Tage eine App ohne Nutzung angemeldet bleibt (1–365, Standard 30), Quick Connect an/aus (Standard an). Gilt für alle Konten und wirkt ohne Neustart.
- Navigation: am Desktop links die Seitenleiste (Start, Entdecken, Suche mit Strg+K, Favoriten, die Bibliotheken, Einstellungen, Verwaltung nur mit Admin-Recht; unten die Server-Karte mit dem Kontomenü), auf Tablets die schmale Leiste links, auf dem Handy die Leiste unten („Mehr“ öffnet Einstellungen, Verwaltung, Relay, Abmelden), auf dem TV die Pillen oben (Links/Rechts wechselt, Runter geht in die Seite, Hoch aus der Seite zurück in die Navigation).
- Detailseite: unter „Abspielen“ stehen drei Felder Video, Audio und Untertitel. Jede Option sagt, ob sie Direct Play, Remux oder Transcode auslöst; ohne Änderung wählt der Server wie bisher (gemerkte Serienauswahl, Sprache aus den Einstellungen). Bei Transcode zeigt das Video-Feld Quelle → Ziel (z. B. „4K · HEVC → 1080p HEVC“), die Zeile darunter den Grund (Limit vom Server mit Quelle Konto/Gerät/Wartung/Upload, eigene Qualitätseinstellung, eingebrannte Bild-Untertitel). Kapitel mit Bildern starten den Film an der Stelle.
- Sammlungen: Verwaltung → Bibliotheken → [Bibliothek] → „Sammlungen“ einschalten. Film-Bibliotheken bekommen die Filmreihen von TMDB automatisch („Alien Filmreihe“); der Server fragt dabei einmal je Film nach seiner Reihe (Aufgabe „Sammlungen aktualisieren“, danach täglich). Reihen erscheinen ab der eingestellten Anzahl vorhandener Titel (Standard 2) im Reiter „Sammlungen“ der Bibliothek, für alle Nutzer mit Zugriff; die Detailseite eines Films zeigt „Teil der Sammlung …“, am Filmende bietet der Player den nächsten Teil an. Umbenennen/Ausblenden dürfen Admins und Nutzer mit dem Recht „Sammlungen bearbeiten“ (Verwaltung → Nutzer): Sammlung öffnen → „Bearbeiten“. Ein neuer Name bleibt auch, wenn TMDB die Reihe anders nennt; ausgeblendete Sammlungen sehen nur diese Nutzer (mit dem Abzeichen „Ausgeblendet“).
- Eigene Sammlungen (Admins und Recht „Sammlungen bearbeiten“, Bibliothek mit eingeschalteten Sammlungen): „…“ an einem Film oder einer Serie → „Zu Sammlung hinzufügen“ → Sammlung wählen oder „Neue Sammlung …“; im Reiter „Sammlungen“ auch „+ Neue Sammlung“. Auf der Sammlungsseite nimmt „…“ → „Aus Sammlung entfernen“ einen Titel heraus (bei TMDB-Reihen bleibt er draußen), „Bearbeiten“ → „Löschen …“ löscht eine eigene Sammlung.
- Reiter einer Bibliothek: „Empfehlungen“ (Standard beim Öffnen) mit Fortsetzen, zuletzt veröffentlicht (Serien: Folgen), zuletzt hinzugefügt und den eigenen Genre-Reihen („Genre-Reihen hinzufügen …“ am Ende, je Nutzer; oben im Dialog legt „Reihenfolge“ mit ▲ ▼ fest, in welcher Folge sie erscheinen – neu gewählte kommen ans Ende); ein Klick auf eine Überschrift zeigt die ganze Reihe. „Kategorien“ zeigt alle Genres als Kacheln. Wie viele Titel eine Reihe zeigt, stellt der Admin je Bibliothek ein (Verwaltung → Bibliotheken → „Empfehlungen“, Werte ändern, dann „Speichern“).
- Mehrfachauswahl in Bibliotheken: am PC den Kreis oben links auf einem Poster anklicken, am Handy/Tablet lange drücken, am TV OK halten → „Auswählen“. Danach wählt jeder Klick / jedes Antippen / OK weitere Titel. Die Leiste oben: Abspielen, Favorit, Gesehen, Hinzufügen (Sammlung, Wiedergabeliste, zuletzt benutzte Listen) und „…“ (Zufallswiedergabe; Admins: Metadaten aktualisieren, Analysieren). „Alles auswählen“ nimmt alle Titel der Ansicht dazu, „Alles abwählen“ oder Zurück beenden die Auswahl.
- Reiter „Mediathek“: Unter dem Kopf stehen Filter-Chips, die beim Scrollen sichtbar bleiben – Sortierung (Titel, zuletzt hinzugefügt, Erscheinungsdatum, Bewertung, Laufzeit) und daneben die Richtung, Status (ungesehen/angefangen/gesehen), Genre, Jahrzehnt, Bewertung (ab 6–9), Qualität (4K/1080p/720p/SD), HDR (HDR, HDR10+, Dolby Vision), Audiosprache (die Sprachen der Bibliothek), Tonformat (DTS bis DTS:X/IMAX, Dolby Digital bis TrueHD/Atmos) und Favoriten; bei Genre, HDR, Sprache und Format sind mehrere Werte wählbar (ein Titel passt, wenn einer zutrifft). „Zurücksetzen“ nimmt alle Filter zurück. Jede Bibliothek merkt sich ihre Filter auf dem Gerät. Bei Sortierung nach Titel steht rechts die Buchstabenleiste: Buchstabe anklicken (Handy: am Rand entlangziehen, quer das Buchstabenband wischen und antippen; TV: ▶ aus der letzten Spalte, ▲ ▼, OK) springt zum ersten Titel mit diesem Buchstaben. Qualität, HDR, Audiosprache und Tonformat brauchen analysierte Dateien (Aufgabe „Medien analysieren“). Die Filter selbst lesen nur die dabei gespeicherten Angaben aus der Datenbank – sie öffnen keine Datei und starten kein ffprobe/ffmpeg. Nach dem Update auf Datenbank-Version 22 analysiert der Server Dateien mit DTS-Ton einmal neu (nur lesend), damit DTS-Varianten erkannt werden.
- Liste gemeinsam schauen: Auf der Seite einer Wiedergabeliste „Gemeinsam schauen“ (am Handy das Personen-Symbol) startet die Liste als gemeinsame Sitzung; andere Nutzer treten auf der Startseite bei („Liste „Name“ · 2 von 5 · Titel“). Der Gastgeber bestimmt Pause, Spulen und den Titel (Weiter, Zurück, Sprung in der Warteschlange); die Zuschauer folgen. Beitreten kann nur, wer jeden Titel der Liste sehen darf (Bibliotheksfreigabe und Altersgrenze). Zuschauer können nicht selbst weiterschalten; verlässt der Gastgeber den Player, endet die Sitzung für alle (die Zuschauer schauen dann allein weiter, mit dem Hinweis „Der Gastgeber hat das gemeinsame Schauen beendet.“). Zuschauer starten beim Beitritt und nach jedem Titelwechsel an der Stelle des Gastgebers; liegen sie trotzdem auseinander (vor dem 08.10.2026: Beitritt bei 0:00, nach „Weiter“ um die alte Position versetzt), App auf beiden Geräten aktualisieren.
- Wiedergabelisten: Jeder Nutzer legt eigene Listen an.
- Anlegen: Bereich „Wiedergabelisten“ → „+ Neue Liste“, oder „…“ an einem Titel → „Zu Wiedergabeliste hinzufügen“ → „Neue Liste …“. Mit dem Schalter „Für alle sichtbar“ sehen und spielen alle Nutzer die Liste.
- Bearbeiten: Ersteller; bei Listen für alle auch Admins und Nutzer mit dem Recht „Wiedergabelisten für alle bearbeiten“ (Verwaltung → Nutzer). Freigeben oder privat machen dürfen nur Ersteller und Admins.
- Entfernen: „…“ der Zeile → „Aus der Liste entfernen“ oder auf Handy/Tablet die Zeile nach links wischen; 5 s lang lässt es sich über „Rückgängig“ unten zurückholen, auch wenn man die Seite schon verlassen hat.
- Jeder Titel steht höchstens einmal in einer Liste; was schon drin ist, wird beim Hinzufügen übersprungen (mit Hinweis).
- Rückmeldungen: grün „Erledigt“, wenn sich die Liste geändert hat, gelb, wenn nichts zu tun war, rot bei Fehlern; sie verschwinden nach 3 s (Fehler 5 s), Antippen schließt sie sofort.
- Sichtbarkeit: Titel, die ein Konto nicht sehen darf (Bibliothek nicht freigegeben, FSK), fehlen für dieses Konto in der Liste.
- Sortieren:
- Maus und Touch: Zeile am Griff links ziehen.
- TV: OK auf einer Zeile halten öffnet ihr Menü (kurz drücken spielt ab hier) → „Verschieben“, dann ▲ ▼, OK legt ab, Zurück bricht ab.
- „…“ oben → „Sortieren …“ sortiert einmalig nach Titel, Jahr, Hinzugefügt, Dauer oder Serie/Folge.
- Abspielen: Im Player wechseln ⏮ ⏭ und die Media-Tasten Next/Previous den Titel; dazu Zufall, Wiederholen (aus · alle · dieser Titel) und das Panel „Warteschlange“. Am TV und am Handy quer bleibt die Leiste einzeilig (kleinere Knöpfe; beendet wird dort und auf Handys mit ■ oder Zurück, ✕ entfällt); am Handy hochkant fallen die Kapitelknöpfe weg (Kapitel über das Kapitel-Panel).
- Hinzufügen während der Wiedergabe: Einstellungen im Player (Regler-Symbol) → „Zur Wiedergabeliste …“ bzw. „Zur Sammlung …“; der Film läuft weiter.
- Nach einem Update des Servers legt dieser die Tabellen beim ersten Start an (Migration 19); alte Einträge gab es keine.
- Qualität und Limits: Einstellungen → Wiedergabe → Qualität ist eine Obergrenze dieses Geräts. Transcodiert wird nur, wenn die Bitrate der Datei darüber liegt; darunter läuft sie unverändert, auch in höherer Auflösung. Limits des Servers (Konto-Bandbreite, Admin → Geräte, Balancer) gehen vor. Das Qualitätsmenü im Player bietet nur Stufen bis zum wirksamen Limit („Automatisch“ = dieses Limit) und gilt nur für die laufende Wiedergabe. Admin → Transcoding (Videotranscoding, HEVC-Kodierung) wirkt auch auf die Anzeige. Jedes Limit zählt für sich: ein Geräte-Limit „720p“ ohne Bitrate gilt auch dann, wenn das Konto eine höhere Bandbreite erlaubt.
- Abspielgeschwindigkeit am Fernseher: Gibt die Box den Ton als Bitstrom an Verstärker oder Soundbar (TrueHD/Atmos, E-AC-3, AC-3), wechselt die App bei einer anderen Geschwindigkeit als „Normal“ kurz auf umgewandelten Ton (AAC, Hinweis im Player) und bei „Normal“ wieder auf den Originalton. Titel mit AAC-Ton und Handys sind nicht betroffen.
- Einstellungen → Verbindung: QUIC an/aus, Statuszeile des Transports, „Von unterwegs“ (Automatisch oder nur über das Relay). Einstellungen → Wiedergabe: Qualität, Audio/Untertitel-Vorgaben, Abweichungen je Bibliothek.
- „Weiterschauen“ auf der Startseite (und im Reiter „Empfehlungen“ der Bibliotheken) zeigt angefangene Titel und – in Serien- und Anime-Serien-Bibliotheken – nach einer gesehenen Folge die nächste, auch wenn sie noch nicht angefangen ist; je Serie eine Folge (die zuletzt geschaute). Ab 90 % der Laufzeit gilt ein Titel als gesehen und fällt heraus; wird er später erneut angespielt, erscheint er dort wieder, bis er erneut zu Ende ist.
- Statusleiste, Display-Aussparung und Gestenleiste werden einmal freigehalten; die Leisten der App reichen mit ihrem Hintergrund darunter.
- Fehlersuche Android (Entwicklung): Qt-Warnungen der App zeigt
adb logcat -s Tenjin. Hängt die App, zeigtadb shell top -H -p $(adb shell pidof org.tenjin.client)den HauptthreadqtMainLoopThread; Perfetto kann seine Aufrufstapel aufzeichnen (die App ist dafür über adb profilierbar,profileable shellim Manifest). Einen problematischen Titel kann man in der Layout-Vorschau nachspielen: Antwort vonGET /api/v1/items/<id>speichern,TENJIN_PREVIEW_ITEM_JSON=<Datei>undTENJIN_PREVIEW_PAGE=item:deepsetzen (TENJIN_LANG=defür deutsche Textbreiten). - Reiter wischen (Handy, Tablet): bei „Entdecken“ (Für dich / Filme / Serien) und in Bibliotheken mit Sammlungen (Mediathek / Sammlungen) blättert man seitlich zwischen den Reitern: Der Inhalt folgt dem Finger, nach links kommt der rechte Reiter, nach rechts der linke; kurzes Ziehen federt zurück. In den Posterreihen von „Entdecken“ scrollt das Wischen weiter die Reihe. Titel und Reiter bleiben beim Scrollen oben stehen, man sieht immer, welcher Reiter offen ist. Innerhalb von „Entdecken“ und einer Bibliothek merkt sich die App die Reiter: Ein Wechsel zeigt den Inhalt sofort und aktualisiert ihn im Hintergrund. Wer in einen anderen Bereich wechselt und zurückkommt, bekommt alles frisch vom Server.
- Handy im Querformat: schmale Leiste links mit Start, Entdecken, Suche, Bibliothek und „Mehr“ (Favoriten, Einstellungen, Verwaltung, Relay, Abmelden). Start zeigt den Hero links und „Weiterschauen“ als Zeilen rechts, die Detailseite ist zweispaltig (links Titel, Abspielen, Spurwahl mit Video und Audio nebeneinander und Untertitel darunter; rechts Beschreibung, Kapitel, Folgen), die Spurwahl öffnet als Panel von rechts. Reihen wie Kapitel und Weiterschauen wischen seitlich, die Seite selbst nur senkrecht. Die Suche sucht beim Tippen (ab zwei Zeichen), Enter sucht sofort; der Text trifft Titel und Originaltitel von Filmen und Serien sowie Namen von Personen, nicht die Besetzung. Die Chips unter dem Suchfeld sind Suchparameter: „Alle“ (Filme, Serien, Personen), ein Chip je Bibliothekstyp, den das Konto sehen darf, „Folgen“ (Folgen über ihren Titel, mit Serie und Nummer), „Personen“, „Verfügbar“ (nur Titel mit Mediendatei; der Online-Abschnitt entfällt dann), „Genre“ (Mehrfachauswahl aller Genres des Servers, gilt nicht für Personen) – jede Änderung sucht neu, die Chips bleiben bei neuer Eingabe gesetzt, „Alle“ hebt sie auf. „Datum“ und „Name“ sortieren die Antwort (eines aktiv, Klick dreht die Richtung). Auf schmalen Bildschirmen lässt sich die Chip-Zeile seitlich schieben.
- TV-Modus wird automatisch erkannt (kein Touchscreen); Bedienung mit D-Pad/Fernbedienung. Die Oberfläche passt sich der Auflösung an, mit der Android die App zeichnet (Shield: 1920×1080-Vorgabe, auch am 4K-Fernseher; das Video läuft in 4K). Alles ist mit den Pfeiltasten erreichbar: auf der Startseite führt ▲ aus „Weiterschauen“ zu „Fortsetzen“/„Details“, in der Suche ▼ unter den Treffern zu Personen und „Online suchen“, in der Verwaltung öffnet ▶ oder OK einen Bereich. Zahlenfelder ändert man mit ◀ ▶, ▲ ▼ gehen weiter. Einen Wunsch entfernt man am TV über „Auf der Wunschliste“ auf der Detailseite. Im Player: Taste C öffnet die Kapitel, S die Wiedergabeeinstellungen; nach einer Auswahl bleibt der Dialog offen, „Zurück“ schließt ihn, erst dann wirken die Pfeiltasten wieder als Spulen.
- Sprache: Einstellungen → Sprache. „Automatisch“ nimmt Deutsch, wenn das Gerät auf Deutsch läuft, sonst Englisch; „Deutsch“ oder „English“ legt sie fest. Meldungen des Servers (Aktivitäten, Fehler) erscheinen in derselben Sprache. Folgen stehen auf Deutsch als „S1 F3“ (Staffel 1, Folge 3), auf Englisch als „S1 E3“.
- Ordnerzeile unter Admin → Bibliotheken: der Server liest jeden Ordner über sein Dateisystem („Lokale Platte“ bzw. „Netzfreigabe über das Dateisystem“ bei UNC-Pfaden; SMB/NFS/WebDAV als eigene Quellen folgen). Dahinter die Änderungserkennung: lokale Platten melden Änderungen sofort, Netzfreigaben werden alle 15 Minuten abgeglichen (eine Dauerüberwachung würde die SMB-Handles großer Freigaben erschöpfen), „nur beim Scan“ wartet auf den Scan. Windows-Pfade erscheinen mit Backslashes, intern speichert der Server sie mit Schrägstrichen.
- Metadatensprache je Bibliothek: Admin → Bibliotheken → „Metadatensprache“ (Deutsch/English). Neue Bibliotheken übernehmen die Sprache der App; ein Wechsel lädt die Metadaten der Bibliothek neu.
- Online-Suche (Standard aus): Admin → Provider & API-Keys → „Online-Suche erlauben“ und bei jedem Provider, der mitsuchen soll, „Für die Online-Suche nutzen“ (nur mit Schlüssel). Danach steht in der Suche unter den Treffern „Online suchen“; erst dieser Klick fragt die Provider, pro Eingabe einmal, mit den gesetzten Chips (ein Typ-Chip holt nur diesen Typ, „Personen“ nur Personen). Steht „Alle“ und die Online-Suche findet eine Person, erscheinen auch ihre Filme und Serien, als „mit <Name>“ markiert (bei Genre-Filter nur passende); eine Gastrolle zeigt die Serie, nicht die Folge. Der Server holt dafür die Filmografie der ersten drei Personen (bis 40 Titel je Person) in den Katalog; die Personenseite holt beim ersten Öffnen die ganze Filmografie samt Besetzung der Titel im Hintergrund (je Titel rund 0,5 MB Bilder; Admin → Provider & API-Keys → „Katalog“ zeigt den Stand, Bildgröße ab 1 GB in GB). Die Karte „Grenzen der Suche“ daneben stellt die Zahlen ein: Personen je Online-Suche (3) und Titel je Person (40) – beide nur beim Filter „Alle“, die anderen Chips holen keine Filmografie –, Titel je Personenseite (unbegrenzt), Details je Gruppe (10), direkte Treffer der lokalen Suche (unbegrenzt; kappt die Liste erst nach den Filter-Chips), „Filmografie erneut prüfen nach“ (7 Tage – danach sieht die Personenseite beim Öffnen nach neuen Titeln, 0 = nur einmal) und der Antwort-Cache für Filmografien (24 h); 0 heißt unbegrenzt bzw. nie. Jede Zeile erklärt in der Verwaltung, was sie bewirkt. Was gefunden wird, speichert der Server im Katalog (Admin → Provider & API-Keys → „Katalog“): spätere Suchen finden es sofort als „Nicht vorhanden“ – die Detailseite eines Katalogtitels sagt oben, dass nur Metadaten vorliegen (und „Besetzung und Details werden gerade geladen“, bis der Server sie geholt hat – die Seite fragt selbst nach), „Nächste Folge“ fehlt, und in Staffel- und Folgenlisten sind Einträge ohne Datei gedimmt mit „Nicht vorhanden“ (das gilt auch für Lücken in eigenen Serien). Wenn die Datei später in einer Bibliothek liegt, übernimmt der Server die Katalogdaten beim nächsten Metadaten-Lauf (Besetzung, Bilder, IDs, auch Favorit und Bewertung) ohne neue Provider-Anfrage und entfernt den Katalogeintrag. Darüber hinaus wird der Katalog nie von selbst gelöscht, nur über den roten Knopf „Katalog leeren“. Wunschliste: Auf der Seite eines Katalogtitels setzt „Zur Wunschliste“ den Titel auf die eigene Liste (Seitenleiste bzw. „Mehr“ → Wunschliste); landet der Titel später in einer Bibliothek, gilt der Wunsch als erfüllt und das Aktivitätslog meldet es; der Eintrag bleibt mit grünem Chip „Erfüllt“ auf der Liste und verschwindet nach der in „Grenzen der Suche“ eingestellten Zahl Tage (Standard 7) von selbst. Entfernen geht jederzeit über das ✕ oben rechts auf dem Poster oder den Knopf „Auf der Wunschliste“ der Detailseite. Einträge überleben „Katalog leeren“ (dann ohne Bild; ein Klick sucht den Titel erneut) und wandern mit dem Nutzerdaten-Sync. Nutzern lässt sich das Recht „Online-Suche“ unter Admin → Nutzer nehmen (Standard an). Konten mit FSK-Grenze sehen nur Online-Treffer mit bekannter Freigabe; dafür holt der Server vor der Antwort die Details der ersten Treffer. Jede Online-Suche kostet je Provider eine Anfrage plus bis zu 30 Detailabrufe im Hintergrund; OMDb im Tarif Free und Google Books mit kleinem Tagesbudget besser nicht freigeben. Sind mehrere Provider freigegeben, fragt der Server sie gleichzeitig und legt gleiche Titel über die IMDb-ID zusammen; es gilt der Provider weiter oben in der Reihenfolge. Ein Chip unten links auf dem Poster zeigt, welcher Provider den Treffer geliefert hat. OMDb-Beschreibungen sind meist englisch, die Detailseite vermerkt das.
- Fehlt bei TMDB die Beschreibung in der Bibliothekssprache, nimmt der Server die englische und die Detailseite sagt es
unter dem Text („Beschreibung auf Englisch: …“). Gibt es in keiner der beiden Sprachen einen Text, sagt die Seite das beim Öffnen
(„Der Provider hat zu diesem Titel keine Beschreibung …“). Sprache und Grund stehen im Titel-Datensatz (
overview_language,overview_fallback). - Besetzung und Personen: Die Besetzung eines Titels kommt mit seinen Metadaten (bis 30 Personen, Darsteller zuerst). Biografie,
Geburts- und Sterbedatum, Geburtsort und Porträt einer Person holt der Server beim ersten Öffnen der Personenseite von TMDB in der
Metadatensprache der Bibliothek (Biografie notfalls englisch) und behält sie; ohne TMDB-Schlüssel zeigt die Seite nur Name und Titel.
Gaststars einer Folge erscheinen nach der nächsten Metadaten-Aktualisierung der Serie (Aufgabe „Metadaten“, spätestens nach 30 Tagen,
oder
POST /api/v1/items/<id>/refresh); Serien aus Suche und Filmografien bekommen ihre Staffeln (und damit Gaststars) im zweiten Durchgang im Hintergrund – die Reihe „Gastauftritte“ einer Person wächst daher mit der Zeit. Die Personenseite gliedert in „Filme“, „Serien“ (eigene Rolle in der Serie) und „Gastauftritte“ (einzelne Folgen, ein Klick öffnet die Folge; Selbst-Auftritte bleiben hier sichtbar, in der Filmografie nicht); jede Karte zeigt Titel, Jahr (· Miniserie bzw. · S3 F2) und Rolle. Unter „Serien“ stehen nur Serien, in deren Besetzung die Person steht (Haupt- oder Stammrolle); Serien mit einzelnen Gastauftritten erscheinen als Folgen unter „Gastauftritte“, beides zusammen ist möglich. Die Zahlen wachsen beim Nachladen nur noch. Nach dem Update auf Datenbank-Version 29 erscheinen Filme, die bei schon geöffneten Personen früher wieder verschwanden (Rolle hinter den ersten 30 der Besetzung), bei der nächsten Prüfung der Filmografie wieder („Filmografie erneut prüfen nach“, Standard 7 Tage). Die Seite antwortet sofort mit dem gespeicherten Stand und lädt Biografie, Filmografie und Poster nach, solange sie (oder ihr Raster) offen ist; beim Verlassen endet das Nachfragen. Die Reihentitel „Filme ›“, „Serien ›“, „Gastauftritte ›“ öffnen alle Titel der Reihe als Raster (Fernbedienung: ▲ von den Karten auf den Reihentitel, OK). Die Personenseite zeigt nur Titel, die auf dem Server liegen; Titel aus Bibliotheken ohne Freigabe für das Konto erscheinen abgeblendet als „Kein Zugriff“ (nur Titel und Jahr). Detailseiten: eine Folge zeigt einen Chip zu ihrer Staffel und das Datum der Erstausstrahlung, eine Staffel einen Chip zur Serie; der Zurück-Knopf oben links nennt die Seite, zu der er führt (Start, Suche, Person, „Serie › Staffel 1“ …). Am Fernseher: vom Abspielen-Knopf nach unten über die Kapitel zur Besetzungsreihe, OK öffnet die Person; ▲ vom Abspielen-Knopf erreicht die Chips und den Zurück-Knopf; „Zeige alle“ liegt eine Stufe über der Reihe und öffnet das Raster (OK öffnet die Person, Zurück führt zum Titel).
5. Zugriff von unterwegs
Drei Wege, die die App in dieser Reihenfolge selbst probiert:
- Direkt (Hole Punching): braucht ein am Relay registriertes Serverpaar (Abschnitt 6). Vergibt das Netz unterwegs je Ziel einen neuen Port (Büro, Mobilfunk), sucht die App bis zu 6 s den passenden Port (Portsuche) – keine Freigabe zu Hause nötig (am 08.10.2026 aus einem Büronetz und im Mobilfunk erfolgreich geprüft). Mit VPN ins Heimnetz zeigt die App „Direkt (LAN/VPN)“.
- QUIC durch das Relay: funktioniert ohne Freigabe zu Hause; das Relay leitet nur verschlüsselte Pakete.
- Tunnel über das Relay (TCP): Rückfall, ebenfalls ohne Freigabe. Im Modus C endet TLS am Relay.
Beim allerersten Verbinden über das Relay zeigt die App „Relay · HTTPS“ (Tunnel): Hole Punching und QUIC brauchen das Zertifikat des Servers, das sie dabei erst kennenlernt. Ab dem nächsten Start versucht sie zuerst Hole Punching („Direkt · QUIC“), dann QUIC durch das Relay („Relay · QUIC“).
Die Serverkarte unten links und der Kopf von Start und Verwaltung zeigen den Weg der Daten: „Direkt“ (Heimnetz), von unterwegs „Direkt (Portfreigabe)“ (der Server-Port ist im Router freigegeben, manuell oder per UPnP – der Server prüft das über das Relay; läuft das Relay im selben Netz wie der Server, erkennt er nur UPnP-Freigaben) bzw. „Direkt (Hole Punching)“ (ohne Freigabe durchgestochen), oder „Relay“ (QUIC durch das Relay oder Tunnel), dahinter QUIC oder HTTPS. Grün heißt direkt, blau Weiterleitung über das Relay, lila Terminierung am Relay. Die Relay-Einstellung „Passthrough/Terminierung“ gilt nur für Verbindungen über das Relay.
Ohne Relay bleibt nur eine eigene Portfreigabe plus manuelle Adresse (https://<öffentliche-adresse>:7800).
6. Relay einrichten (eigener öffentlicher Host)
tenjin-relay.exe --port 7900 --cert fullchain.pem --key privkey.pem # mit eigenem Zertifikat (z. B. Let's Encrypt), sonst selbstsigniert
tenjin-relay.exe --data-dir /var/lib/tenjin-relay # Datenverzeichnis (Standard: AppData)
Das Datenverzeichnis trägt die Identität des Relays (Relay-ID, Zertifikat, registrierte Server, Cache). Unter Windows ist
der Standard %APPDATA%\tenjin-relay; wer das Relay einmal mit --data-dir gestartet hat, muss es immer so starten – ein
Relay mit frischem Ordner hat eine neue ID und ein neues Zertifikat, und registrierte Server lehnen es wegen des gepinnten
Fingerabdrucks ab (Serverlog: „relay connection: The host name did not match …“).
tenjin-relay.exe --set-admin-password "<passwort>" # einmalig: Admin-Zugang für „Relay verwalten“
tenjin-relay.exe --new-code # Registrierungscode für einen Media Server (24 h, einmalig)
# Docker: docker exec tenjin-relay /opt/tenjin/tenjin-relay --data-dir /var/lib/tenjin-relay --new-code
tenjin-relay.exe --list | --forget <serverId> # Verwaltung auf der Konsole
tenjin-relay.exe --upnp # nur für ein Relay hinter einem Heimrouter
tenjin-relay.exe --cache-dir D:\tenjin-cache --cache-gb 200 --cache-days 14 # Modus-C-Cache (Standard <data-dir>/cache, 100 GB, 7 Tage; "off" = aus)
tenjin-relay.exe --cache-key-file /var/lib/tenjin-relay/cache.key # Cache-Schlüssel auf der Platte behalten (sonst nur im Speicher: Neustart leert den Cache)
tenjin-relay.exe --ffmpeg /usr/bin/ffmpeg --transcode-sessions 2 --transcode-encoder auto # Relay-Transcoding (Standard: ffmpeg neben dem Binary/bin/ffmpeg/PATH, 2 Sitzungen)
tenjin-relay.exe --no-transcode # kein Transcoding am Relay anbieten
Ports am Relay-Host: TCP und UDP 7900 eingehend erlauben (TCP: Steuer-, Tunnel- und Admin-Verbindungen, UDP: Reflektor und QUIC-Durchleitung). Die Durchleitung nutzt zusätzlich zufällige UDP-Ports für die Server-Seite; auf einem öffentlichen Host sind sie direkt erreichbar, hinter einem Heimrouter nur aus dem LAN.
6.1 Media Server registrieren
- Relay-Admin erzeugt einen Code (
--new-codeoder in der App unter „Relay verwalten“). - Server-Admin: Admin → Relay: Adresse
relay.example.org:7900und Code eintragen, „Speichern und verbinden“. Läuft das Relay auf demselben Rechner, trotzdem die öffentliche Adresse eintragen (DDNS-Name oder öffentliche IP, die FRITZ!Box beherrscht Hairpin-NAT): mitlocalhostmeldet das Relay den Server unter 127.0.0.1, und Hole Punching von unterwegs schlägt fehl (Telefon im Mobilfunk, 11.10.2026) – im Server-Protokoll steht dannreflexive address "127.0.0.1". Der Server verbindet sich ausgehend; keine Portfreigabe nötig. Das Relay-Zertifikat wird beim ersten Kontakt gepinnt und im Admin-Bereich angezeigt. - Status: Admin → Relay („Verbunden mit Relay …“, offene Tunnel, relay-seitige Einstellungen und wer sie zuletzt geändert hat).
6.2 Clients von unterwegs
Verbindungsseite → „Von unterwegs über ein Relay“: Relay-Adresse eingeben, „Server suchen“, Server wählen. Die App merkt sich das Relay und nutzt es automatisch, wenn der Server direkt nicht erreichbar ist.
6.3 Relay verwalten (Relay-Admin)
App: Nutzermenü oder Verbindungsseite → „Relay verwalten“, Adresse und Admin-Passwort. Dort: Status (Server online, Tunnel, UDP-Sitzungen, Bytes, Postfach, Versionsindex), je Server Modus (Passthrough/Terminierung), Cache, Transcoding, Bandbreite, Entfernen; Registrierungscodes; Audit-Protokoll. Terminierung (Modus C) ist die Voraussetzung für den Relay-Cache (Schalter „Cache“) und das Relay-Transcoding (Schalter „Transcoding“):
- Cache: Direct-Play-Dateien werden am Relay verschlüsselt zwischengespeichert und von dort ausgeliefert. Ohne
--cache-key-filelebt der Schlüssel nur im Speicher, ein Neustart des Relays leert den Cache. - Transcoding: das FFmpeg des Relays rechnet um (Direct Stream und Transcode), der Server liefert nur noch das
Original an das Relay. Das Relay braucht dafür FFmpeg (Statuszeile „Transcoding“ beim Start, Chip auf der
Admin-Seite) und ein Cache-Verzeichnis; Hardware-Encoder werden beim Start geprüft (
--transcode-encoder).
Die Terminierung zeigt dem Relay die Anfragen im Klartext und sollte nur bewusst eingeschaltet werden. Beide Admins dürfen Modus/Cache/Transcoding ändern, die letzte Änderung gilt. Admin → Relay im Server zeigt, ob das verbundene Relay Transcoding anbietet.
7. Konten verknüpfen (Sync zwischen zwei Servern)
Voraussetzung: beide Server sind am selben Relay registriert.
- App am Server 1 → Einstellungen → „Konten verknüpfen“ → „Verknüpfungscode erzeugen“ (eine Stunde gültig).
- App am Server 2 (Server wechseln, dort anmelden) → Code eingeben → „Verknüpfen“ (auf dem Handy steht der Knopf unter dem Codefeld).
- Beide Server bestätigen über das Relay; ab dann werden Fortschritt, Gesehen-Status und Favoriten alle 15 Minuten und bei neuer Post abgeglichen („Jetzt abgleichen“ stößt sofort an). Inhalte werden über Provider-IDs erkannt.
- „Verknüpfung aufheben“ beendet den Sync auf beiden Seiten.
Optional: Admin → Relay → „Versionsindex an das Relay melden“ (Standard aus) meldet, welche Filme und Folgen in welcher Qualität vorhanden sind (keine Nutzerdaten, keine Pfade).
Woanders vorhanden: Fehlt ein Film oder eine Folge auf dem eigenen Server, liegt aber auf einem Server, mit dem das Konto verknüpft ist und der seinen Versionsindex meldet, zeigt die Detailseite „Liegt auf „Name“ (Qualität)“. Hat die App für diesen Server eine gespeicherte Sitzung, startet „Auf „Name“ abspielen“ die Wiedergabe direkt von dort (in Suche und Wunschliste trägt das Poster dann „Auf „Name““ statt „Nicht vorhanden“); beim Verlassen der Seite kehrt die App zum eigenen Server zurück. Ohne Sitzung einmal über Konto → „Server wechseln“ auf dem anderen Server anmelden. „Server wechseln“ behält Server und Sitzung; die Verbindungsseite listet sie unter „Zuletzt verbunden“ (✕ löscht zuerst nur die gespeicherte Anmeldung dieses Geräts – der Eintrag bleibt mit „Anmeldung nötig“ –, ein weiteres ✕ entfernt den Server aus der Liste; andere Geräte und Nutzer des Servers betrifft das nicht).
8. Betrieb und Fehlersuche
Bild-Cache der App (seit 09.10.2026): Poster und Hintergrundbilder speichert jede App auf dem Gerät und zeigt sie beim
nächsten Mal ohne Anfrage an den Server. Einstellungen → „Bild-Cache“ (je Gerät): an/aus (Standard an), „Größe höchstens“
(100 MB–100 GB, Standard 2 GB), „Aufbewahren höchstens“ (1–365 Tage, Standard 7), „Cache leeren“, belegter Platz. Dieselben
Einstellungen setzt ein Admin aus der Ferne: Verwaltung → Nutzer → Konto → „Geräte & Diagnose“, je Gerät (Entwurf mit
Speichern/Verwerfen, „Cache leeren“); das Gerät übernimmt sie mit seiner nächsten Statusabfrage (bis 10 s) und meldet seinen Stand
zurück. Geänderte Bilder erscheinen sofort: Gecacht werden nur Bilder, deren Adresse die Version des Bildes trägt (Zeitpunkt
des letzten Downloads); ein neues Bild hat eine neue Adresse. Bilder ohne Version (neben den Mediendateien auf dem Share,
Personenfotos, Online-Suche) werden nie zwischengespeichert. Größe und Alter prüft die App beim Start und alle 6 Stunden im
Hintergrund. Ablage: Windows %LOCALAPPDATA%\Tenjin\tenjin-client\cache\images, Android im App-Cache (Systemeinstellungen →
Apps → Tenjin → Speicher → Cache leeren wirkt ebenfalls). Prüfen: Diagnosemodus an, im Protokoll erscheinen bei einem zweiten
Besuch derselben Seite perf img: request …-Zeilen, aber keine proxy: GET …/images/… (aus dem Cache).
Folgen ohne eigene Bilder (z. B. Serien von einer NAS ohne Episodenbilder) zeigen auf der Startseite, im Folgen-Detail und in der Folgenliste einer Staffel ersatzweise Hintergrund bzw. Poster der Staffel oder Serie
(eigene Bilder gehen immer vor; auch diese Bilder liegen im Bild-Cache).
Während eines Imports stehen Scan und Metadatenpflege: Beide Aufgaben enden während eines laufenden Imports sofort mit „Wartet auf den Import“ (eine bereits laufende Pflege hält vor dem nächsten Titel an) und laufen nach dessen Ende von selbst wieder an (der Import stößt den Scan seiner Bibliotheken an, der Scan die Pflege). Andere Aufgaben (Prüfen, Kapitel, Vorschaubilder, Lautheit) laufen weiter, wenn sie gerade laufen. Der Scheduler führt sonst höchstens zwei Aufgaben gleichzeitig aus, ein Import startet aber sofort in einer eigenen Spur und steht in der Warteschlange vor allen anderen Aufgaben (seit 11.10.2026 abends – vorher wartete der zweite Import hinter Scan und Prüfen).
Aufgaben „Kapitel erkennen“, „Intro/Outro erkennen“ usw. tauchen alle 15 Minuten auf: Das ist die Kette nach dem Abgleich der Netzfreigaben (Scan → Prüfen → Kapitel/Untertitel/Intro/Lautheit → Vorschaubilder). Jede Aufgabe prüft nur, ob es etwas zu tun gibt, und endet sonst sofort – Abbrechen ist nicht nötig; ob eine Analyse überhaupt läuft, bestimmen die Schalter der Bibliothek. Dauern diese Leerläufe Sekunden, fehlt der Index aus Migration 33 (Server vor dem 11.10.2026): ein Neustart legt ihn an.
„Bibliothek aktualisieren“ auf einer Netzfreigabe dauert Minuten: Der Abgleich listet alle Ordner der Freigabe (nie Dateiinhalte); kalt müssen die NAS-Platten erst aufwachen, warm dauert eine Freigabe mit 10.000 Dateien 10–30 s. Seit 21.10.2026 werden die zuletzt geänderten Ordner der ersten Ebene zuerst gelesen und sofort gespeichert – neue Titel erscheinen, bevor der Durchlauf fertig ist –, und bekannte Jellyfin-Trickplay-Ordner werden nicht mehr bei jedem Lauf gelistet. Das Intervall je Wurzel steht in der Verwaltung unter Bibliotheken.
Eine Analyse steht lange bei „0 %“ (vor 21.10.2026): Vorschaubilder, Lautheit, Kapitel und Untertitel lesen die ganze Datei; bei einer 50-GB-Remux über das NAS sind das mit 40 MB/s rund 20 Minuten. Bis 21.10.2026 meldete die Aufgabe den Fortschritt nur je Datei; seitdem zeigt die Verwaltung den Anteil innerhalb der Datei (z. B. „Vorschaubilder für X · 63 %“). Die Lesegeschwindigkeit stellt Verwaltung → Aufgaben → „Analyse-Lesegeschwindigkeit“ ein (0 = ungedrosselt, gilt ab der nächsten Datei); vorhandene Jellyfin-Trickplay-Ordner werden nur übernommen, wenn sie beim Start des Laufs schon da sind.
Abbrechen einer Analyse wirkt erst nach Minuten (vor 21.10.2026): Der Abbruch wurde nur zwischen zwei Dateien geprüft, ein laufender ffmpeg las die aktuelle Datei zu Ende. Seit 21.10.2026 beendet „Abbrechen“ den ffmpeg-Prozess sofort (Untertitel, Lautheit, Kapitel, Intro/Outro, Vorschaubilder); angefangene Ausgabedateien werden gelöscht, die Datei gilt nicht als fehlgeschlagen und kommt im nächsten Lauf wieder dran.
Ein Nutzer sieht in „Entdecken“ keine Poster und „Kein Zugriff auf diese Bibliothek“: Katalogtitel gehören keiner Bibliothek; ein Konto darf sie öffnen, wenn eine aktuelle Entdecken-Reihe sie zeigt. Bis 11.10.2026 galt das nur für die allgemeinen Reihen, nicht für die persönlichen („Weil du X gesehen hast“) – Server aktualisieren.
Server reagiert beim Start eines Titels minutenlang nicht (vor 21.10.2026): Hat ein Titel eingebettete Textuntertitel ohne vorab extrahierte Spur, holte der Server sie beim ersten Abruf synchron mit ffmpeg – auf dem Thread, der alle Anfragen bedient; bei großen Dateien auf dem NAS wirkte der Server bis zu fünf Minuten tot (er läuft weiter, kein Absturz). Seit 21.10.2026 läuft die Extraktion im Hintergrund, andere Anfragen werden weiter bedient. Dazu kommt bei einem NAS: Schlafende Platten wachen beim ersten Zugriff erst auf (einige Sekunden, einmalig) – der erste Start oder die erste Analyse einer Datei nach längerer Ruhe dauert deshalb länger, alle weiteren nicht.
Beschreibungen in der falschen Sprache nach einem Import (vor 20.10.2026): Hatte TMDB keinen deutschen Text, ersetzte die
Pflege den deutschen Text aus Plex/Jellyfin durch den englischen Ersatztext. Seit 20.10.2026 bleibt ein vorhandener Text in der
Bibliothekssprache stehen; schon ersetzte Texte holt ein erneuter Import nicht zurück (der Titel gilt als zugeordnet) – dafür das
Scratchpad-Skript restore_import_texts2.py <Datenverzeichnis> [--apply]: liest die Importkopien unter <data>/import/ (Jellyfin
zuerst, dann Plex) nur lesend, ordnet Dateien exakt über die Wurzelzuordnung des Imports zu und schreibt nur deutsch aussehende
Texte in Einträge mit overview_fallback (Server dazu beenden; Trockenlauf ohne --apply).
Staffeln nach Jahr oder geteilte Anime-Staffeln (seit 13.10.2026): Kennt TMDB die Staffelnummer nicht („Season 2004“, Anime mit Staffel 3, die bei TMDB Teil von Staffel 1 ist), ordnet die Pflege sie selbst zu – Jahresstaffeln über das Jahr der Erstausstrahlung, geteilte Staffeln über die fortlaufende Folgennummer. Die Staffel behält ihren Namen aus der Bibliothek, Texte, Bilder und Folgen kommen von TMDB. Ist die Zuordnung nicht eindeutig (zwei TMDB-Staffeln im selben Jahr, Lücken in den Folgen), bleibt die Staffel wie bisher ohne TMDB-Daten. Im Protokoll steht jede Zuordnung („mapped to provider season“); „Neu zuordnen“ an der Serie setzt sie zurück.
Dateien ohne Bitrate nach einem Import (vor dem 12.10.2026): Verwaltung → Bibliotheken → Bibliothek öffnen → „Ohne Bitrate nachprüfen“. Der Hinweis nennt, wie viele Dateien die Prüfaufgabe noch einmal liest; alle anderen bleiben unangetastet.
Android: „ERROR_CODE_IO_UNSPECIFIED: Source error“ bei jedem Film nach einem Plex-Import (vor 11.10.2026): Der Import speicherte die Bitrate tausendfach zu groß; der Server wählte darum Transcoding und schrieb eine HLS-Playlist mit einer Bandbreite, die Android nicht lesen kann. Server aktualisieren und neu starten – Migration 34 repariert die Bitraten, Direct Play greift wieder.
Personenseite eines Nutzers zeigt „Kein Zugriff“ ohne Poster: Bis 11.10.2026 galten Katalogtitel der Filmografie (Online-Suche) für Nicht-Admins als gesperrt, und gesperrte Karten kamen ohne Bild. Seitdem: Katalogtitel sind für Konten mit Online-Suche „Nicht vorhanden“ und öffnen sich; Titel aus nicht freigegebenen Bibliotheken bleiben „Kein Zugriff“, zeigen aber ihr Poster – Bilder kommen grundsätzlich für jedes angemeldete Konto.
Server antwortet nicht, der Prozess läuft aber (Konsole): Bis 11.10.2026 fror ein Klick in das Konsolenfenster (Windows
„QuickEdit“/Markieren-Modus) die Ausgabe ein und damit den Hauptthread des Servers – die App meldete den Server als nicht
erreichbar, obwohl er lief. Seitdem schreibt der Server die Konsole über einen eigenen Thread mit begrenzter Warteschlange (das
Protokoll in logs/ bleibt vollständig) und schaltet QuickEdit beim Start ab; dasselbe gilt für das Relay. Ältere Versionen:
Eingabetaste im Konsolenfenster drücken, der Server läuft weiter.
Die App wirkt träge (Leistungsanalyse): Einstellungen → Diagnose einschalten, den Ablauf einmal durchklicken, dann in
client.log nach perf suchen:
perf http: GET /api/… -> 200, … B, … ms (http3|https)– Dauer jeder Server-Anfrage aus Sicht der App und der Weg.perf job: queue … ms, work … ms, to ui … ms, ui … ms– Wartezeit auf den (einzigen) Anfrage-Thread der App, Dauer der Arbeit, Wartezeit bis die Oberfläche das Ergebnis annimmt, Dauer der Verarbeitung dort.perf img: request …– Zeitpunkt jeder Bildanforderung;perf ui stall: … ms– die Oberfläche war so lange blockiert (> 100 ms). Langeperf http-Zeiten beiqueue 0liegen am Server oder am Weg. Gegenprobe ohne App:quic_probe(Build-Ziel im Testordner,build\<preset>\bin\quic_probe.exe <host> <port> <fingerprint> <token> /api/v1/me …– misst über QUIC mit Pausen von 0–8 s) und ein HTTPS-Abruf von/api/v1/meim 100-ms-Takt: Hängt auch HTTPS, ist der Server selbst blockiert. Einzelne Admin-Abrufe lassen sich mit einem Admin-Token direkt messen (z. B.GET /api/v1/admin/search). Bekannter Fall (bis 09.10.2026): Eine offene Verwaltung irgendwo (Live-Aktualisierung alle 5 s) blockierte den Server alle 5 s für ~3,5 s, weilGET /admin/searchdie Größe von ~61.000 Katalog- und Personenbildern einzeln las – Server aktualisieren.Logs: Server
logs/server.logim Datenverzeichnis; App: Desktop schreibt%LOCALAPPDATA%\Tenjin\tenjin-client\client.log(Vorgängerclient.log.1), ausführlicher mit Einstellungen → Diagnose (ausführliches Protokoll; Android zusätzlich logcat). Mit ausführlichem Protokoll stehen die Decoder-Fakten drin (decoder: video … hwdec=…bzw.hw=yes/no, HDR-Transfer, am Ende verworfene Frames). Ein Admin holt das Protokoll eines Geräts über Admin → Nutzer → „Geräte & Diagnose“; der Server legt es unterlogs/clients/ab. Relay: Konsole (--verbose).Verwaltung (nur Admin-Konten): am Desktop Modul-Tabs, auf Tablets die Bereichsliste links, am Handy Bereichskacheln (jeder Bereich als eigene Seite, Zurück führt zur Liste), am TV die Bereichsliste neben „Streams & Last“ (▲ ▼ wählen, OK öffnet, Zurück verlässt). Übersicht und Aktivitäten gibt es am Desktop; die Kennzahlen (Streams, GPU, CPU, Netz) stehen überall oben in „Streams & Last“. Die GPU-Auslastung kommt vom Server (NVIDIA, AMD oder Intel); fehlt ein Wert, bleibt die Karte leer. Die Verlaufskurven sammeln ab dem Öffnen alle 5 s. „Live · alle 5 s“ gilt für Streams, Kennzahlen, Aufgaben (dort auch die Analyse-Lesegeschwindigkeit und die „Ruhefrist für neue Dateien“: Sekunden seit der letzten Änderung, bevor eine Datei analysiert wird – schützt Kopien, die noch laufen; bei neuen Dateien folgt nach 5 s ein zweiter Blick auf die Größe, und unter Windows gilt eine Datei, die ein anderes Programm noch zum Schreiben offen hat, grundsätzlich als „noch in Arbeit“, auch auf Netzfreigaben; die Detailseite sagt solange „Die Datei wird noch geprüft“ statt Abspielen), Aktivitäten, Geräte-Online-Stand, Providerzähler und „Laufende Anfragen“ (laufende Suchen, Warteschlange, aktueller Abruf – auch der einer offenen Personenseite –, „Zuletzt: …, vor N s“); Bibliotheken, Nutzer und Einstellungen lädt der Refresh-Knopf oben rechts neu.
Aktivitätslog (Admin → Aktivitäten am Desktop) zeigt Scans, Metadaten, Relay-Ereignisse, Sync, Warnungen; Filter nach Bereich.
Admin → Netzwerk: QUIC-Verbindungen mit RTT und Bytes, UPnP-Status, Upload-Balancer.
Admin → Relay → „Cache am Relay“ (nur mit Terminierung und Cache): wie viel dieser Server im Relay-Cache belegt, wie voll der Cache insgesamt ist, wie oft das Relay aus dem Cache geliefert hat und welche Titel dort liegen. Andere Server am selben Relay sieht man nicht.
Admin → Streams zeigt laufende Sitzungen mit Pfad A (direkt), B (Relay-Passthrough) oder C (am Relay terminiert) und der Adresse des Clients, auch hinter dem Relay. Verschwindet ein Client ohne Abmeldung (Absturz, Netz weg), bleibt seine Sitzung höchstens 3 Minuten nach dem letzten Abruf stehen; ein Neustart derselben App ersetzt sie sofort. Pausierte Player melden sich jede Minute und bleiben in der Liste. Die Detailkarte einer Sitzung zeigt den Transcoder-Vorsprung: wie viele Sekunden der Server bei Transcode und Remux (Direct Stream) vor der Wiedergabe liegt, ob er gedrosselt ist und welche Segmente er erzeugt hat – Hilfe bei Pufferpausen (großer Vorsprung + Puffern = Engpass beim Client oder im Netz). Bei Direct Play gibt es keinen Transcoder; dort steht „Direct Play – kein Transcoder, der Puffer liegt beim Player“.
Typische Probleme:
- Halten von Rechts/Links am Fernseher springt nur in 30-s-/10-s-Schritten statt zu spulen: ältere App-Version. Die Fernbedienung der Nvidia Shield (Android TV) schickt beim Halten eine Folge kurzer Tastendrücke statt einer gehaltenen Taste; seit dem 07.10.2026 erkennt die App das als Halten. Ein einzelner Tipp springt dort etwa eine halbe Sekunde verzögert.
- Abspielgeschwindigkeit am Fernseher (Shield) wirkt nicht bzw. die App stürzt beim Umschalten ab: ältere App-Version. Ton, den
die Box als Bitstrom an Verstärker/Soundbar gibt (TrueHD, E-AC-3, AC-3), kann Android nur mit 1× abspielen; ab dem 06.10.2026
wechselt die App bei ≠ 1× auf umgewandelten AAC-Ton und bei „Normal“ zurück. Die App braucht dafür den großen Speicherbereich
(
largeHeap); prüfen mitadb shell dumpsys package org.tenjin.client | findstr LARGE_HEAP. Ohne ihn lief der Java-Speicher bei 4K mit 2× voll (AbsturzOutOfMemoryErrorinSonic, vorher Pufferpausen alle ~15 s). - App findet den Server nicht: mDNS (UDP 5353) blockiert → Adresse manuell eingeben.
- Nur „HTTPS (TCP)“ statt HTTP/3: UDP 7800 blockiert (Firewall) → Regel anlegen; Funktion bleibt erhalten.
- Zertifikat „geändert“: Server neu aufgesetzt → Fingerabdruck prüfen und erneut vertrauen.
- Desktop-Player meldet „Der Player (libmpv) ist nicht verfügbar“ oder fällt auf Qt Multimedia zurück:
libmpv-2.dllfehlt neben der exe (Windows,scripts\fetch-mpv.cmdund neu bauen) bzw. Paketlibmpv2(Linux). - Wiedergabe meldet „Verbindung unterbrochen – die Wiedergabe wird fortgesetzt …“: Netz oder Server waren weg; die App probt den Server alle 5 s und setzt an der letzten Position fort, nach 10 Minuten gibt sie auf. Pausen bis 5 Minuten und Ausfälle bis 1 Minute überbrückt der Player meist aus seinem Puffer, längere Ausfälle enden in dieser Wiederaufnahme.
- Über VPN ins Heimnetz langsam oder Timeouts: bis 08.10.2026 waren QUIC-Pakete für VPN-Tunnel zu groß (zerlegt, Verluste) – Server und App aktualisieren. Prüfen: Verwaltung → Netzwerk, Sendefenster (cwnd) einer Verbindung bricht nicht mehr ein; „Paketgröße“ muss auf Statisch (1.350 oder kleiner) stehen.
- Nach einem Netzwechsel (WLAN aus, anderes WLAN) zeigt die App „Netzwerk gewechselt – verbinde neu …“ und braucht von unterwegs einige Sekunden (Direktversuch, dann Hole Punching). Meldungen wie „punch.tenjin.invalid not found“ gab es bis 08.10.2026 – App aktualisieren. Im App-Protokoll steht „network changed (…) - connecting anew“.
- Wiedergabe über HTTP/3 stockt, über TCP nicht: Einstellungen → Diagnose einschalten;
http3: failureoderno response after 20 sim Protokoll zeigen QUIC-Probleme, Admin → Netzwerk die Verbindungen. - Von unterwegs nur „Relay HTTPS“ und im Server-Log Punch-Anfragen ohne
/reflexive: Läuft auf dem Server-PC ein VPN-Client, der den gesamten Internetverkehr umleitet (OpenVPNredirect-gateway), gehen die UDP-Antworten von Server und Relay über den Tunnel hinaus und kommen nie an. Im VPN-Profil des Server-PCspull-filter ignore "redirect-gateway"setzen. - Von unterwegs nur Relay: das App-Protokoll (Konsole) zeigt „port search hit“ bei Erfolg bzw. „no answer from the server after the port search“; das Server-Log „hole punched by the port search“. Scheitert auch die Portsuche (sehr strenge Firewall), bleibt QUIC durch das Relay (automatisch) oder eine Freigabe zu Hause (UPnP oder Router).
- Transcoding fehlt: FFmpeg nicht gefunden →
bin\ffmpeg\oder Einstellungenmedia.ffmpeg_path/media.ffprobe_path. - Relay-Transcoding greift nicht (Sitzung läuft beim Server): Relay ohne FFmpeg oder Cache-Verzeichnis, Server nicht auf Terminierung, Schalter „Transcoding“ aus, oder die App hängt direkt am Server statt am Relay-Tunnel.
Updates: neue Binaries über die alten kopieren; Datenbanken werden beim Start migriert (Server, Relay). Vor einem Release-Build Server und Relay beenden: ein gesperrtes Binary bricht den Link-Schritt ab (LNK1168), bevor die übrigen Programme neu gelinkt sind – der alte Server läuft dann unbemerkt weiter.
Sicherung: das Datenverzeichnis (Datenbanken,
server.key,tls/) sichern;server.keybestimmt die Server-ID, ohne ihn müssen Apps neu koppeln und das Relay neu registriert werden.