Wii U Jellyfin Client
  • C 93.5%
  • Shell 1.7%
  • JavaScript 1.3%
  • Awk 1.2%
  • Makefile 0.9%
  • Other 1.4%
Find a file
Yasin Birgül 60b39e8321
Some checks are pending
build / wuhb (push) Waiting to run
build / tests (push) Waiting to run
Minutenlanger Streampuffer, und die restlichen Befunde der Analyse
Der Puffer

Sechzehn Megabyte waren fest verdrahtet, bei den voreingestellten acht
Megabit also rund sechzehn Sekunden. Das ueberbrueckt eine Stoerung, aber
nicht die Ausfaelle, die eine Wiedergabe wirklich unterbrechen: jemand
laedt etwas herunter, die Mikrowelle laeuft, der Router wechselt den Kanal.

Die Groesse steht jetzt als Dauer da und die Bytes folgen aus der Bitrate,
die die Qualitaetsstufe beim Server bestellt - vier Minuten, gedeckelt auf
160 MB. Das ergibt je nach Stufe zwischen knapp zwei und vier Minuten;
360p bekommt die vollen vier fuer 29 MB, 1080p bei 12 Mbit/s stoesst an
den Deckel. Was tatsaechlich belegt wurde, steht im Protokoll, denn
ensure_stream_buffer() halbiert sich herunter, bis es passt.

Der Vorlauf vor dem ersten Bild bleibt unveraendert kurz: die zwei
Sekunden aus PREBUFFER_SECONDS sind unabhaengig davon, wie gross die
Reserve dahinter ist. Sie fuellt sich hinter dem laufenden Bild.

Damit ein Block dieser Groesse nicht bei jedem Sprung zurueckgegeben und
sofort wieder geholt wird - genau der Weg zu einem Heap, der ihn irgendwann
nicht mehr liefert, und derselbe Grund, aus dem der Decoder den Sprung
ueberlebt - gehoert der Ringpuffer jetzt dem Player statt dem HttpStream.
http_stream_open() bekommt ihn geliehen und gibt ihn nicht frei. Er
ueberlebt auch player_open(), weil die Vorspann-Intros nacheinander da
durchlaufen, und faellt erst in player_close() weg; waehrend des Stoeberns
wuerde er nur den Bildcache aushungern.

ringbuf_reset() ist dafuer neu: es leert den Puffer und nimmt die Schalter
closed und aborted zurueck, sonst haette der zweite Stream in dem Moment
geendet, in dem er beginnt. Mit eigenem Test, der genau das nachweist -
absichtlich kaputtgemacht faellt er um.

Weil eine Prozentzahl von einer minutentiefen Reserve nichts mehr aussagt,
zeigt der Wartebildschirm jetzt Sekunden statt Prozent.

Ausserdem

* draw_toast() rechnete die Box von der rechten Kante nach links auf. Ab
  etwa hundertzwanzig Zeichen begann sie ausserhalb des Bildschirms. Kein
  theoretischer Fall: eine Spurbezeichnung kommt als DisplayTitle vom
  Server und bringt bis zu 127 Byte mit. Breite gedeckelt, Text gekuerzt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 18:01:31 +02:00
.github/workflows Hardware-Feedback: Diagnose, Quick Connect, Touch 2026-09-01 14:10:50 +02:00
content Nativer Jellyfin-Client fuer die Wii U (Aroma) 2026-09-01 11:15:57 +02:00
data Nativer Jellyfin-Client fuer die Wii U (Aroma) 2026-09-01 11:15:57 +02:00
patches Shader-Farben: Leseport-Konflikt in der ALU-Gruppe beheben 2026-09-02 20:09:01 +02:00
source Minutenlanger Streampuffer, und die restlichen Befunde der Analyse 2026-09-03 18:01:31 +02:00
tests Minutenlanger Streampuffer, und die restlichen Befunde der Analyse 2026-09-03 18:01:31 +02:00
tools Minutenlanger Streampuffer, und die restlichen Befunde der Analyse 2026-09-03 18:01:31 +02:00
.gitattributes Nativer Jellyfin-Client fuer die Wii U (Aroma) 2026-09-01 11:15:57 +02:00
.gitignore Shader-Farben: Leseport-Konflikt in der ALU-Gruppe beheben 2026-09-02 20:09:01 +02:00
LICENSE Nativer Jellyfin-Client fuer die Wii U (Aroma) 2026-09-01 11:15:57 +02:00
Makefile Nativer Jellyfin-Client fuer die Wii U (Aroma) 2026-09-01 11:15:57 +02:00
README.md Ausrichtungsregeln und Erfolgspruefung von Moonlight uebernehmen 2026-09-02 00:46:16 +02:00

Wii-U-Jellyfin

Ein nativer Jellyfin-Client für die Nintendo Wii U unter der Homebrew-Umgebung Aroma. Kein Browser, kein Wrapper — eine echte .wuhb-Anwendung, die mit devkitPPC und wut gebaut wird, über SDL2 auf die GX2-GPU rendert und Video mit dem H.264-Hardware-Decoder der Konsole dekodiert.

   Jellyfin-Server ──HTTPS──► libcurl ──► MPEG-TS-Demuxer ──┬──► H264DEC (Hardware) ──► NV12 ──► SDL2/GX2
                                                            └──► libfaad (AAC)      ──► PCM  ──► SDL2/AX

Funktionsumfang

Anmeldung

  • Quick Connect (Code auf dem Fernseher, Bestätigung in einem anderen Client) — muss auf dem Server unter Dashboard → Allgemein aktiviert sein
  • Benutzerliste des Servers oder manuelle Eingabe von Benutzername/Passwort
  • Eingabe über die systemeigene Wii-U-Bildschirmtastatur (nn::swkbd)
  • Token wird auf der SD-Karte gespeichert, beim nächsten Start geht es direkt weiter

Durchsuchen

  • Startseite mit Weiter schauen, Als Nächstes, Bibliotheken und Zuletzt hinzugefügt
  • Bibliotheks-Raster mit Nachladen beim Scrollen, Sortierung und Reihenfolge umschaltbar
  • Detailseite mit Backdrop, Poster, Beschreibung und Metadaten
  • Serien mit Staffelauswahl und Episodenleiste
  • Volltextsuche über Filme, Serien und Folgen
  • Artwork wird auf Hintergrund-Threads geladen und zwischengespeichert

Wiedergabe

  • Progressiver MPEG-TS-Stream vom Server (kein HLS-Playlist-Handling nötig)
  • H.264 über den Hardware-Decoder der Wii U, AAC über libfaad
  • A/V-Synchronisation über die Audio-Uhr
  • Pre-Roll-Intros von Server-Plugins wie Local Intros (siehe unten)
  • Ton- und Untertitelspur wählbar während der Wiedergabe (Taste Y)
  • Fortsetzen, Springen (±10 s / ±60 s), Pause, OSD mit Fortschrittsbalken
  • Untertitel werden serverseitig ins Bild gerendert (subtitleMethod=Encode)
  • Wiedergabestatus wird an den Server gemeldet (Start / Fortschritt / Ende), Fortsetzen-Punkte bleiben also über alle Clients synchron

Bedienung

  • GamePad, Pro Controller, Wiimote + Classic Controller — alles über SDL2s GameController-Mappings
  • Touch auf dem GamePad: Kacheln, Schaltflächen und Einstellungen lassen sich antippen; im Player tippt man auf den Fortschrittsbalken zum Springen
  • Die Oberfläche läuft standardmäßig auf Fernseher und GamePad

Installation

  1. Aroma auf der Wii U einrichten (siehe aroma.foryour.cafe).
  2. jellyfin.wuhb nach sd:/wiiu/apps/ kopieren.
  3. Wii U starten, im Wii-U-Menü die Anwendung öffnen (oder über das Aroma Homebrew-Menü).

Beim ersten Start legt die App sd:/wiiu/apps/jellyfin/ an — dort liegen config.json und jellyfin.log.

HTTPS-Zertifikate

Die Wii U hat keinen Systemzertifikatsspeicher. Das .wuhb enthält deshalb ein CA-Bundle unter /vol/content/cacert.pem. Alternativ kann eine eigene Datei nach sd:/wiiu/apps/jellyfin/cacert.pem gelegt werden — praktisch für selbstsignierte Zertifikate im Heimnetz.

Wird kein Bundle gefunden, verbindet sich die App trotzdem, prüft dann aber die Zertifikate nicht. Die Einstellungsseite zeigt den aktuellen Zustand an.


Bauen

Mit Docker (empfohlen, plattformunabhängig)

./tools/build-docker.sh          # Linux / macOS / Git Bash
powershell tools\build-docker.ps1 # Windows PowerShell

Das Skript nutzt das offizielle devkitpro/devkitppc-Image, installiert die benötigten Portlibs und legt jellyfin.wuhb im Projektverzeichnis ab.

Mit lokaler devkitPro-Installation

dkp-pacman -S --needed wiiu-dev wiiu-sdl2 wiiu-sdl2_image wiiu-sdl2_ttf \
                       wiiu-curl wiiu-mbedtls ppc-jansson ppc-faad2
make -j$(nproc)

Ergebnis: jellyfin.wuhb.

Die Artwork-Dateien unter data/ werden von tools/gen_assets.mjs erzeugt (node tools/gen_assets.mjs) und sind eingecheckt — Node wird zum Bauen also nicht gebraucht.


Steuerung

Taste Browsen Wiedergabe
A Öffnen / Auswählen Pause ⇄ Weiter · im Intro: überspringen
B Zurück Wiedergabe beenden
X Suche (Startseite) · Sortierung (Bibliothek) OSD anheften · im Intro: alle überspringen
Y Einstellungen (Startseite) · Reihenfolge (Bibliothek) Ton-/Untertitelspur wählen
L / R Seitenweise blättern ±60 Sekunden springen
Links / Rechts Auswahl bewegen ±10 Sekunden springen
+ Neu laden
HOME Zurück ins Wii-U-Menü

Sprünge werden gesammelt und erst ~0,7 s nach der letzten Eingabe ausgeführt — jeder Sprung startet auf dem Server eine neue Transkodierung, und so wird beim Scrubben nur eine einzige angefordert.


Wie die Wiedergabe funktioniert

Die Wii U kann H.264 in Hardware dekodieren (H264DEC* aus wut), aber sonst nichts. Deshalb fordert die App vom Server einen einzelnen, durchgehenden MPEG-TS-Stream an:

GET /Videos/{id}/stream.ts?container=ts&videoCodec=h264&audioCodec=aac
    &profile=high&level=41&maxWidth=1280&maxAudioChannels=2
    &allowVideoStreamCopy=true&allowAudioStreamCopy=true&startTimeTicks=…

allowVideoStreamCopy=true heißt: Jellyfin kopiert die Originalspur, wenn sie die Vorgaben ohnehin erfüllt, und transkodiert nur sonst. Das schont schwache Server erheblich.

Der Stream läuft durch:

Stufe Datei Aufgabe
Download source/net/http.c libcurl-Thread → Ringpuffer (4 MB)
Demuxen source/media/tsdemux.c PAT/PMT, PES-Zusammenbau, PTS
Video source/media/h264dec.c H264DECExecute → NV12-Bilder

| Audio | source/media/aacdec.c | ADTS → PCM über libfaad | | Takt | source/media/player.c | Audio-Uhr, Bildauswahl, Seek |

Die Dekodierung läuft auf Kern 2, das Netzwerk auf Kern 0, die Oberfläche auf dem Hauptkern.

Zwei Fallstricke von h264.rpl

H264DECExecute meldet Erfolg mit 0xE4, nicht mit 0. Der Rest der API benutzt 0. Wer das übersieht, verwirft jedes dekodierte Bild — nachzulesen im Referenzdecoder von FFmpeg-wiiu, der if (res != 0xE4) als Fehlerfall behandelt. Dasselbe gilt für H264DecodeResult.status.

Threads brauchen mehr Stack. SDL gibt Threads auf der Wii U per Voreinstellung 32 KB. Ein Aufrufpfad durch h264.rpl, libfaad oder curl+mbedTLS zurück in eigenen Code sprengt das. Alle Arbeits-Threads werden deshalb mit SDL_CreateThreadWithStackSize angelegt.

Intros / Pre-Rolls

Vor dem Start eines Films fragt der Client

GET /Items/{id}/Intros?userId=…

ab (mit Fallback auf die alte Route /Users/{uid}/Items/{id}/Intros für Server vor 10.10). Jedes Plugin, das serverseitig IIntroProvider implementiert — allen voran das offizielle Local Intros — liefert darüber seine Clips. Sie kommen als ganz normale Bibliotheks-Items zurück und werden über denselben Streaming-Pfad abgespielt wie alles andere.

Verhalten:

  • Intros laufen nur beim Start von vorn, nicht beim Fortsetzen aus der Mitte — sonst bekäme man den Vorspann bei jedem Wiederaufnehmen erneut.
  • Sie zählen nicht zur Wiedergabehistorie: kein Fortsetzen-Punkt, keine Statusmeldung, kein „wird gerade geschaut".
  • A überspringt das laufende Intro, X alle verbleibenden.
  • Ein Intro, das sich nicht öffnen lässt oder fehlschlägt, wird still übersprungen. Ein kaputter Vorspann darf den Film nie blockieren.
  • Abschaltbar unter Einstellungen → Intros abspielen.
  • Maximal 8 Clips werden abgespielt, als Schutz vor Fehlkonfiguration.

Eine Einschränkung, die nicht am Client liegt: Manche Plugins (z. B. die Episoden-Pre-Rolls von jellyfin-plugin-prerolls) hängen an einem JavaScript-Hook in Jellyfin Web statt an IIntroProvider. Solche Intros erreichen keinen nativen Client — weder diesen noch den Jellyfin Media Player. Was über IIntroProvider läuft, funktioniert hier.

Ton- und Untertitelspuren

Y öffnet während der Wiedergabe die Spurauswahl. Die Liste kommt aus MediaSources[0].MediaStreams und zeigt Jellyfins eigene DisplayTitle, also genau das, was auch der Webclient anzeigt — etwa „Deutsch - German - AAC - Stereo - Default".

Beim Start greifen die Vorgaben des Servers (DefaultAudioStreamIndex, DefaultSubtitleStreamIndex); ob der Standard-Untertitel gleich an ist, entscheidet die Einstellung Untertitel einbrennen.

Ein Spurwechsel startet den Stream an der aktuellen Position neu — die Auswahl steckt serverseitig in der Transkodierung, ein Umschalten im laufenden Strom ist nicht möglich. Das kurze Nachladen ist also unvermeidbar.

Verifiziert gegen einen Testserver mit zwei Ton- und zwei Untertitelspuren: die gewählte Tonspur kommt tatsächlich an (Messung der Grundfrequenz: Spur 1 → 442 Hz, Spur 2 → 883 Hz bei 440/880-Hz-Testtönen), und der Untertitel steht sichtbar im Bild.

Warum 720p und nicht 1080p?

Der Hardware-Decoder schafft 1080p — daran liegt es nicht. Der Engpass sitzt hinter dem Decoder: er gibt NV12 aus, die GPU will RGBA, und diese Umwandlung läuft auf der CPU. Ihr Aufwand skaliert linear mit der Pixelzahl, und 1080p sind 2,25-mal so viele Pixel wie 720p. 1080p macht die Wiedergabe also langsamer, nicht besser.

Dazu kommt: die Wii U gibt an den meisten Fernsehern ohnehin 720p aus. Ein 1080p-Stream würde beim Ausgeben wieder herunterskaliert — doppelte Arbeit ohne sichtbaren Gewinn.

1080p steht trotzdem in den Einstellungen, ehrlich beschriftet. Wer flüssige Wiedergabe will, geht in die andere Richtung: 480p hat nur 45 % der Pixel von 720p und ist entsprechend flüssiger.

Wo die CPU-Zeit hingeht — und was noch möglich wäre

Das Dekodieren läuft auf der Hardware, über h264.rpl. Was auf der CPU liegt, ist die Stufe danach: der Decoder gibt NV12 aus, die GPU will RGBA.

Moonlight Wii U zeigt, wie man auch das noch loswird, und macht dabei zwei Dinge, die dieses Projekt (noch) nicht kann:

  1. Kein Kopieren. Es legt mehrere GX2-Texturen an und übergibt deren Speicher direkt an H264DECExecute — der Decoder schreibt sein Bild also unmittelbar in den Texturspeicher.
  2. Umwandlung auf der GPU. Ein eigener Pixel-Shader (src/wiiu/shaders/display.psh) tastet die Y- und die UV-Ebene als zwei Texturen ab (UNORM_R8 und UNORM_R8_G8) und rechnet NV12 → RGB beim Zeichnen. Damit kostet die Umwandlung gar keine CPU-Zeit mehr.

Warum hier nicht: Moonlight zeichnet direkt mit GX2 und besitzt seinen Grafikzustand selbst. Dieses Projekt benutzt SDL2s Renderer für die gesamte Oberfläche, und der besitzt den GX2-Kontext und bietet keine Möglichkeit, eigene Shader einzuhängen. Moonlights Weg zu übernehmen hieße, das Videobild mit rohem GX2 neben SDL zu zeichnen und dabei dessen Zustand nicht zu zerstören — machbar, aber ein Eingriff, der sich nur auf echter Hardware erproben lässt.

Übernommen wurde, was sich gefahrlos übernehmen ließ: die Erfolgsprüfung von H264DECExecute und die genauen Ausrichtungsregeln des Bildspeichers (Zeilenbreite auf 256, Höhe auf 16 aufgerundet).

Der Weg vom Bild auf den Schirm

Ursprünglich lief das über eine SDL_PIXELFORMAT_NV12-Textur. SDL kann das, aber nur über einen generischen Software-Pfad: Bild in einen eigenen Puffer kopieren, dort umwandeln, dann hochladen — drei Durchläufe über jedes Bild. Auf einem 1,24-GHz-PowerPC waren das ~7 fps bei 1280×704.

Jetzt macht es source/media/nv12.c selbst:

  • SDL_LockTexture liefert auf der Wii U über GX2RLockSurfaceEx einen direkten Zeiger in den GPU-Speicher — die Umwandlung schreibt also unmittelbar dorthin, ohne Zwischenpuffer.
  • Die BT.601-Koeffizienten stecken in Nachschlagetabellen, die innere Schleife kommt ohne Multiplikationen aus und verarbeitet zwei Pixel pro Durchgang (beide teilen sich ein Chroma-Sample).
  • Die Arbeit wird auf zwei Kerne aufgeteilt: der Renderthread nimmt die obere Bildhälfte, ein Helferthread auf Kern 0 die untere.
  • Ein Bild wird nur einmal umgewandelt, auch wenn die Renderschleife es mehrfach zeigt.

Die Farbwerte sind auf dem Host gegen bekannte BT.601-Referenzwerte geprüft (tools/run-tests.sh), die Geschwindigkeit steht als convert N ms im Log.

Qualitätsstufen

Die Einstellungsseite bietet Automatisch (720p, bis 8 Mbit/s) sowie 720p/480p/360p mit festen Bitratengrenzen. 720p ist die Obergrenze — höher aufgelöstes Material lässt die Konsole zwar dekodieren, aber der Fernseher gibt ohnehin nur 720p aus.

Der Client sendet immer eine videoBitRate. Ohne diese Angabe nimmt Jellyfin eine sehr vorsichtige Voreinstellung an und skaliert das Bild entsprechend herunter: ein Testtranskodierung ohne Bitrate kam als 416×234 zurück, mit Bitrate als volle 1280×720.

Ebenso wird immer eine maxHeight mitgeschickt. maxWidth allein reicht nicht: eine 4:3-Quelle (1440×1080) kommt damit als 1280×960 zurück — mehr Zeilen, als der für 1280×720 eingerichtete Decoder verarbeiten kann. Mit Höhenbegrenzung sind es 960×720.


Fehlersuche

Die App schreibt jellyfin.log nach sd:/wiiu/apps/jellyfin/. Dort steht die Serverversion, die Stream-URL (Token geschwärzt) und der genaue HTTP-Status jeder fehlgeschlagenen Anfrage.

„Server kann den Stream nicht erzeugen (HTTP 500)"

Das ist ein Serverproblem, kein Client-Problem. Wichtig zu wissen: jede Anfrage an /Videos/.../stream.ts läuft durch ffmpeg — auch wenn die Datei schon H.264/AAC ist, muss sie nach MPEG-TS remuxt werden. Fällt ffmpeg aus, scheitert damit jeder Titel, auch ein zehn Sekunden langes Intro.

Nachgestellt mit einem Jellyfin-Container: nimmt man ffmpeg weg, antwortet der Server exakt so — HTTP 500, Body Error processing request.

Zu prüfen, in dieser Reihenfolge:

  1. Dashboard → Wiedergabe → Transkodierung: ffmpeg-Pfad gesetzt und gültig?
  2. Hardwarebeschleunigung testweise auf keine stellen. Eine falsch konfigurierte VAAPI/QSV/NVENC-Beschleunigung ist die häufigste Ursache.
  3. Transkodierungs-Pfad beschreibbar und genug Platz frei?
  4. Das Server-Log ansehen — dort steht der Stacktrace, der die Ursache benennt. Der Client kann nur den Statuscode zeigen.

Gegenprobe: die geloggte Stream-URL im Browser öffnen (Token wieder einsetzen). Kommt dort ebenfalls ein 500, liegt es sicher am Server.

Wiedergabe hängt bei „Puffer 0 %" oder die Konsole stürzt ab

War bis v1.0 ein Fehler im Client, siehe Git-Historie. Falls es weiterhin auftritt, steht die Ursache im Log:

  • h264: userMemory ist …, erwartet … — die Annahme über H264DECSetParam_USER_MEMORY stimmt nicht; bitte melden.
  • h264: frame needs N bytes, buffer holds M — der Decoder wählt ein größeres Layout als vorgesehen; die Reserve in h264dec.c muss dann größer werden.
  • Der Videodecoder liefert keine Bilder — es kamen ~15 s Video an, ohne dass ein einziges Bild herauskam.
  • video: N shown, M dropped … (X fps) — läuft alle 5 s mit und zeigt, ob die Pipeline mit der Bildrate mithält.

Quick Connect meldet „Server: aus"

Quick Connect ist in Jellyfin standardmäßig deaktiviert. Einschalten unter Dashboard → Allgemein → Quick Connect. Der Client fragt vorher /QuickConnect/Enabled ab und beschriftet die Schaltfläche entsprechend.

Ältere Server (10.8)

Getestet gegen Jellyfin 10.8.13 und 10.11.11. Für 10.8 gibt es Rückfälle auf die alten Routen (/Users/{id}/Views, /Users/{id}/Items/{id}/Intros); die 404-Warnungen im Log davor sind normal und harmlos.

Tests

./tools/run-tests.sh            # erzeugt einen TS mit ffmpeg und prüft ihn
./tools/run-tests.sh sample.ts  # oder gegen einen echten Server-Mitschnitt

Der Test schickt einen MPEG-TS-Strom durch source/media/tsdemux.c und prüft, was herauskommt: gültige Annex-B-Startcodes, SPS/PPS/IDR, ADTS-Synchronisation, monoton laufende PTS. Das ist der Teil der Medienpipeline, der sich ohne Konsole verifizieren lässt — gegen echten Jellyfin-Output läuft er sauber durch.

Projektstruktur

source/
├── main.c              SDL-Setup und Hauptschleife
├── app/                Zustandsmaschine, Navigation, Konfiguration, Eingabe, Tasks
├── common/             Logging, Stringhilfen, Ringpuffer
├── net/                libcurl-Wrapper und die Jellyfin-API
├── ui/                 Zeichenprimitive, Text, Bildcache, Bildschirme
└── media/              Demuxer, Decoder, Player

Grenzen

  • Nur Video. Musikbibliotheken werden angezeigt, aber nicht abgespielt.
  • Untertitel nur eingebrannt. Die Wii U hat keinen Untertitel-Renderer, der Server zeichnet sie ins Bild. Ein Wechsel kostet deshalb einen Neustart des Streams, und Untertitel erzwingen immer eine Transkodierung.
  • Kein Direct Play von HEVC, VP9 oder AV1. Der Server transkodiert diese Formate nach H.264; ohne ausreichend starken Server ruckelt es.
  • Die Medienpipeline ist gegen die dokumentierten wut-APIs geschrieben, wurde aber nicht auf echter Hardware gegengetestet — siehe unten.

Status

Auf echter Hardware (Wii U mit Aroma) getestet. Funktioniert dort: Start, Anmeldung mit Benutzer/Passwort, Navigation, Bibliotheks- und Detailansicht mit Artwork. Der H.264-Hardwaredecoder initialisiert sich korrekt (38 MB Arbeitsspeicher für 720p) und das Audiogerät öffnet mit 48 kHz.

Die eigentliche Bildausgabe — H264DECExecute → NV12 → SDL2s YUV-Texturpfad — konnte noch nicht beobachtet werden, weil der Teststream serverseitig fehlschlug (siehe Fehlersuche). Der Demuxer davor ist gegen echten Jellyfin-Output verifiziert.

Lizenz

GPL-3.0-or-later — siehe LICENSE. Die Verlinkung gegen libfaad (GPL-2.0) macht diese Wahl notwendig.

Dieses Projekt steht in keiner Verbindung zu Jellyfin oder Nintendo.