tvg-chno: Sendernummern in IPTV-Playlists, und was jeder Player damit macht
Kein Standard definiert dieses Attribut. Eine vermessene Playlist trägt 1.355 davon über 263 verschiedene Werte, und keine zwei der Anwendungen, die es lesen, sind sich einig.
tvg-chno="1" 107 entries
tvg-chno="2" 92
tvg-chno="3" 80
tvg-chno="4" 72
tvg-chno="5" 68
tvg-chno="#" 4
tvg-chno="22.1" 1
Das ist der Kopf des Sendernummern-Histogramms einer echten Playlist, mit zwei ihrer merkwürdigeren Werte darunter festgehalten. Die Datei hält 1.895 Einträge. 1.355 davon tragen das Attribut, und diese 1.355 Nummern decken 263 verschiedene Werte ab, im Mittel 5.15 Einträge je Wert. Die mit Abstand beliebteste Nummer der Datei wird von 107 nicht miteinander verwandten Sendern beansprucht.
Kein Standard definiert, was irgendetwas davon bedeutet. Es gibt keine Spezifikation für tvg-chno, kein Register und keinen Eigentümer. Die Referenzumsetzung dokumentiert es in einer Zeile einer README, und die Anwendungen, die es lesen, sind sich über die Schreibweise, den Typ, den Rückfall und darüber, ob der Wert überhaupt gezeigt wird, uneinig.
Woher das Attribut kommt, soweit es sich zeigen lässt
RFC 8216 ist eine informative Einreichung und kein Dokument des Standardisierungswegs. Sie definiert EXTM3U in Abschnitt 4.3.1.1, EXTINF in Abschnitt 4.3.2.1 und die Familie #EXT-X-, und die Zeichenkette tvg kommt darin nirgends vor. Ihre Attributlisten-Grammatik ist kommagetrennt mit einer festen Namensform, der die leerzeichengetrennte tvg--Konvention nicht folgt, und derselbe Abschnitt weist Clients an, Namen zu ignorieren, die sie nicht kennen. Diese Anweisung ist es, die die Konvention neben der RFC leben lässt: alles Folgende ist eine private Übereinkunft zwischen einem Programm und den Playlists, die man ihm gezeigt hat.
Das früheste Auftreten von tvg-chno, auf das ich zeigen kann, ist der Pull Request #92 gegen Kodis IPTV-Simple-Erweiterung, eröffnet am 2016-11-24 und zusammengeführt am 2016-12-17. Ich kann nicht belegen, dass er der erste ist, nur dass nichts Früheres öffentlich ist. Er fügt eine Markerkonstante hinzu, und die erklärte Motivation seines Autors war der Abgleich von Sendernummern mit einem Backend. Der Negativbefund drumherum ist stärker als der Commit: ein Eintrag im selben Verfolger vom 2015-07-20 sagt klar, dass das M3U-Format kein Tag für eine Sendernummer hat, und schlägt vor, die Nummer in den Sendernamen zu packen. Der Autor von #92 fand diesen Eintrag fünf Minuten nach dem Eröffnen seines Pull Requests, und der Betreuer schloss ihn später als durch seinen Patch behoben. Mitte 2015 kannte die eigene Gemeinschaft der Erweiterung kein solches Attribut.
Das Präfix tvg- ist fast vier Jahre älter als die Nummer. tvg-name, tvg-logo und group-title sitzen im ersten Projekt-Commit der Erweiterung vom 2013-01-17, tvg-id landet am selben Tag, und tvg-shift vier Tage danach. Wofür tvg steht, ist Folklore: alle lesen es als Kurzform von Fernsehprogrammführer, also TV-Programm, und die Geschwisterattribute, die die Programmadresse tragen, stützen diese Lesart, aber keine Erstquelle nennt die Auflösung, und die Berichte, die den Attributsatz auf ein früheres Windows-Player-Umfeld zurückführen, sind aus zweiter Hand. Der Negativbefund ist fester. XMLTV ist das, worauf diese Attribute zeigen, und nicht das, woher sie kamen.
Die Übernahme nach Kodi verläuft über Tvheadend, das es im März 2018 ausgibt, Emby, das es im Lauf von 2018 dokumentiert, und Jellyfin im Februar 2019. Die ärgerlichste Einzelheit der Sammlung ist, dass die Commit-Nachricht von Tvheadend sagt, sie füge ein Attribut tvg-chnum hinzu, während der Code, den sie mitbringt, tvg-chno= schreibt, und dass es auf dem Rückweg zuerst tvh-chnum liest und auf tvg-chno zurückfällt. Mindestens fünf Schreibweisen tragen in echten Dateien eine Sendernummer: tvg-chno, channel-number, ch-number, tvh-chnum, und eine channel-id, die manche Leser als Nummer behandeln.
1.176 der 1.355 Nummern werden mit einer anderen Zeile geteilt
Wir haben drei lokal gehaltene Beispiel-Playlists vermessen, insgesamt 2.209 Einträge. Zwei der drei nummerieren überhaupt nichts: null ihrer 314 Einträge tragen das Attribut. Alles hier ist die dritte Datei.
Die Werte sind schief verteilt. 179 der 263 verschiedenen Werte werden genau einmal verwendet, die Masse sitzt also in einem kurzen Kopf: 107 Einträge auf der Nummer 1, dann 92, 80, 72 und 68. Der Bereich reicht von 1 bis 4.999, die Obergrenze des Parsers von 99.999 hat also nie ausgelöst. 1.176 der 1.355 Zeilen, also 86.8 Prozent, teilen sich ihre Nummer mit mindestens einer anderen Zeile, und ein eindeutiger Schlüssel über der Datei würde 1.092 davon verwerfen. Zählt man nur die Werte, die unser Parser annimmt, liegt der Anteil geteilter Nummern bei 1.172 von 1.299, also 90.2 Prozent.
Warum nichts in einer dieser Dateien ein stabiler Schlüssel ist, wird in dem Artikel zum erweiterten M3U geklärt, und ich führe das hier nicht erneut aus. Was dieser Artikel nicht tut, ist die naheliegende Reparatur zu erledigen: wenn sich Nummern über eine Datei hinweg doppeln, beschränken Sie sie auf die Gruppe, in der sie sitzen, und jede Gruppe bekommt eine saubere Folge.
Das funktioniert nicht.
33 der 85 Gruppen, die überhaupt eine Nummer tragen, enthalten innerhalb der Gruppe mindestens eine doppelte Nummer. 69 dieser 85 enthalten einen Sender mit der Nummer 1. Eine Gruppe hält 7 Einträge, die alle die Nummer 1 tragen, und in der größten Gruppe der Datei decken 79 nummerierte Einträge 74 verschiedene Nummern ab. Das Gruppieren verringert die Anzahl der Kollisionen, ohne sie zu beseitigen, und eine Lösung, die für zwei Drittel Ihrer Gruppen wirkt, scheitert beim übrigen Drittel stillschweigend.
Die Ausfallquote zählt so viel wie die Doppelung. 596 der 1.895 Einträge, also 31.5 Prozent, enden ohne brauchbare Nummer: 540 trugen das Attribut nie, und 56 trugen etwas, das der Parser ablehnt. Im Abgleich mit dem Kennungsattribut tragen 398 Zeilen weder eine Nummer noch eine Kennung, also die Menge, die in der Datei nichts ansprechen kann. Eine Programmzeile ohne etwas, woran sie sich hängen kann, zeigt sich als ein Programm, das auf manchen Sendern falsch und auf anderen richtig ist, nie als Beschwerde über die Nummerierung.
Jede Dezimalzahl in der Datei ist argentinisch
25 Einträge nutzen die Nummerierung major.minor, über 24 verschiedene Werte von 22.1 bis 36.2, und nur 32.1 wiederholt sich. Jeder einzelne der 25 trägt das Land AR, eine Kennung, die auf .ar endet, und die Gruppe Argentina, die 26 Einträge hält und alle 26 nummeriert. Argentinien sendet ISDB-Tb. ATSC und ISDB-Tb nutzen beide die Form major.minor, und die Form ist alles, was sie hier teilen. Unser eigener Quellkommentar nennt diese Werte ATSC-artig, was für die Form stimmt und über die Herkunft falsch ist.
Diese 25 Zeilen sind der Grund, warum die Nummer eine Gleitkommazahl ist und keine Ganzzahl. Der Typ war billig. Die Migration nicht. Die Spalte lässt sich nicht nachfüllen, denn die Nummer wohnt in der Nutzlast der Quelle und wir bewahren die rohe Playlist nicht auf. Jede bestehende Installation hätte auf jeder Zeile einen leeren Wert getragen, und eine nach dieser Nummer sortierte Liste hätte eine ganze Bibliothek in den nicht nummerierten Schwanz gestellt. Die Migration löscht den Fingerabdruck der Momentaufnahme und die Materialisierungsmarke und zwingt die nächste Synchronisierung, den Katalog neu aufzubauen. Jede bestehende Installation zahlte eine vollständige Neumaterialisierung, um ein Abzeichen anzuzeigen.
Sechsundfünfzig Werte sind überhaupt keine Zahlen
56 der 1.355 Werte, über 53 verschiedene Schreibweisen, werden rundheraus abgelehnt. Sie fallen in vier Formen:
- Ein blankes
#auf 4 Einträgen, ein Platzhalter, den der Erzeuger nie gefüllt hat. - 49 Codes von Rundfunksystemen: eine Reihe
D011bisD081, eine FamilieBS101bisBS4K101, eine lange ReiheCS055bisCS363, und ein einzelnesJCOM307. Das ist ein echtes nationales Nummerierungsschema, und das Attribut hat keinen Platz dafür. CH 106undCH 108, dieselbe Nummer mit einem Präfix und einem Leerzeichen.- Ein Wert, der ein Plattformname in japanischer Schrift ist, mit
527am Ende.
Eine Ablehnung kostet die Zeile ihre Nummer und nie die Zeile, alle 56 behalten also ihren Platz und sortieren sich in den nicht nummerierten Schwanz.
Mehrere Ablehnungen sind Regeln ohne Zeugen: ein führendes Vorzeichen stellt +5 und -5 außerhalb der angenommenen Stile, und null wird abgelehnt, weil eine fehlende Nummer nicht Sender null ist. Keine dieser Formen kommt in 1.355 Werten auch nur einmal vor. Führende Nullen sind der nachsichtige Fall: 007 wird zu 7 ausgewertet.
Diese Aufteilung braucht einen Vorbehalt, denn das Messskript bildet unseren Parser in Python nach und float() ist lockerer als der Stilsatz, den wir übergeben. Ich habe den Bestand auf jede Form geprüft, in der die beiden uneins sind, ein führendes Plus oder Minus, Exponenten, Unterstriche, umgebende Leerzeichen und führende Nullen, und von jedem null gefunden. Die Aufteilung 1.299 gegen 56 ist die des ausgelieferten Parsers.
Keine zwei dieser Leser sind sich einig
Nichts davon stammt aus einer Spezifikation, denn es gibt keine. Jede Zelle ist aus dem Quelltext des jeweiligen Projekts oder seiner eigenen Dokumentation gelesen.
| Verbraucher | Liest es | Nimmt außerdem an | Dezimal | Zwei Zeilen, eine Nummer | Attribut fehlt |
|---|---|---|---|---|---|
| Kodi IPTV Simple | Ja, seit 2016-12 | ch-number, Werte ohne Anführungszeichen und jede Schreibweise mit Präfix, weil der Abgleich eine Teilzeichenkettensuche ist | Am Punkt in eine Haupt- und eine Unterkanalnummer geteilt | Keine Erkennung; beide überleben, der Kern sortiert nach Nummer und bricht Gleichstände über den Namen | Der laufende Zähler macht beim vorherigen Sender plus eins weiter |
| Jellyfin | Ja, seit 2019-02 | Eine numerische tvg-id; eine numerische channel-id, aber nur wenn tvg-id vorhanden und nicht numerisch ist; eine führende Zahl im Namen; der Dateiname der Adresse | Als Gleitkommazahl ausgewertet, die ursprüngliche Zeichenkette bleibt erhalten | Nichts im Parser | Fällt durch die Kette; -1 und 0 als ungültig abgelehnt |
| Emby | Ja, im Lauf von 2018 | Nichts dokumentiert | Nicht dokumentiert | Nicht dokumentiert | Dokumentiert als automatische Erkennung aus den verfügbaren Tags |
| xTeVe | Nein, gespeichert und ignoriert | Nichts; die Nummerierung ist intern | Nur aus seiner eigenen Oberfläche | Kann nicht passieren; der Zuteiler nimmt die erste freie Nummer | Wie vorhanden: erste freie Nummer ab einem einstellbaren Beginn, standardmäßig 1000 |
| Threadfin | Ja | Nur tvg-chno | Als Zeichenkette gespeichert, zum Sortieren als Gleitkommazahl ausgewertet | Wörtlich kopiert, Kollisionen bleiben also bestehen | Erste freie Nummer ab der Startnummer der Gruppe |
| Channels DVR | channel-number, laut seiner Dokumentation | channel-id, das seine Dokumentation zum Pflichtfeld macht | Nicht dokumentiert | Über Quellen hinweg zusammengeführt, der bevorzugte Sender gewinnt | Nicht dokumentiert |
| Plex | Überhaupt keine M3U-Aufnahme | Nicht zutreffend | Was auch immer der vorgeschaltete Proxy sendet | Was auch immer der Proxy sendet | Die Nummern kommen aus einer Tuner-Senderliste |
| VLC | Nein | Liest tvg-logo, tvg-name, tvg-language, tvg-id, group-title und verwirft den Rest | Nicht zutreffend | Nicht zutreffend | Kein Begriff einer Sendernummer, nur die Position in der Playlist |
Kodis Leser ist der freizügigste des Feldes und der in seiner Wirkung überraschendste. Jeder Eintrag wird aus einem laufenden Zähler angesetzt, der sich auf die Nummer zurücksetzt, die ein Sender beansprucht, ein einziges tvg-chno="500" zwei Drittel weit unten in einer Datei nummeriert also jeden späteren nicht nummerierten Sender ab 501 neu. Ein Attribut auf einer Zeile bewegt hunderte andere. Und nach all dem Auswerten steht die Einstellung im Kern von Kodi, Backend-Sendernummern zu verwenden, standardmäßig auf aus: die Gruppe aller Sender nummeriert sich selbst von 1 bis n, andere Gruppen erben das, und die Nummer der Playlist bleibt am Sender, ohne gezeigt zu werden.
Jellyfins ist der strengste: sein Regex verlangt einen Wert in doppelten Anführungszeichen, tvg-chno=101 ohne Anführungszeichen ist für ihn also unsichtbar, während Kodi es bereitwillig liest, und unser eigener Leser hat dieselbe Einschränkung. Seine Rückfallkette endet beim Dateinamen der Stream-Adresse, dem Punkt, an dem eine Sendernummer aufhört, Daten zu sein, und anfängt, eine Vermutung über einen Pfad zu sein.
xTeVe ist die interessante Verweigerung. Es wertet das Attribut in allgemeine Metadaten aus und nutzt es nie, vergibt seine eigenen Nummern ab dem ersten freien Platz bei 1000 oder darüber, und ein Wunsch, tvg-chno zu beachten, wurde als nicht geplant geschlossen. Das ist der einzige Entwurf hier, in dem zwei Zeilen, die eine Nummer beanspruchen, nicht kollidieren können, denn die Meinung der Playlist wird nie eingeholt, und der Preis ist, dass eine sorgfältig nummerierte Quelle umnummeriert ankommt. Threadfin, seine Abspaltung, ging den anderen Weg und kopiert den Wert wörtlich, Kollisionen kommen also unversehrt durch; sein Entdoppeln hasht die Adresse, die tvg-id und die Quellenkennung, nie die Nummer.
Plex ist die eigenartige Zeile, denn es hat keine eigene M3U-Aufnahme und nichts darin wertet das Attribut aus; seine Seite zu von der Gemeinschaft unterstützten Tunern verlangt ein Windows-BDA- oder Linux-DVB-Gerät. Der übliche Weg von einer Playlist aus ist ein Proxy nach Art von HDHomeRun, wo die Nummer als GuideNumber in lineup.json ankommt, und welche Nummer das ist, hängt vom Proxy ab: xTeVe setzt eine eigene ein, Threadfin reicht die Zeichenkette geradewegs durch.
Sechs Zeilen ergeben vier brauchbare Nummern
Hier ist ein Bruchstück, gebaut, um jeden Pfad auf einmal zu treffen. Jeder Host ist eine reservierte Beispieldomain und jeder Name ist erfunden.
#EXTINF:-1 tvg-id="one.example" tvg-chno="1",Example One
https://example.com/live/one.m3u8
#EXTINF:-1 tvg-id="two.example" tvg-chno="1",Example Two
https://example.com/live/two.m3u8
#EXTINF:-1 tvg-chno=101,Example Three
https://example.com/live/three.m3u8
#EXTINF:-1 tvg-chno="22.1",Example Four
https://example.com/live/four.m3u8
#EXTINF:-1 tvg-chno="BS4K101",Example Five
https://example.com/live/five.m3u8
#EXTINF:-1 tvg-chno="007",Example Six
https://example.com/live/six.m3u8
Eins und Zwei beanspruchen beide die Nummer 1, was der Normalfall dieser Datei ist und nicht ihr Sonderfall. Unser Vergleicher behält beide, geordnet über einen Namensvergleich in natürlicher Ordnung und danach einen ordinalen Vergleich ihrer Kennungen, das Paar ist also vorhersagbar. Kodi behält ebenfalls beide. xTeVe würde ihnen 1000 und 1001 geben und das Attribut nie lesen.
Drei steht ohne Anführungszeichen da, Kodi liest also 101, während wir überhaupt nichts lesen, wie es auch Jellyfin täte: die Zeile landet auf unserer Seite im nicht nummerierten Schwanz und bei Kodi auf Sender 101.
Vier ist der Unterkanalfall. Wir behalten 22.1 als Dezimalzahl, Kodi teilt es in Hauptnummer 22 mit Unterkanal 1, Jellyfin wertet eine Gleitkommazahl aus und behält die ursprüngliche Zeichenkette zur Anzeige, und jeder Verbraucher mit einer Ganzzahlspalte zeigt 22.
Fünf wird von unserem Zahlenparser abgelehnt und behält seine Zeile, es gesellt sich also im Schwanz zu Drei. Kodi kommt schlechter weg als wir: sein Leser übergibt den Wert an atoi, was für eine Zeichenkette, deren Ziffern nicht vorne stehen, 0 zurückgibt, und nichts sichert den Setter ab, die Zeile wird also Sender 0 und der laufende Zähler wird mit ihr auf 0 zurückgesetzt. Der nächste nicht nummerierte Sender wird 1. Ein Unrat-Wert richtet dort mehr Schaden an als ein fehlender.
Sechs ist der Fall mit der führenden Null: 007 normalisiert sich für uns zu 7, und Jellyfin wertet dieselbe 7 aus und zeigt dabei weiter 007 an.
Nach der Nummer der Quelle sortiert liest sich unsere Liste als Example One, Example Two, Example Six bei 7, Example Four bei 22.1, dann Example Five und Example Three in Namensreihenfolge, denn eine fehlende Nummer sortiert hinter jede vorhandene und nicht als null.
Eine Kollision löst sich je nachdem, was die Zuschauerin oder der Zuschauer gerade tut, unterschiedlich auf. Uns hat es drei Mechanismen gekostet statt einem. Beim Sortieren wird die Kollision vom Namens-Gleichstandsbrecher aufgefangen. Bei der Eingabe über den Ziffernblock geht das Tippen von 1 die Treffer durch: jede Zeile mit dieser Nummer wird gesammelt und wiederholte Druckvorgänge gehen sie durch, mit Umbruch am Ende, denn die erste von 107 für immer festzuhalten würde die anderen 106 unerreichbar machen. Beim Zusammenführen, wo mehrere Quellen zu einem logischen Sender beitragen, gewinnt die Nummer des namengebenden Mitglieds, und andernfalls das erste Mitglied in Prioritätsreihenfolge, das eine hat. Dieselben Mitglieder sind die Warteschlange, in die ein stehengebliebener Stream wechselt, was einen eigenen Artikel hat.
Der Weg über den Ziffernblock hat eine Lücke, die mir nicht gefällt. Er sammelt nur Zifferntasten, mit einem Fenster von 1.2 Sekunden dazwischen und einem Zurücksetzen nach fünf Ziffern, und er wertet ohne aktivierte Zahlenstile aus, es gibt also keine Möglichkeit, 22.1 zu tippen. Ein Unterkanal ist über die Suche erreichbar, wo die Anfrage durch den Parser geht, der einen Dezimalpunkt annimmt, und über die Fernbedienung unerreichbar. Der ehrliche Grund, warum das nicht behoben ist, lautet, dass 25 Zeilen in unserem Bestand es brauchen.
Eine Nummer, die Sie vergeben, ist nicht die Nummer, die die Datei geschickt hat
Die Nummer der Quelle wird nie überschrieben. Eine Umsortiergeste schreibt einen eigenen gebrochenen Schlüssel, und die beiden leben nebeneinander.
Der Mechanismus wird von einer Beschränkung bestimmt, die mit der Ordnung nichts zu tun hat. Unsere Stapelgrenze bei der Synchronisierung liegt bei 500 Änderungen und ein einzelner abgelehnter Datensatz lässt den ganzen Stapel scheitern und nimmt jede unbeteiligte Änderung mit, die mitreist, eine Gruppe bei jedem Ablegen neu zu nummerieren war also nie tragfähig. Stattdessen bekommt jeder Sender einen impliziten Schlüssel aus seiner Position in der Rückfallordnung, ein platzierter Sender nutzt seinen synchronisierten Schlüssel, und ein Ablegen zwischen zwei Zeilen nimmt die Mitte, was genau eine Zeile schreibt. Implizite Schlüssel liegen eins auseinander, jedes Ablegen in dieselbe Lücke halbiert sie also: gegen eine Mindestlücke von 1e-9 landet das dreißigste aufeinanderfolgende Ablegen in einen Platz noch, und das einunddreißigste gleicht die Gruppe auf gleichmäßig verteilte Schlüssel neu aus. Dieser Neuausgleich ist der einzige Weg hier, der tausende Zeilen schreibt, und er wird mit seiner Größe protokolliert, statt still zu laufen. Drei Kommentare in unserem eigenen Quelltext sagen fünfzig. Wir haben das aus dem Bauch heraus falsch gemacht, der erste Entwurf dieses Artikels hat es wiederholt, und die Zahl wurde erst dreißig, als jemand die Rechnung gemacht hat.
Das Abzeichen zeigt die Position der Zeile statt dieses Schlüssels, denn implizite Schlüssel verschieben sich, sobald die Quelle Sender hinzufügt oder entfernt, und eine Nummer, die sich nach einer Synchronisierung von selbst bewegt, ist schlimmer als keine. Eine frühere Fassung dieser Ordnung wohnte im Ansichtsmodell, wo eine gespeicherte Reihenfolge für Kategoriegruppen der Quelle galt und stillschweigend nicht für Alle Sender, Favoriten oder benutzerdefinierte Gruppen.
Die Windows- und die Xbox-App werten all das auf Ihrem Gerät aus, aus der Playlist, auf die Sie sie richten, und Sie können ein kostenloses Konto anlegen, um beides auszuprobieren. Nichts über Ihre Sendernummern erreicht uns, denn die Datei wird nie hochgeladen und das Auswerten passiert lokal.
Wenn Sie Playlists ausgeben, schreiben Sie tvg-chno auf jede Zeile und halten Sie es innerhalb der Datei eindeutig, denn die Verbraucher, die es beachten, teilen keine Regel dafür, was zu tun ist, wenn Sie das nicht tun, und einer von ihnen nummeriert alles unterhalb Ihres ersten nummerierten Senders neu. Wenn Sie Playlists lesen, zählen Sie die verschiedenen Werte, bevor Sie irgendetwas auf dem Attribut aufbauen. In unserem Bestand ist diese Zahl der Unterschied zwischen 1.355 Nummern und 263.
Was dieser Artikel gemessen hat46 Behauptungen, jeweils mit den Beweisen dahinter
| Anspruch | Beweise | Gezählt |
|---|---|---|
| RFC 8216 ist eine informative unabhängige Einreichung. Sie definiert EXTM3U in Abschnitt 4.3.1.1, EXTINF in Abschnitt 4.3.2.1 und die Tag-Familie EXT-X-, und sie definiert kein tvg--Attribut und kein Attribut für eine Sendernummer; die Zeichenkette tvg kommt darin nicht vor. Ihre Attributlisten-Grammatik in Abschnitt 4.2 ist kommagetrennt mit einer festen Form für Attributnamen, der die leerzeichengetrennte tvg--Konvention nicht folgt. Abschnitt 4.2 verlangt außerdem, dass Clients unbekannte Tags und unbekannte Attributnamen ignorieren, und deshalb überlebt die Konvention daneben.RFC 8216, Informational, sections 4.2, 4.3.1.1 and 4.3.2.1. Full text re-read 2026-08-23; no occurrence of the string tvg. | Spezifikation | Nicht zutreffend |
| Das früheste nachweisbare öffentliche Auftreten von tvg-chno ist PR #92 gegen Kodis PVR IPTV Simple Client, eröffnet am 2016-11-24 und zusammengeführt am 2016-12-17, Commit 28e607bb7d192c54759bae8e2bb1a5d51297e002 von sangwoo shin, Nachricht add channel number tag, der die Markerkonstante tvg-chno= in den Playlist-Lader einführt.https://github.com/kodi-pvr/pvr.iptvsimple/pull/92 and commit 28e607bb7d192c54759bae8e2bb1a5d51297e002. Constant re-verified 2026-08-23 against branch Piers: TVG_INFO_CHNO_MARKER = tvg-chno= and CHANNEL_NUMBER_MARKER = ch-number= in src/iptvsimple/PlaylistLoader.h. | Spezifikation | Nicht zutreffend |
| Im Juli 2015 hielt der Fehlerverfolger derselben Erweiterung fest, dass das M3U-Format kein Tag für eine Sendernummer habe, und schlug vor, sie stattdessen im Sendernamen zu kodieren. Der Autor von PR #92 nannte diesen Eintrag nicht als seine Motivation: sein PR-Text gibt den Abgleich mit einem Backend als Grund an, und er bemerkte den Eintrag fünf Minuten nach dem Eröffnen des PR. Der Betreuer schloss den Eintrag am 2016-12-17 als durch #92 behoben.https://github.com/kodi-pvr/pvr.iptvsimple/issues/31, opened 2015-07-20, closed 2016-12-17 as fixed by #92. PR #92 body by excorp, 2016-11-24T04:19Z: Added channel number tag to m3u file. It is useful for syncing channel number with backend in kodi. His follow-up comment: I found something similar in issue #31. | Spezifikation | Nicht zutreffend |
| tvg-name, tvg-logo und group-title stehen im ersten Projekt-Commit der Erweiterung, 095e2fd vom 2013-01-17 von Anton Fedchin. tvg-id landet am selben Tag in 46c58ef, und tvg-shift am 2013-01-21 in 68a61c4. Das Wiki dieses Projekts dokumentiert sechs Attribute, tvg-id, tvg-name, tvg-logo, tvg-shift, group-name und radio, ohne ihre Herkunft zu nennen.afedchin/xbmc-addon-iptvsimple, commit 095e2fd (2013-01-17) at src/iptvsimple/PVRDemoData.cpp:31-33, commit 46c58ef (2013-01-17) at src/iptvsimple/PVRIptvData.cpp:35, commit 68a61c4 (2013-01-21), and https://github.com/afedchin/xbmc-addon-iptvsimple/wiki/IPTV-Simple-Home | Spezifikation | Nicht zutreffend |
| Keine Erstquelle sagt, wofür tvg steht. Die Lesart als Fernsehprogrammführer ist allgemein üblich und die Geschwisterattribute x-tvg-url und url-tvg tragen die XMLTV-Adresse, was sie stützt, aber die Auflösung ist unbelegt.Absence of any expansion in the add-on wiki, the add-on README and the original repository | Spezifikation | Nicht zutreffend |
| Tvheadend schreibt tvg-chno= in seine eigene M3U-Ausgabe und gibt es über channel_get_number_as_str in der Form major.minor aus, was es zu einem Erstanbieter dezimaler Sendernummern macht. Der Commit, der es hinzufügte, 35c83be2 vom 2018-03-20 von Jaroslav Kysela, trägt eine Nachricht, die add tvg-chnum attribute lautet, während das ausgegebene Token tvg-chno ist.tvheadend commit 35c83be2fc8cdded (2018-03-20), message: m3u playlist: add tvg-chnum attribute with the channel number, fixes #5011. The emitter sits at src/webui/webui.c:601 on master today, which is not the line number in that commit. | Spezifikation | Nicht zutreffend |
| Der eigene Leser für automatische IPTV-Netze von Tvheadend nimmt zuerst tvh-chnum und fällt auf tvg-chno zurück, das Projekt liest also eine Schreibweise, die es nicht schreibt.tvheadend/tvheadend, src/input/mpegts/iptv/iptv_auto.c:106-107 | Spezifikation | Nicht zutreffend |
| Mindestens fünf Schreibweisen tragen in freier Wildbahn eine Sendernummer: tvg-chno, channel-number, ch-number, tvh-chnum und eine numerische channel-id.tvg-chno and ch-number at kodi-pvr/pvr.iptvsimple src/iptvsimple/PlaylistLoader.h:33-34; channel-number in the Channels DVR custom-channels documentation and in TVIP set-top firmware 4.1.12+ at https://wiki.tvip.tv/en/m3u, whose example is unquoted (channel-number=10); tvh-chnum at tvheadend/tvheadend src/input/mpegts/iptv/iptv_auto.c:106-107; numeric channel-id at jellyfin/jellyfin src/Jellyfin.LiveTv/TunerHosts/M3uParser.cs:191-195 | Spezifikation | Nicht zutreffend |
| Über drei lokal gehaltene Beispiel-Playlists mit 2.209 Einträgen nummeriert nur eine Datei überhaupt etwas: 1.355 ihrer 1.895 Einträge tragen tvg-chno, also 71.5 Prozent. Die anderen beiden Dateien tragen das Attribut auf null ihrer 314 Einträge. | n = 2209 | 23.08.2026 |
| Die 1.355 Werte decken 263 verschiedene Nummern ab, im Mittel 5.15 Einträge je Wert. 179 Werte werden genau einmal verwendet. Die häufigsten fünf sind 1 auf 107 Einträgen, 2 auf 92, 3 auf 80, 4 auf 72 und 5 auf 68. Der Zahlenbereich reicht von 1 bis 4.999. | n = 1355 | 23.08.2026 |
| 1.176 der 1.355 Einträge teilen sich ihre Nummer mit mindestens einer anderen Zeile, also 86.8 Prozent, und ein eindeutiger Schlüssel würde 1.092 davon verwerfen. Zählt man nur Werte, die der Parser annimmt, teilen sich 1.172 von 1.299 ihre Nummer, also 90.2 Prozent. | n = 1355 | 23.08.2026 |
| 33 der 85 Gruppen, die überhaupt eine Nummer tragen, enthalten innerhalb der Gruppe mindestens eine doppelte Nummer, 69 von 85 enthalten einen Sender mit der Nummer 1, und eine Gruppe hält 7 Einträge, die alle die Nummer 1 tragen. In der größten Gruppe decken 79 nummerierte Einträge 74 verschiedene Nummern ab. | n = 1895 | 23.08.2026 |
| 596 der 1.895 Einträge enden ohne brauchbare Nummer, also 31.5 Prozent: 540 trugen das Attribut nie und 56 trugen einen Wert, den der Parser ablehnt. | n = 1895 | 23.08.2026 |
| In derselben Datei tragen 1.250 Einträge sowohl tvg-chno als auch tvg-id, 105 tragen eine Nummer und keine Kennung, 142 eine Kennung und keine Nummer, und 398 tragen keines von beidem. | n = 1895 | 23.08.2026 |
| 25 Einträge über 24 verschiedene Werte nutzen die Unterkanal-Nummerierung in der Form major.minor, von 22.1 bis 36.2, und 32.1 ist die einzige Dezimalzahl, die sich wiederholt, auf 2 Einträgen. Jeder einzelne der 25 trägt tvg-country=AR, eine tvg-id, die auf .ar endet, und group-title Argentina. Diese Gruppe hält insgesamt 26 Einträge und nummeriert alle 26. Argentinien sendet ISDB-Tb und nicht ATSC; die beiden Systeme teilen sich die Form major.minor und nicht die Geografie. | n = 1895 | 23.08.2026 |
| Die Nummer ist als Gleitkommazahl typisiert und in einer SQLite-REAL-Spalte gespeichert, und beide Stellen nennen die Unterkanal-Nummerierung als Grund. | n = 1 | 23.08.2026 |
| Die Spalte lässt sich nicht an Ort und Stelle nachfüllen, denn die Nummer wohnt in der Nutzlast der Quelle und die rohe Playlist wird nicht aufbewahrt, die Migration löscht deshalb den Fingerabdruck der Momentaufnahme und die Materialisierungsmarke, um die nächste Synchronisierung zum Neuaufbau des Katalogs zu zwingen, statt sie abkürzen zu lassen. | n = 1 | 23.08.2026 |
| Der Parser nimmt einen Dezimalpunkt, führende und nachlaufende Leerzeichen und nur die invariante Kultur an. Ein führendes Vorzeichen, ein Exponent, ein Tausendertrennzeichen und ein Dezimalkomma liegen außerhalb des Stilsatzes. Nicht endliche, nicht positive und Werte über 99.999 werden abgelehnt. Führende Nullen werden angenommen und im Wert normalisiert, aus 007 wird also 7. Eine Ablehnung liefert nichts zurück und kostet die Zeile ihre Nummer, nie die Zeile. | n = 1 | 23.08.2026 |
| 22.1 wird ausgewertet und 22,1 nicht, auch unter einer französischen Kultur, und das Abzeichen stellt 5 dar statt 5.0. | n = 2 | 23.08.2026 |
| 56 Werte über 53 verschiedene Schreibweisen werden abgelehnt: 4 sind ein literales #, 49 sind Codes von Rundfunksystemen aus den Familien BS, CS, D und JCOM wie D011, BS4K101, CS363 und JCOM307, 2 lauten CH 106 und CH 108, und 1 ist ein Plattformname auf Japanisch, der auf 527 endet. | n = 1355 | 23.08.2026 |
| Das Messskript bildet den Parser mit Pythons float() nach, was lockerer ist als der Stilsatz in C#. Der Bestand wurde auf jede Form geprüft, in der die beiden uneins sind, ein führendes Plus oder Minus, Exponentenschreibweise, Unterstriche, umgebende Leerzeichen und führende Nullen, mit null Vorkommen von jedem, die Aufteilung in 1.299 angenommene gegen 56 abgelehnte ist also die Aufteilung des ausgelieferten Parsers. | n = 1355 | 23.08.2026 |
| Auf der Spalte mit der Sendernummer gibt es keinen Index, weder eindeutig noch sonst, und drei getrennte Quelldateien halten an Ort und Stelle fest, dass nichts auf diesem Wert aufsetzen darf. | n = 3 | 23.08.2026 |
| Ein Parser bedient beide Formate auf der Leitung, das M3U-Attribut und das Feld num des Portalprotokolls, und das Portalfeld wird über einen flexiblen Konverter gelesen, weil Panels es austauschbar als Zeichenkette oder als Zahl ausgeben. | n = 2 | 23.08.2026 |
| Das Sortieren nach der Nummer der Quelle stellt nicht nummerierte Zeilen hinter nummerierte, statt fehlend als null zu behandeln, und gleiche Nummern fallen auf einen Namensvergleich in natürlicher Ordnung und danach auf einen ordinalen Vergleich der Kennungen zurück. | n = 1 | 23.08.2026 |
| Das Abzeichen zeigt die Nummer der Quelle nur, solange die Liste nach dieser Nummer sortiert ist, und sonst die 1-basierte Position der Zeile; auch eine nicht nummerierte Zeile fällt auf die Position zurück, denn ein leeres Abzeichen in einer nummerierten Spalte liest sich als kaputte Zeile. | n = 1 | 23.08.2026 |
| Die Eingabe über den Ziffernblock sammelt jede Zeile, die zur getippten Nummer passt, und geht sie bei wiederholtem Druck durch, mit Umbruch am Ende, statt die erste Übereinstimmung festzuhalten. | n = 1 | 23.08.2026 |
| Der Puffer für mehrstellige Eingaben sammelt nur Zifferntasten und wertet ohne aktivierte Zahlenstile aus, eine Unterkanalnummer ist vom Ziffernblock aus also nicht erreichbar; derselbe Wert, in die Suche getippt, passt sehr wohl, denn die Suche schickt die Anfrage durch den Zahlenparser, der einen Dezimalpunkt annimmt. | n = 1 | 23.08.2026 |
| Wenn mehrere Quellen zu einem logischen Sender beitragen, gewinnt die Nummer des namengebenden Mitglieds, und wenn es keine hat, gewinnt das erste Mitglied im Bündel, das eine anbietet; die Reihenfolge im Bündel ist bereits die Prioritätsreihenfolge. | n = 1 | 23.08.2026 |
| Eine von der Nutzerin oder dem Nutzer vergebene Reihenfolge ist ein eigener gebrochener Schlüssel und nie ein Überschreiben der Nummer der Quelle. Ein Ablegen schreibt genau eine Synchronisierungszeile, denn die Stapelgrenze der Synchronisierung liegt bei 500 Änderungen und ein abgelehnter Datensatz lässt den ganzen Stapel scheitern. Implizite Schlüssel liegen eins auseinander und jedes Ablegen in dieselbe Lücke halbiert sie, bei einer Mindestlücke von 1e-9 landet das dreißigste aufeinanderfolgende Ablegen in einen Platz also noch, und das einunddreißigste gleicht neu aus; der Neuausgleich ist der einzige Weg, der mehr als eine Zeile schreibt. | n = 1 | 23.08.2026 |
| Bevor die Ordnung in eine reine Funktion gezogen wurde, galt eine synchronisierte Reihenfolge für Kategoriegruppen der Quelle und galt stillschweigend nicht für Alle Sender, Favoriten oder benutzerdefinierte Gruppen. | n = 1 | 23.08.2026 |
| Kodis Markerleser sucht den Marker irgendwo in der Zeile und nimmt einen Wert in Anführungszeichen oder durch Leerzeichen begrenzt an, ein tvg-chno=101 ohne Anführungszeichen wird also gelesen und eine Schreibweise mit Präfix wie x-tvg-chno= passt ebenfalls. Der Wert wird am Punkt in eine Hauptnummer und eine Unterkanalnummer geteilt.kodi-pvr/pvr.iptvsimple branch Piers, head 78a023cb31, src/iptvsimple/PlaylistLoader.cpp:336, :375-390 and ReadMarkerValue at :622-664 | Spezifikation | Nicht zutreffend |
| Kodi setzt jeden neuen Eintrag aus einem laufenden Zähler an, der bei der Einstellung für die Startnummer beginnt, setzt den Zähler auf die Nummer, die ein Sender beansprucht, und erhöht ihn nach jedem Hinzufügen, ein einziger nummerierter Sender nummeriert also jeden späteren nicht nummerierten Sender ab dieser Stelle neu.kodi-pvr/pvr.iptvsimple, src/iptvsimple/PlaylistLoader.cpp:174 and src/iptvsimple/Channels.cpp:37, :100, :121 | Spezifikation | Nicht zutreffend |
| Kodi wandelt den Markerwert mit atoi um, was für eine Zeichenkette, deren Ziffern nicht vorne stehen, 0 zurückgibt, etwa BS4K101. Nichts sichert den Setter ab, die Zeile bekommt also die Sendernummer 0 und der laufende Zähler wird auf 0 zurückgesetzt, was den nächsten nicht nummerierten Sender auf 1 setzt. Ein Unrat-Wert richtet dort mehr Schaden an als ein fehlender.kodi-pvr/pvr.iptvsimple, std::atoi at src/iptvsimple/PlaylistLoader.cpp:388, unguarded SetChannelNumber(int) at src/iptvsimple/Channel.h:64, counter assignment at src/iptvsimple/Channels.cpp:100 and increment at :121 | Spezifikation | Nicht zutreffend |
| Die Einstellung pvrmanager.usebackendchannelnumbers im Kern von Kodi steht standardmäßig auf falsch. Mit abgeschalteten Backend-Nummern nummeriert die Gruppe aller Sender ihre Mitglieder 1..n neu und andere Gruppen erben diese Nummerierung, denn der 1..n-Weg läuft nur für den Eigentümer der Sender oder wenn startgroupchannelnumbersfromone gesetzt ist, und auch diese Einstellung steht standardmäßig auf falsch. Die Sendernummer des Clients bleibt am Mitglied erhalten und wird schlicht nicht angezeigt.xbmc/xbmc at 3f152e7c12, system/settings/settings.xml:1832 for usebackendchannelnumbers with <default>false</default> and :1841 for startgroupchannelnumbersfromone with <default>false</default>; xbmc/pvr/channels/PVRChannelGroup.cpp:915-919 for the 1..n condition and :927 for SetClientChannelNumber | Spezifikation | Nicht zutreffend |
| Die Erweiterung liefert eine Einstellung mit, die tvg-chno rundheraus ignoriert und Sender nur nach ihrer Reihenfolge in der Datei nummeriert.kodi-pvr/pvr.iptvsimple README: Only number by channel order in M3U, which ignores any tvg-chno tags | Spezifikation | Nicht zutreffend |
| Die Referenzumsetzung dokumentiert das Attribut in einer Zeile ihrer README, das Attribut ist also von keinem Standard dokumentiert und nicht schlechthin undokumentiert.kodi-pvr/pvr.iptvsimple README line 515: tvg-chno: The number to be used for this channel. | Spezifikation | Nicht zutreffend |
| Jellyfins Attribut-Regex verlangt einen nicht leeren Wert in doppelten Anführungszeichen, eine Nummer ohne Anführungszeichen ist für ihn also unsichtbar. Seine Sendernummer fällt über tvg-chno, dann eine numerische tvg-id, dann, nur wenn tvg-id vorhanden und nicht numerisch ist, eine numerische channel-id, dann eine führende Zahl im Anzeigenamen und schließlich den Dateinamen der Adresse zurück. -1 und 0 werden als ungültig abgelehnt.jellyfin/jellyfin, src/Jellyfin.LiveTv/TunerHosts/M3uParser.cs:36 for the GeneratedRegex, :170-255 for GetChannelNumber with the channel-id branch nested as an else-if inside the tvg-id branch at :185-195, :267-277 for IsValidChannelNumber with -1 and 0 rejected at :270-271. Re-verified against master 2026-08-23. | Spezifikation | Nicht zutreffend |
| Jellyfin bekam die Unterstützung für tvg-chno in PR #863, erstellt am 2019-02-10 und zusammengeführt am 2019-02-14.https://github.com/jellyfin/jellyfin/pull/863 | Spezifikation | Nicht zutreffend |
| Emby dokumentiert tvg-chno als Sendernummer und hält fest, dass fehlende Werte automatisch aus den jeweils verfügbaren Tags erkannt werden. Das Verhalten darüber hinaus ist nicht dokumentiert und der ausgelieferte Parser ist nicht quelloffen. Als Zeitpunkt der Unterstützung gilt 2018; die einzige dafür gefundene Quelle ist der Text des Jellyfin-PR, der sagt, Emby habe dies im Juli 2018 angekündigt.EmbySupport/Emby.Docs/M3U-Tuners.md:41, last updated 2026-07-18, published at https://emby.media/support/articles/M3U-Tuners.html; date attribution from the body of https://github.com/jellyfin/jellyfin/pull/863 | Spezifikation | Nicht zutreffend |
| Die öffentliche Quellmomentaufnahme von Emby ist auf 3.5.3 vom 2018-09-20 eingefroren und ihr M3U-Parser enthält überhaupt kein tvg-chno. Diese Datei ist der unmittelbare Vorfahr von Jellyfins Parser, und deshalb tragen beide dieselben Rückfälle über das Namenspräfix und den Dateinamen der Adresse.MediaBrowser/Emby at 1d7c2ab4bf, Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs:159-252, last touched 2017-08-20 | Spezifikation | Nicht zutreffend |
| xTeVe speichert jedes Playlist-Attribut als allgemeine Metadaten und hat auf der Struktur, in die es eine Playlist-Zeile auswertet, kein Feld für eine Sendernummer. Es vergibt seine eigenen Nummern und nimmt die erste freie Nummer ab einem einstellbaren ersten Sender, der im Code und nicht in der Dokumentation auf 1000 steht, zwei Zeilen, die eine Nummer beanspruchen, können also bauartbedingt nicht kollidieren. Ein Wunsch, tvg-chno zu beachten, wurde als nicht geplant geschlossen.xteve-project/xTeVe at 0e999b85b9, src/internal/m3u-parser/xteve_m3uParser.go:54-80 for the generic attribute map with no chno handling, src/struct-system.go:202-216 for M3UChannelStructXEPG, src/system.go:129 for defaults[mapping.first.channel] = 1000, src/xepg.go:332-348 for the first-free scan; issue #269 closed as not planned | Spezifikation | Nicht zutreffend |
| Threadfin, eine Abspaltung von xTeVe, liest tvg-chno sehr wohl, speichert es als Zeichenkette, wertet es zum Sortieren und für Vergleiche beim Entdoppeln als Gleitkommazahl aus und kopiert den Wert wörtlich in die Senderkennung, die es nach außen gibt, Kollisionen bleiben also bestehen. Das Entdoppeln ist ein md5 über Adresse plus tvg-id plus M3U-Quellenkennung, mit Rückfall auf Adresse plus Quellenkennung, wenn tvg-id leer ist; ein zweiter Durchgang bricht Gleichstände über die kleinere ausgewertete Sendernummer. Das Entfernen von Duplikaten über den Namen ist vorhanden, im Quelltext aber abgeschaltet.Threadfin/Threadfin, branch main, head 6b9c0ccf16 dated 2025-09-29. String storage at src/struct-system.go:194 and :232; verbatim copy into xChannelID at src/xepg.go:643-647; float parse for sort at src/m3u.go:287-288; float parse for the dedupe tie-break at src/xepg.go:1923-1927; hash input at src/xepg.go:476-484, :508-516 and :1835-1843; disabled name-based removal at src/xepg.go:1853 | Spezifikation | Nicht zutreffend |
| Plex Live TV hat keine eigene M3U-Aufnahme, innerhalb von Plex wertet also nie etwas tvg-chno aus. Seine Dokumentation zu von der Gemeinschaft unterstützten Tunern verlangt ein Gerät nach der Windows-BDA- oder der Linux-DVB-Schnittstelle und nennt TVHProxy unter den Wegen, die Leute nutzen. Der übliche Weg von einer Playlist aus ist ein Proxy nach Art von HDHomeRun, wo die Nummer als GuideNumber in lineup.json ankommt, und welche Nummer das ist, hängt vom Proxy ab: xTeVe setzt eine eigene ein, Threadfin reicht die Zeichenkette aus tvg-chno wörtlich durch.Plex Live TV and Community Supported Tuners documentation, which describes Windows BDA and Linux DVB API devices and names TVHProxy; the HDHomeRun lineup.json GuideNumber field; Threadfin/Threadfin src/xepg.go:643-647 into src/hdhr.go:160, which sets stream.GuideNumber from the value taken from tvg-chno | Spezifikation | Nicht zutreffend |
| Channels DVR dokumentiert channel-number für eigene Senderquellen, neben einer verpflichtenden channel-id, tvg-logo, tvg-name und seinen eigenen tvc--Erweiterungen. Seine Dokumentation erwähnt tvg-chno nicht. Sie hält fest, dass eine Nummer, die mit der Senderliste einer anderen Quelle kollidiert, zusammengeführt wird und der bevorzugte Sender verwendet wird.Channels DVR documentation for custom channel sources, verbatim: Be sure not to use a channel number that exists in another source's lineup. Channels will merge them together and use the prioritized channel. | Spezifikation | Nicht zutreffend |
| Der M3U-Parser von VLC liest tvg-logo, tvg-name, tvg-language, tvg-id und group-title und verwirft unbekannte tvg--Schlüssel stillschweigend, chno eingeschlossen. VLC hat überhaupt keinen Begriff einer Sendernummer, nur die Position in der Playlist.VideoLAN vlc, modules/demux/playlist/m3u.c, tvg attribute handling added 2020-03-11 | Spezifikation | Nicht zutreffend |
| Das von Hand gebaute Bruchstück in diesem Artikel ergibt sechs Zeilen, von denen vier unter unserem Parser eine brauchbare Nummer tragen, und eine nummerierte Sortierung von 1, 1, 7 und 22.1, gefolgt von den beiden nicht nummerierten Zeilen in Namensreihenfolge. | n = 6 | 23.08.2026 |