Drei Ebenen (allgemein → Mediathek → Serie), eine globale Rangliste als Boden darunter, und die Wahl als prüfbares Punktesystem. Zwei Funde bestimmen den Entwurf: **Jellyfin hat kein Kennzeichen für Audiodeskription.** `MediaStream` führt `IsDefault`, `IsForced`, `IsHearingImpaired`, `IsOriginal` — nichts für Sehschädigung; die `visual_impaired`-Disposition reicht der Server nicht durch. Sie ist nur am Text zu erkennen, und deshalb muss die Erkennung nachsichtig sein und sich überstimmen lassen. **Der Sprachvergleich greift heute bei `ger` nicht.** Verglichen werden die ersten zwei Zeichen, also `ge` gegen `de` — und `ger` ist die ISO-639-2/B-Form von Deutsch, die ffmpeg in viele Dateien schreibt. Bei solchen Titeln wirkt die Spracheinstellung lautlos gar nicht. Gemessen, nicht vermutet. Auf Serienebene wird nicht eine Sprache gespeichert, sondern die Signatur der tatsächlich gewählten Spur. Nur so ist der ZDF-Fall lösbar, bei dem die deutsche Spur die mit Audiodeskription ist und die als englisch ausgezeichnete die richtige. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
11 KiB
Standardsprachen für die Tonspur
Kontext
Heute gibt es genau eine Einstellung: eine bevorzugte Tonsprache für alles. Sie wird angewandt, indem die erste Spur genommen wird, deren Sprachcode passt (PlayerModel.swift:1374). Kein Abwägen, keine Ausweichkette, keine Rücksicht darauf, was für eine Spur das ist.
Gewünscht ist etwas Abgestuftes: eine allgemeine Sprache, eine je Mediathek, und bei Serien eine je Serie — damit die eine auf Englisch läuft und die andere auf Deutsch.
Und ein konkreter Ärger, der den ganzen Entwurf bestimmt.
Der ZDF-Fall
Bei manchen ZDF-Serien ist die als deutsch ausgezeichnete Spur die mit Audiodeskription, und die als englisch ausgezeichnete ist in Wahrheit Deutsch ohne Audiodeskription.
Daran scheitert jede Lösung, die nur „bevorzuge Deutsch" sagt — sie wählt zuverlässig die falsche. Wer hier ankommen will, muss zwei Dinge können:
- Audiodeskription erkennen und meiden.
- Eine einmal getroffene Wahl für die ganze Serie behalten, auch wenn sie einer Sprache widerspricht.
Was Jellyfin hergibt — und was nicht
Aus MediaBrowser.Model/Entities/MediaStream.cs (Stand master):
| Feld | da? |
|---|---|
Language |
ja |
Title (roh aus der Datei) |
ja — holen wir heute nicht |
DisplayTitle (zusammengesetzt) |
ja |
IsDefault, IsForced |
ja |
IsHearingImpaired |
ja |
IsOriginal |
ja |
| Audiodeskription | nein |
Es gibt kein Kennzeichen für Audiodeskription. IsHearingImpaired meint Hörschädigung (Untertitel mit Geräuschbeschreibung), nicht Sehschädigung. Die visual_impaired-Disposition aus dem Container reicht Jellyfin nicht durch.
Folge: Audiodeskription ist nur am Text zu erkennen. Das ist keine schöne Lösung, aber die einzige — und es heisst, dass sie nachsichtig sein und sich überstimmen lassen muss.
Heute dekodieren wir von einer Spur nur Index, Type, Codec, Language, DisplayTitle, Channels, IsDefault, IsForced (JellyfinItem.swift:166). Title, IsHearingImpaired und IsOriginal kommen dazu.
Entwurf
Drei Ebenen, eine Frage
Serie → Mediathek → allgemein
Jede Ebene kann „wie die Ebene darüber" sagen. Gefragt wird von unten nach oben; die erste Antwort gilt. Bei Filmen gibt es die Serienebene nicht — dort endet es bei der Mediathek, und genau so war es gewünscht.
Gespeichert wird nicht „eine Sprache", sondern eine Spur
Das ist die Kernentscheidung, und sie kommt aus dem ZDF-Fall.
Auf der Serienebene wird nicht „Deutsch" abgelegt, sondern eine Signatur der Spur, die tatsächlich gewählt wurde:
TrackSignature { languageCode, normalizedTitle, channels, codec }
Eine Kennung („Spur 2") taugt nicht: Folgen derselben Serie haben unterschiedlich sortierte Spuren. Eine Signatur überlebt das, weil sie beschreibt, wie die Spur aussieht.
Damit ist der ZDF-Fall lösbar: einmal die „englische" Spur wählen, und jede weitere Folge nimmt sie — obwohl der Sprachwunsch Deutsch lautet.
Auf Mediatheks- und allgemeiner Ebene bleibt es bei einer Sprache. Dort wäre eine Signatur sinnlos, weil sie über verschiedene Titel hinweg nichts bedeutet.
Die Wahl als Punktevergabe
Ein reiner Typ in FlixyPlayback/Decision/AudioTrackChooser.swift — Spuren und Wunsch hinein, eine Spur heraus. Kein Netz, keine Einstellungen, keine Ansicht. Dieselbe Bauform wie PlaybackDecider, StreamHealth und DowngradeRule, und aus demselben Grund: eine Regel, die man nicht mit einer Zahlenfolge durchspielen kann, ist nicht zu beurteilen.
| Kriterium | Punkte |
|---|---|
| passt zur gemerkten Signatur | +100 |
| passt zur gewünschten Sprache | +60 |
| steht in der Rangliste | +50 minus Position |
IsDefault |
+10 |
| mehr Kanäle (5.1 vor Stereo) | +1 je Kanal |
| sieht nach Audiodeskription aus | −200 |
| sieht nach Kommentarspur aus | −200 |
Gewinnt die höchste Summe; bei Gleichstand die Spur mit der kleineren Nummer, damit dieselbe Datei immer dasselbe ergibt.
Abzug statt Ausschluss, und das ist Absicht: gibt es eine Sprache nur mit Audiodeskription, ist sie immer noch besser als Stille. Ein harter Ausschluss liefe dort ins Leere.
Erkannt wird an Wortmarken in Title und DisplayTitle — audiodeskription, audio description, hörfilm, descriptive, freistehendes ad; für Kommentare kommentar, commentary, director. Die Liste steht an einer Stelle und ist geprüft.
Die Sprachcodes lügen — und wir fallen darauf herein
Vor allem anderen ein Fund, gemessen statt vermutet. So vergleicht die App heute (PlayerModel.swift:1399): die ersten zwei Zeichen.
deu ~ de → Treffer
ger ~ de → KEIN Treffer ← Jellyfin meldet sehr oft „ger"
de-DE ~ de → Treffer
gsw ~ de → KEIN Treffer ← Schweizerdeutsch, eigene Sprache
ger ist die ISO-639-2/B-Form von Deutsch, und ffmpeg schreibt sie in viele Dateien. Bei solchen Titeln greift die Spracheinstellung heute überhaupt nicht — lautlos, ohne dass irgendetwas darauf hindeutet.
Gebraucht wird also ein richtiger Vergleich: kleinschreiben, Region abschneiden (de-DE → de), und die zwanzig Sprachen, die zwei dreibuchstabige Formen haben, über eine Tabelle zusammenführen (ger/deu, fre/fra, dut/nld, cze/ces, gre/ell …).
gsw bleibt gsw. Schweizerdeutsch ist keine Schreibweise von Deutsch, sondern eine eigene Sprache ohne zweibuchstabigen Code. Es auf de abzubilden wäre bequem und falsch — wer Hochdeutsch will, bekäme Schweizerdeutsch untergeschoben. Stattdessen steht es in der Rangliste, und zwar da, wo du es hinstellst.
Wenn die Wunschsprache fehlt: eine Rangliste
Keine Zufallswahl, kein einzelner Ausweichwert, sondern eine geordnete Liste — „probier Deutsch, sonst Schweizerdeutsch, sonst Englisch, sonst Französisch".
Nur einmal, für alles. Sie ist keine dritte Einstellung je Mediathek oder Serie: dort steht der Wunsch, die Rangliste ist der Boden darunter und gilt überall gleich. Eine Reihenfolge je Mediathek zu pflegen wäre Arbeit für einen Fall, den es nicht gibt.
Sie greift nur, wenn der Wunsch bei diesem Titel fehlt. Hast du eine Datei mit nur Deutsch, ist nichts zu entscheiden; hast du eine mit zwölf Sprachen, entscheidet die Liste.
Die vollständige Reihenfolge, die immer zu einer Antwort kommt:
- gemerkte Signatur der Serie
- Wunschsprache (Serie → Mediathek → allgemein)
- die Rangliste, von oben nach unten
- die Spur mit
IsDefault - die erste Spur ohne Audiodeskription
- die erste Spur
Das Punktesystem bildet 1–3 ab; 4–6 sind der Boden darunter.
Gemerkt wird, was man tut
Wählt jemand während einer Folge eine andere Tonspur, wird sie als Signatur für diese Serie abgelegt. Ohne Nachfrage — die Frage „für diese Serie merken?" bei jeder Umstellung ist genau die Art Dialog, die man nach dem dritten Mal wegklickt.
Sichtbar wird es trotzdem: das Spurenblatt zeigt „Für diese Serie gemerkt" mit einem Weg, es wieder zu löschen. Eine automatische Handlung, die man nicht sehen kann, ist von einem Fehler nicht zu unterscheiden — dasselbe Prinzip wie bei der Qualitätsautomatik.
Bei Filmen wird nichts gemerkt: ein Film wird einmal gesehen.
Wo es steht
- Einstellungen → Sprachen: Tonsprache, die Rangliste (ziehbar, mit Hinzufügen und Entfernen), Untertitelsprache, und ein Schalter „Audiodeskription meiden" (an).
- Mediathek → Filter/Einstellungen: „Tonsprache für diese Mediathek" mit „wie allgemein" als Vorgabe.
- Serie → Detailseite: „Tonsprache für diese Serie", mit dem gemerkten Wert, falls einer da ist.
Abgelegt wird alles je Gerät in UserDefaults — wie alle anderen Einstellungen auch, und wie besprochen ohne Synchronisierung.
Plex
Für dieses Stück ist die Antwort einfach: es wird Jellyfin-only gebaut. Die Auswahl steckt im neutralen Teil und würde bei Plex arbeiten, wenn dort jemals dieselben Angaben ankommen — aber geprüft wird sie nur gegen Jellyfin.
PlexKit jetzt zu entfernen, wäre eine eigene Entscheidung, und keine kleine: gut fünftausend Zeilen, die vollständige Live-TV-Anbindung samt Programmführer und Aufnahmen, der PIN-Anmeldeweg, das Werkzeug FlixyProbe und rund achtzig Tests hängen daran. Das ist umkehrbar nur über die Versionsgeschichte.
Vorschlag: nicht jetzt. Erst soll Jellyfin das können, was du brauchst; erst wenn du Plex tatsächlich abgeschaltet hast, wird ausgebaut. Solange es steht, kostet es nichts ausser dem Verzicht auf neue Plex-Funktionen — und den hast du ohnehin ausgesprochen.
Was ich nicht bauen würde
- Keinen Proxy vor Jellyfin. Ausdrücklich ausgeschlossen, und ich teile das: eine Schicht, die Antworten umschreibt, bricht bei jedem Server-Update anders.
- Keinen eigenen Server. Monate für Anmeldung, Mediathek, Metadaten, Sitzungen — und die Sprachwahl ist davon der kleinste Teil.
- Keine Sprache je Genre oder Kategorie. Du hast es selbst verworfen, und zu Recht: die Frage „welche Sprache für Dokumentationen" hat niemand.
- Keine Zufallswahl als Ausweichfall. Zweimal dieselbe Folge soll zweimal dasselbe ergeben.
- Kein Dialog beim Umstellen. Siehe oben.
- Keine Heuristik über den Inhalt — etwa Tonspuren vergleichen, um Audiodeskription zu erkennen. Das ist Signalverarbeitung auf dem Gerät für einen Fall, den drei Wortmarken erschlagen.
Wie geprüft wird
AudioTrackChooserTests: Spurlisten von Hand, darunter der ZDF-Fall wörtlich — deutsche Spur mit Audiodeskription, englisch betitelte deutsche Spur — und die Erwartung, dass nach einmaligem Merken die richtige kommt.- Sprachcodes:
ger/deu/de-DEmüssen alle auf Deutsch passen,gswauf keines davon. Genau der Fall, der heute stillschweigend danebengeht. - Rangliste: Wunschsprache fehlt, zweite greift; keine aus der Liste vorhanden; nur Audiodeskription da; gar keine Sprachangabe; eine einzige Spur.
- Gleichstand: zweimal dasselbe Ergebnis.
- Gegen die Attrappe lässt sich eine Datei mit mehreren Spuren melden und die Auswahl im Player ansehen.
- An deinem Server: eine ZDF-Folge, einmal die richtige Spur wählen, nächste Folge öffnen.
Fertig ist es, wenn
- Eine ZDF-Folge nach einmaligem Umstellen dauerhaft ohne Audiodeskription läuft.
- Eine Serie auf Englisch und eine andere auf Deutsch startet, ohne dass zwischendurch etwas umgestellt wird.
- Fehlt die Wunschsprache, greift die Rangliste — nachvollziehbar und jedes Mal gleich.
- Eine Datei, die ihre Tonspur
gernennt, wird endlich als Deutsch erkannt. - Was die App automatisch gemerkt hat, ist im Spurenblatt zu sehen und zu löschen.