m3u gegen m3u8: die Dateiendung sagt Ihnen nicht, welches Format vorliegt

Eine der drei Dateien, die wir für die Parser-Arbeit aufbewahren, heißt .m3u8 und hält 1.895 Senderzeilen. Eine andere heißt .m3u, und auf 303 ihrer 308 Zeilen endet der Adresspfad auf .m3u8.

file                    named   entries   URL paths ending .m3u8   lines beginning #EXT-X-
playlist_01              .m3u       308                      303                        0
playlist_02             .m3u8     1,895                    1,621                        0
iptv-org-index-sample    .m3u         6                        6                        0

Drei Dateien, die wir für die Parser-Arbeit aufbewahren: zwei echte Playlists und eine Testvorlage mit sechs Einträgen. Eine kuratierte Stichprobe und keine zufällige Ziehung aus der freien Wildbahn. Behalten Sie das beim Lesen jeder Zahl unten im Kopf. Die auf .m3u8 benannte ist eine Senderliste mit 1.895 Zeilen, jede ein Name und eine Adresse, ohne irgendein HLS-Tag darin. Die auf .m3u benannte ist ebenfalls eine Senderliste, und auf 303 ihrer 308 Zeilen endet der Adresspfad auf .m3u8. Sortieren Sie die beiden nach ihren eigenen Endungen, und Sie haben sie vertauscht. Sortieren Sie sie nach den Endungen der Adressen darin, und Sie nennen beide Dateien HLS, 98.4 Prozent der einen und 85.5 Prozent der anderen, was doppelt falsch ist.

Die Endung ist eine Namenskonvention. Sie reist mit der Datei, wer immer sie geschrieben oder ausgeliefert hat, hat sie gewählt, und nichts setzt sie durch. Ein Parser, der ihr vertraut, wird bei echter Eingabe falsch liegen. Das Falschliegen ist leise.

RFC 8216 nimmt beide Endungen für dieselbe Datei an

Das Dokument, das HLS definiert, ist darin ausdrücklich. Es sagt das Gegenteil der Folklore. Es ist informativ und nicht auf dem Standardisierungsweg, und eine Überarbeitung, die es ablösen würde, draft-pantos-hls-rfc8216bis, liegt in der Warteschlange des RFC-Editors und benennt die Master Playlist in Multivariant Playlist um. Die Regel unten übersteht diese Umbenennung. Abschnitt 4:

Each Playlist file MUST be identifiable either by the path component of its URI or by HTTP Content-Type. In the first case, the path MUST end with either .m3u8 or .m3u. In the second, the HTTP Content-Type MUST be application/vnd.apple.mpegurl or audio/mpegurl. Clients SHOULD refuse to parse Playlists that are not so identified.

Lesen Sie die beiden Hälften. Eine konforme HLS-Playlist darf unter einem Pfad ausgeliefert werden, der auf .m3u endet, eine der beiden Schreibweisen, die das Dokument nennt. Und die Erkennung ist ein Entweder-oder: eine Playlist, die über ihren Content-Type erkannt wird, hat die Anforderung mit jedem beliebigen Pfad erfüllt, auch ganz ohne Endung. Die Spezifikation, die die Leute für ".m3u8 heißt HLS" anführen, erlaubt also .m3u für HLS und erlaubt einen Pfad, der nichts sagt.

Der Hälfte der Folklore zur Kodierung ergeht es nicht besser. Die 8 in .m3u8 wird weithin als UTF-8 erklärt, und Abschnitt 4.1 verlangt tatsächlich UTF-8, von jeder Playlist, bei beiden Endungen: "Playlist files MUST be encoded in UTF-8. They MUST NOT contain any Byte Order Mark (BOM); clients SHOULD fail to parse Playlists that contain a BOM or do not parse as UTF-8." Die Anforderung hängt an der Playlist und nicht an der Schreibweise ihres Namens. Alle drei unserer Dateien dekodieren als UTF-8 mit null Ersatzzeichen, keine trägt eine Bytereihenfolge-Markierung, und die auf .m3u benannte hat in 24 ihrer Anzeigenamen Zeichen außerhalb von ASCII, die Endungen sagen Ihnen also auch hier nichts.

Was die Spezifikation zur Einordnung einer Playlist heranzieht, ist ihr Inhalt. Abschnitt 4.1: "A Playlist is a Media Playlist if all URI lines in the Playlist identify Media Segments. A Playlist is a Master Playlist if all URI lines in the Playlist identify Media Playlists." Die Art ist eine Eigenschaft dessen, wohin die Adresszeilen zeigen. Der Dateiname steht in diesem Satz nicht.

Die beiden Dateien tragen ihre Endungen verkehrt herum

Keine einzige Zeile in einer der drei beginnt mit #EXT-X-. Keine einzige, über 2.209 Einträge hinweg, und von einer Datei namens .m3u8 hatte ich das nicht erwartet. RFC 8216 übernimmt genau zwei Tags aus dem älteren M3U-Format, #EXTM3U und #EXTINF, und jedes Tag, das sie darüber hinaus definiert, trägt das Präfix EXT-X-, das Fehlen kommt einem Beweis also etwa so nahe, wie es ein Bestand kann: das sind Senderlisten, gebaut auf den beiden übernommenen Tags plus einer eigenen Schicht Direktiven.

Die Adressendungen innerhalb der größeren Datei sind der Ort, an dem die Geschichte mit der Endung auseinanderfällt. Von ihren 1.895 Zeilen zeigen 1.621 auf einen Pfad, der auf .m3u8 endet. Der Rest ist gestreut: 133 Zeilen, deren Pfad überhaupt keine Endung trägt, 15, deren letztes Pfadsegment auf einen Doppelpunkt und eine Portnummer endet, die Path.GetExtension für eine Endung hält, dann 75 mit .php, 17 mit .mpd, 14 mit .htm, 7 mit .ts, 6 mit .m3u, 3 mit .2ts, und je eine Zeile mit .smil, .dash, .mp4 und .wmv. Siebzehn Zeilen enden auf .mpd und eine auf .dash, die beide MPEG-DASH-Manifeste benennen, welche XML sind und überhaupt kein M3U. Sechs zeigen auf ein weiteres M3U. Zweihundertvierzig tragen eine Endung, die kein Medienformat benennt.

Über alle drei Dateien hinweg enden 1.930 von 2.209 Adresspfaden auf .m3u8 und 7 auf .ts, was sich oberflächlich als 87.4 Prozent HLS und 0.3 Prozent MPEG-TS liest. Nichts in den Dateien stützt das, denn keine davon wurde abgerufen. Was der Transportweg tatsächlich ist, ist ein eigenes Thema.

Noch eine Form aus derselben Datei, denn sie zählt später. Ihre #EXTM3U-Zeile ist 6294 Byte lang, und alle bis auf sieben dieser Byte sind ein Attribut x-tvg-url, das 101 kommagetrennte Programmadressen hält. RFC 8216 gibt die Form des Tags als die blanke Zeichenkette #EXTM3U an, verbietet Leerzeichen "except for elements in which it is explicitly specified", und sagt, eine Playlist, die ihre Regeln verletzt, sei ungültig und Clients MÜSSEN die Auswertung verweigern. Die erste Zeile dieser Datei liegt erkennbar außerhalb der Spezifikation, auf eine Weise, die keine HLS-Playlist erzeugen würde. Das ist ein Signal, und wir nutzen es nicht.

Geben Sie einem Senderlisten-Parser ein HLS-Manifest, und Sie bekommen drei verschiedene Fehler

Hier ist eine Live-Media-Playlist, für diesen Artikel mit einem reservierten Beispiel-Host gebaut und auf drei Segmente gekürzt:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:26401
#EXTINF:10.000,
https://example.com/seg26401.ts
#EXTINF:10.000,
https://example.com/seg26402.ts
#EXTINF:10.000,
https://example.com/seg26403.ts

Ich habe das durch den ausgelieferten Parser laufen lassen, statt es von Hand nachzuvollziehen. Drei Sender, null Meldungen.

Zeile 1 wird übersprungen, denn der Parser sucht nur nach #EXTINF: und geht über jede andere #-Zeile als unbekannte Direktive hinweg. Die Zeilen 2, 3 und 4 gehen denselben Weg: #EXT-X-VERSION, #EXT-X-TARGETDURATION und #EXT-X-MEDIA-SEQUENCE sind für uns alle bloß Rauten. Jede Zeile #EXTINF:10.000, wird sauber ausgewertet, denn der Dauer-Scanner nimmt 10, der Rest .000 landet harmlos im Attributbereich, und der Titel nach dem Komma ist leer. Ein leerer Titel wird zur wörtlichen Zeichenkette Unnamed channel. Jede folgende Zeile ist eine absolute HTTPS-Adresse, sie wird also angenommen, und ein Sender wird ausgegeben.

Drei Sender namens Unnamed channel, jeder auf ein zehn Sekunden langes Bruchstück eines einzigen Stroms zeigend. Kein Fehler, keine Warnung, kein Zähler. Der Import meldet Erfolg.

Ändern Sie eine Sache, und die Form ändert sich völlig. HLS erlaubt eine Segmentadresse relativ zu ihrem Manifest (Abschnitt 4.1) und erlaubt einem Live-Server, Segmente vorne abzuwerfen, während der Strom fortschreitet (Abschnitt 6.2.2), und viele Server tun beides, die Zeilen lauten also seg26401.ts, wo eine vollständige Adresse stand. Diese scheitern am Test auf eine absolute Adresse, und dieselbe Datei ergibt null Sender und drei Meldungen, die Skipped non-absolute http(s) URL lauten. Eine Master-Playlist mit absoluten Adressen der Fassungen scheitert auf eine dritte Art: sie hat überhaupt keine #EXTINF-Zeilen, nur #EXT-X-STREAM-INF vor jeder Adresse einer Fassung, jede Adresse kommt also ohne wartende Kopfzeile an und erzeugt URL without preceding EXTINF (skipped).

Drei Eingaben, die alle dasselbe sind, drei nicht miteinander verwandte Ergebnisse, und keines davon sagt "das ist ein HLS-Manifest". Das schlimmste der drei ist das, das gelingt. Wer eine Media-Playlist mit absoluten Segmentadressen importiert hat, bekommt eine Quelle, die gefüllt aussieht, und der Fehler zeigt sich erst beim Versuch, eine Zeile abzuspielen.

Die erste #EXT-X--Zeile sagt Ihnen, was die Datei ist

Jede dieser Dateien kündigt sich in ihren ersten vier Zeilen an. Der Test ist billig, er ist nicht die Endung, und nichts in unserem Client oder unseren Diensten führt ihn aus: lesen Sie den Anfang des Rumpfes und suchen Sie eine Zeile, deren erste sieben Zeichen #EXT-X- lauten. Jeder Treffer bedeutet in der Praxis HLS, denn jedes Tag, das die Spezifikation über die beiden übernommenen hinaus definiert, trägt dieses Präfix. Zwei Treffer sind darüber, welche Art vorliegt, entscheidend:

  • #EXT-X-TARGETDURATION bedeutet eine Media Playlist, eine Liste von Segmenten. Abschnitt 4.3.3.1 macht es darin VERPFLICHTEND, sein Fehlen hat also ebenfalls Gewicht.
  • #EXT-X-STREAM-INF bedeutet eine Master Playlist, eine Liste von Fassungen.

Die Spezifikation beansprucht kein Präfix und führt kein Tag-Register, das ist also eine starke Konvention und keine Garantie: eine Senderliste könnte eine verirrte #EXT-X--Zeile tragen und von dem Verfahren, das ich empfehle, falsch gelesen werden. Keine unserer tut das.

Ohne ein #EXT-X- irgendwo stützen drei begleitende Formen eine Senderliste. Eine Dauer von -1, die alle 2.209 unserer Einträge tragen, liegt außerhalb der Grammatik von RFC 8216, denn weder die Form der dezimalen Ganzzahl noch die der dezimalen Gleitkommazahl nimmt ein Minus. Attribute auf der #EXTM3U-Zeile, wie in der Kopfzeile von 6294 Byte oben. Und tvg--Attribute zwischen der Dauer und dem Komma, eine Konvention ohne Spezifikation dahinter.

Beide Tags sitzen üblicherweise nahe dem Anfang der Datei, zu der sie gehören. RFC 8216 schreibt eine Position allein für #EXTM3U vor, ein begrenztes Lesen ist also eine Heuristik.

Der Content-Type ist eine dritte Meinung und wir haben nie danach gefragt

RFC 8216 bietet den Content-Type als Alternative zum Pfad an, was nach der verlässlichen Hälfte klingt, bis man bemerkt, was das Entweder-oder erlaubt: ein Server, der seine Playlist über den Pfad erkennbar gemacht hat, darf danach jede beliebige Kopfzeile senden.

Dafür haben wir eine Absicherung geschrieben. Sie lehnt offensichtlich falsche MIME-Familien ab, bevor ein Rumpf gelesen wird: HTML, JSON, Bilder, Video, Schriften, mehrteilige Inhalte und WebAssembly. Unbekannte und allgemeine Typen gehen an die Rumpfprüfung durch, text/plain ist das genannte Beispiel. Danach schneidet sie aus ihrer eigenen pauschalen Ablehnung von audio/* zwei Ausnahmen heraus: audio/x-mpegurl, mit der erklärten Begründung, dass Inhaltsnetze und statisches Hosting Playlists gewöhnlich als diesen Typ ausliefern, und audio/mpegurl, einen der beiden Typen, die die Spezifikation nennt und den die pauschale Regel sonst ablehnen würde. Die Absicherung ist mit Unit-Tests abgedeckt und hat keinen Aufrufer im Produktivbetrieb. Sie hatte einen, bis die Umstellung auf den schlanken Katalog den serverseitigen Abrufer löschte, der sie nutzte.

Was tatsächlich läuft, ist eine Rumpfprüfung, und sie läuft auf Ihrem Gerät. Sie überspringt eine optionale UTF-8-Bytereihenfolge-Markierung und alle führenden Leerzeichen und nimmt die Datei dann an, wenn die nächsten sieben Byte #EXTM3U oder #EXTINF lauten. Gegen die ausgelieferte Absicherung ausgeführt nimmt sie eine HLS-Master-Playlist, eine HLS-Media-Playlist, eine Senderliste ohne Kopfzeile und eine Datei mit Bytereihenfolge-Markierung an. Sie lehnt eine HTML-Fehlerseite und einen JSON-Fehlerrumpf ab, und das ist die Art Eingabe, für die die Content-Type-Absicherung geschrieben wurde. Sie lehnt außerdem eine Datei ab, deren erste Zeile ein gewöhnlicher #-Kommentar ist, und RFC 8216 würde diese ebenfalls ablehnen, denn sie verlangt #EXTM3U zuerst, wir landen also zufällig an der richtigen Stelle.

Welche Kopie läuft, ist wichtig, und ich hatte sie an der falschen Stelle, bis ich den Aufrufgraphen abgelaufen bin. Der Katalogdienst trägt einen Zwilling mit einer binären Schicht obendrauf, die Nullbytes und sechs Kennungsfolgen für PDF, Windows-Programme, ELF-Binärdateien und drei ZIP-Varianten ablehnt. Diese Schicht sagt, ob die Datei eine verkleidete Binärdatei ist, nie, ob sie HLS ist. Und nichts im Produktivbetrieb erreicht sie: der einzige Aufrufer der Inhaltsprüfung des Server-Zwillings ist ein Integrationstest. Die Prüfung, die bei einem echten Upload läuft, ist die des Clients, bei CloudSyncUploadService.cs:28, sechs Zeilen bevor der Klartext verschlüsselt wird, die Bytes, die ein Server prüfen könnte, sind also bereits Geheimtext, wenn sie Ihren Rechner verlassen.

Diese Prüfung liest höchstens 8192 Byte, eine Grenze, die für eine Sicherheitsprüfung gewählt wurde, ohne einen Gedanken an das Einordnen eines Formats. Gerade eben genug. In der Datei mit 308 Zeilen ist die erste Zeile 7 Byte lang und 29 vollständige #EXTINF-Zeilen passen in das Fenster, 28 davon mit ihrer Adresse. In der Datei mit 1.895 Zeilen frisst allein die erste Zeile 6294 der 8192, was 1898 Byte übrig lässt, die 9 vollständige #EXTINF-Zeilen halten, 8 davon mit ihrer Adresse. Eine Master-Playlist passt ganz hinein und eine Media-Playlist stellt #EXT-X-TARGETDURATION in ihre Eröffnungszeilen, das Fenster funktioniert also wegen der Stelle, an der HLS-Tags sitzen. Acht Kilobyte sind kein grundsätzlich begründeter Anteil einer Datei zum Lesen.

Das Verhalten bei der Bytereihenfolge-Markierung ist der Teil, den ich immer wieder ansehe. RFC 8216 sagt, Clients SOLLTEN die Auswertung einer Playlist mit einer Bytereihenfolge-Markierung verweigern, und das Erste, was unsere Prüfung tut, ist, über eine hinwegzugehen und weiterzumachen. Notepad und PowerShells Out-File schreiben eine, und diese Dateien abzulehnen würde eine Nutzerin oder einen Nutzer einen funktionierenden Import kosten, um eine Regel ohne praktische Folge für uns zu erfüllen, wir weichen also wissentlich ab. Es bleibt eine Abweichung, und wer gegen die Spezifikation baut, sollte sie nicht von uns übernehmen.

Registrieren Sie eine Playlist über eine Adresse, statt sie hochzuladen, gibt es keinen Rumpf zu prüfen, denn diese Registrierung speichert eine Adresse als Kontometadaten und ruft nichts ab. Übrig bleibt die Endung, und unsere Prüfung läuft verkehrt herum: sie greift nur, wenn der Pfad bereits eine hat, eine Adresse mit der Endung .txt wird also abgelehnt und eine Adresse mit der Endung /playlist ungeprüft angenommen. Die Regel prüft die Adressen, die Ihnen etwas gesagt haben, und winkt die schweigsamen durch. Billiger Tippfehlerfänger, nutzlose Formatprüfung.

Die Endung in einer Stream-Adresse ist eine Anforderung und keine Beschreibung

Alles oben Genannte betrifft die Playlist-Datei. Dasselbe Problem wiederholt sich eine Ebene tiefer, bei den Adressen darin, wo es sich leichter vorführen lässt, weil wir sie schreiben.

Portalsoftware der Xtream-Codes-Familie baut eine Live-Adresse als {portal}/live/{user}/{pass}/{streamId}.{ext}, und die Endung ist der Client, der den Server fragt, welchen Behälter er senden soll. Derselbe Sender ist 1234.ts oder 1234.m3u8, je nachdem, was Sie tippen. Ihr Playlist-Export-Endpunkt nimmt dieselbe Wahl als Abfrageparameter entgegen, und die beiden Vokabulare passen nicht zusammen: der Pfad schreibt es .m3u8, während die Gemeinschaftsdokumentation zu dieser API die Abfragewerte als ts, hls und rtmp angibt, mit ts als Vorgabe. Unser eigener Dokumentationskommentar bei XtreamM3uPlusExportUri.cs:5 schreibt output=ts|m3u8, einen Wert, den diese Dokumentation nicht aufführt, wir liefern die Verwirrung also in einer Quelldatei mit aus. Nichts am Sender ändert sich, und die Endung ist immer nur eine Anforderung.

Unser Verzeichnis enthält zwei Baumeister für diese Adresse und sie sind sich uneinig. Der, der auf dem Gerät läuft, verdrahtet .ts fest. Der andere hängt .m3u8 an und hat außerhalb seines eigenen Tests keinen Aufrufer. Zugleich trägt jede Xtream-Quelle für genau das eine gespeicherte Einstellung, auf nicht zusammengeführten Quellen als zweiwertiges Bedienelement mit der Beschriftung Stream-Format sichtbar, mit den Optionen MPEG-TS und HLS (m3u8) und dem Hinweis Vom Xtream-Portal angefordertes Container-Format. Suchen Sie im Desktop-Client nach diesem Feld, und Sie finden den API-Vertrag, die Zeile im Ansichtsmodell und den Einstellungsdialog, sonst nirgends. Der Adressbaumeister liest es nicht. Der Wiedergabepfad liest es nicht.

Eine Nutzerin oder ein Nutzer kann also die Quelleneinstellungen öffnen, auf HLS umschalten, speichern, den Dialog erneut öffnen und HLS ausgewählt sehen, und das Gerät wird für jeden Sender weiter .ts anfordern. Der Wert läuft hin und zurück und ändert nichts. Was uns überrascht hat, ist, dass dieser Fall unserer ist, ausgeliefert, und niemand hat es bemerkt: das Bedienelement wurde neben dem gespeicherten Feld gebaut und der Baumeister nie damit verbunden, die Einstellung meldet also einen Zustand, den sie nicht hat, und das ist schlimmer, als sie nicht anzubieten. Es tauchte auf, während ich Belege für diese Seite sammelte, nie aus einer Supportmeldung, und das sagt Ihnen, wie sichtbar es von außen ist.

Die Einordner, die wir auf diesen Adressen tatsächlich laufen lassen, sind sich ebenfalls uneinig, in kleinerem Maß. Der Wiedergabe-Wachhund entscheidet über hls oder ts, indem er prüft, ob die gesamte Adresse die Teilzeichenkette .m3u8 enthält, ein Token in einer Abfrage zählt also mit. Der Dialog mit den Stream-Informationen meldet einen Behälter, indem er die Endung des Adresspfads in Großbuchstaben setzt, ein Endpunkt get.php würde also PHP zeigen, eine Zeile mit .mpd MPD, und die 15 Zeilen, deren Pfad auf eine Multicast-Gruppe und einen Port endet, etwas in der Form 1:1234. Lassen Sie beide über die Datei mit 1.895 Zeilen laufen, und sie sind sich auf 6 Zeilen uneinig, von denen jede .m3u8 innerhalb einer Abfrage statt am Ende eines Pfads trägt. Sechs Zeilen sind keine Krise, und das Urteil des Wachhunds ist Telemetrie, die kein Schwellenwert liest, es handelt also nichts danach. Es sind trotzdem zwei Funktionen in einer App, die dieselbe Frage unterschiedlich beantworten, und keine von beiden fragt den Demuxer, das einzige Bauteil, das es weiß.

Die Grenze ist, dass wir drei kuratierte Dateien halten. Playlist-Bytes werden auf Ihrem Gerät gelesen, gegen die Adresse, auf die Sie es richten, und wir kuratieren Programmadressen und nie die Programmdaten. Ich kann Ihnen also sagen, wie diese 2.209 Einträge aussehen und was unser Parser mit einem Manifest macht. Ich kann Ihnen nicht sagen, wie oft eine .m3u8-Adresse in freier Wildbahn eine Senderliste zurückgibt, denn das zu messen hieße, Playlist-Rümpfe von Adressen zu ziehen, die Nutzerinnen und Nutzer uns gegeben haben.

Um zu sehen, was eine Datei tatsächlich enthält, werten die Windows- und die Xbox-App sie lokal aus und listen auf, was herauskam; ein kostenloses Konto genügt, um es an einer Quelle auszuprobieren, die Sie bereits haben.

Für alle, die stattdessen den Parser schreiben, ist die Regel enger als "den Rumpf prüfen". Entscheiden Sie anhand des ersten Tags, das nur zu einem Format gehören kann, was die Datei ist, und lassen Sie diese Entscheidung eine Meldung erzeugen. Die Endung und der Content-Type sind Hinweise, deren Prüfung nichts kostet und die nichts belegen, wenn sie übereinstimmen. Unserer erzeugt zwei Meldungen, die das falsche Problem benennen, und einen Import, der gelingt und dabei vollständig falsch ist, und der dritte ist der, der Sie einen Supportvorgang kostet.

Was dieser Artikel gemessen hat34 Behauptungen, jeweils mit den Beweisen dahinter
AnspruchBeweiseGezählt
RFC 8216 erkennt eine Playlist am Pfad ODER am Content-Type, der Pfad darf auf .m3u8 oder auf .m3u enden, und Clients sollten eine Playlist ablehnen, die über keines von beidem erkannt wird.RFC 8216 section 4, verbatim: Each Playlist file MUST be identifiable either by the path component of its URI or by HTTP Content-Type. In the first case, the path MUST end with either .m3u8 or .m3u. In the second, the HTTP Content-Type MUST be "application/vnd.apple.mpegurl" or "audio/mpegurl". Clients SHOULD refuse to parse Playlists that are not so identified.SpezifikationNicht zutreffend
RFC 8216 ist informativ und nicht auf dem Standardisierungsweg, und eine Überarbeitung, die sie ablösen und die Master Playlist in Multivariant Playlist umbenennen würde, liegt in der Warteschlange des RFC-Editors. Die hier zitierte Erkennungsregel ist darin unverändert.RFC 8216 Status of This Memo, verbatim: This document is not an Internet Standards Track specification; it is published for informational purposes. Revision: draft-pantos-hls-rfc8216bis-22 (1 May 2026), datatracker state Sent to the RFC Editor, marked obsoletes 8216 (if approved), titled HTTP Live Streaming 2nd Edition, which introduces the Multivariant Playlist in place of the Master Playlist.SpezifikationNicht zutreffend
RFC 8216 verlangt UTF-8 für jede Playlist unabhängig von der Endung und weist Clients an, an einer Bytereihenfolge-Markierung zu scheitern.RFC 8216 section 4.1, verbatim: Playlist files MUST be encoded in UTF-8 [RFC3629]. They MUST NOT contain any Byte Order Mark (BOM); clients SHOULD fail to parse Playlists that contain a BOM or do not parse as UTF-8.SpezifikationNicht zutreffend
RFC 8216 bestimmt die Art einer Playlist danach, worauf ihre Adresszeilen zeigen, und nicht nach ihrer Endung.RFC 8216 section 4.1, verbatim: A Playlist is a Media Playlist if all URI lines in the Playlist identify Media Segments. A Playlist is a Master Playlist if all URI lines in the Playlist identify Media Playlists.SpezifikationNicht zutreffend
RFC 8216 übernimmt genau zwei Tags aus dem älteren M3U-Format, EXTM3U und EXTINF. Jedes weitere Tag, das sie definiert, trägt das Präfix EXT-X-, und genau das macht eine #EXT-X--Zeile zu einem brauchbaren HLS-Signal. Die RFC beansprucht das Präfix nicht und definiert kein Tag-Register.RFC 8216 section 4, verbatim: The format of the Playlist files is derived from the M3U [M3U] playlist file format and inherits two tags from that earlier file format: EXTM3U (Section 4.3.1.1) and EXTINF (Section 4.3.2.1). Section 4.1 says only: Tags begin with #EXT. They are case sensitive. Section 9 registers one media type and reserves no tag prefix.SpezifikationNicht zutreffend
EXT-X-TARGETDURATION ist in einer Media Playlist verpflichtend, und genau das macht sein Fehlen zu einem brauchbaren Signal.RFC 8216 section 4.3.3.1, verbatim: The EXT-X-TARGETDURATION tag is REQUIRED.SpezifikationNicht zutreffend
EXTM3U muss die erste Zeile jeder Playlist sein, seine festgelegte Form ist die blanke Zeichenkette #EXTM3U, und Leerzeichen sind verboten, außer wo ein Tag sie ausdrücklich vorsieht. Eine Playlist, die diese Regeln verletzt, ist ungültig und Clients müssen die Auswertung verweigern.RFC 8216 section 4.3.1.1, verbatim: It MUST be the first line of every Media Playlist and every Master Playlist. Its format is: #EXTM3U. Section 4.1, verbatim: Whitespace MUST NOT be present, except for elements in which it is explicitly specified. Section 4, verbatim: Playlists that violate these rules are invalid; clients MUST fail to parse them.SpezifikationNicht zutreffend
Die Dauer in #EXTINF ist eine dezimale Ganzzahl oder eine dezimale Gleitkommazahl, und keine der beiden Produktionen lässt ein Minuszeichen zu, #EXTINF:-1 liegt also außerhalb der Grammatik von RFC 8216.RFC 8216 section 4.3.2.1 (Its format is: #EXTINF:<duration>,[<title>]) with section 4.2, where decimal-integer is characters from [0..9] and decimal-floating-point is characters from [0..9] and '.' expressing a non-negative number; only signed-decimal-floating-point admits '-'.SpezifikationNicht zutreffend
RFC 8216 erlaubt eine relative Segmentadresse und erlaubt einem Live-Server, Segmente aus der Playlist zu entfernen, während der Strom fortschreitet. Beides sind Erlaubnisse und keine verlangte Praxis, und das eigene Live-Beispiel der RFC verwendet absolute Segmentadressen.RFC 8216 section 4.1, verbatim: A URI in a Playlist, whether it is a URI line or part of a tag, MAY be relative. Section 6.2.2, verbatim: The server MAY limit the availability of Media Segments by removing Media Segments from the Playlist file (Section 6.2.1). If Media Segments are to be removed, the Playlist file MUST contain an EXT-X-MEDIA-SEQUENCE tag. Section 8.2, Live Media Playlist Using HTTPS, lists absolute https segment URIs.SpezifikationNicht zutreffend
Der Playlist-Export-Endpunkt von Xtream Codes dokumentiert output=ts, output=hls und output=rtmp, mit ts als Vorgabe. m3u8 ist keiner der dokumentierten Abfragewerte, obwohl .m3u8 die Schreibweise derselben Wahl als Pfadendung ist.Community reference documentation for the Xtream Codes API (zaclimon/xipl wiki, Xtream-Codes-API), verbatim on the output parameter: ts, hls and rtmp are available. By default it will be ts which represents the MPEG-TS container.SpezifikationNicht zutreffend
Unser eigener Dokumentationskommentar für den Auswerter der Xtream-Export-Adresse dokumentiert die Abfrage als [&output=ts|m3u8], und das ist kein Wert, den die Gemeinschaftsdokumentation aufführt.n = 123.08.2026
Der Bestand besteht aus drei kuratierten Dateien mit 2.209 Einträgen aus EXTINF und Adresse, und keine einzige Zeile in einer von ihnen beginnt mit #EXT-X-.n = 220923.08.2026
Die auf .m3u benannte Datei hält 308 Senderzeilen, von denen 303 (98.4 Prozent) einen Adresspfad haben, der auf .m3u8 endet. Die auf .m3u8 benannte Datei hält 1.895 Senderzeilen, ist selbst eine Senderliste, und 1.621 ihrer Zeilen (85.5 Prozent) haben ebenfalls einen Adresspfad, der auf .m3u8 endet. Nach der Endung der inneren Adresse zu sortieren ordnet also beide Dateien als HLS ein.n = 220323.08.2026
In der Datei mit 1.895 Zeilen endet der Adresspfad auf 1.621 Zeilen auf .m3u8 und trägt auf 133 überhaupt keine Endung; 15 Zeilen enden auf einen Doppelpunkt und eine Portnummer, die Path.GetExtension für eine Endung hält; 75 enden auf .php, 17 auf .mpd, 14 auf .htm, 7 auf .ts, 6 auf .m3u, 3 auf .2ts, und je eine Zeile endet auf .smil, .dash, .mp4 und .wmv.n = 189523.08.2026
240 der 1.895 Zeilen tragen eine Adressendung, die kein Medienformat benennt: 133 ohne Endung, 15 mit einem Doppelpunkt und einem Port, 75 mit .php, 14 mit .htm und 3 mit .2ts.n = 189523.08.2026
Alle drei Dateien dekodieren als UTF-8 mit null Ersatzzeichen und keine trägt eine Bytereihenfolge-Markierung. Die auf .m3u benannte Datei hat in 24 ihrer Anzeigenamen Zeichen außerhalb von ASCII, die auf .m3u8 benannte in 736 ihrer Anzeigenamen und einem Gruppennamen.n = 220923.08.2026
Über alle 2.209 Einträge hinweg enden 1.930 Adresspfade auf .m3u8 (87.4 Prozent) und 7 auf .ts (0.3 Prozent). 368 Einträge tragen eine Abfragezeichenkette.n = 220923.08.2026
Alle 2.209 #EXTINF-Zeilen im Bestand tragen eine Dauer von -1.n = 220923.08.2026
Die Vorspann-Prüfung liest höchstens 8192 Byte. In der Datei mit 1.895 Zeilen ist allein die erste Zeile 6294 Byte lang, was 1898 Byte des Fensters übrig lässt, in denen 9 vollständige #EXTINF-Zeilen erscheinen, 8 davon mit ihrer Adresse. In der Datei mit 308 Zeilen ist die erste Zeile 7 Byte lang und 29 vollständige #EXTINF-Zeilen passen in dasselbe Fenster, 28 davon mit ihrer Adresse.n = 223.08.2026
Die #EXTM3U-Zeile der Datei mit 1.895 Zeilen ist 6294 Byte lang und trägt ein Attribut x-tvg-url, das 101 kommagetrennte Programmadressen über 6274 Zeichen hält. Die Zeile ist reines ASCII, Byte und Zeichen stimmen also überein.n = 123.08.2026
Die Vorspann-Prüfung überspringt eine optionale UTF-8-Bytereihenfolge-Markierung und führende Leerzeichen und nimmt die Datei dann an, wenn die nächsten sieben Byte #EXTM3U oder #EXTINF lauten. Ausgeführt: sie nimmt eine HLS-Master-Playlist, eine HLS-Media-Playlist, eine Senderliste ohne Kopfzeile und eine Datei mit Bytereihenfolge-Markierung an und lehnt eine HTML-Seite, einen JSON-Rumpf und eine Datei ab, deren erste Zeile ein einfacher #-Kommentar ist.n = 1123.08.2026
Der einzige Aufrufer einer Playlist-Absicherung auf Byte-Ebene im Produktivbetrieb sitzt auf dem Gerät, und er läuft, bevor der Klartext für den Upload verschlüsselt wird. Die entsprechende Inhaltsprüfung des Katalogdienstes hat keinen Aufrufer im Produktivbetrieb.n = 123.08.2026
Gegen den ausgelieferten Parser ausgeführt: eine HLS-Media-Playlist mit absoluten Segmentadressen ergibt einen Sender je Segment mit dem Namen Unnamed channel und null Meldungen; dieselbe Playlist mit relativen Segmentadressen ergibt null Sender und eine Meldung je Segment; eine HLS-Master-Playlist mit absoluten Adressen der Fassungen ergibt null Sender und je Fassung eine Meldung über eine Adresse ohne vorangehendes EXTINF.n = 323.08.2026
Ein leerer Titel nach dem Komma wird zur wörtlichen Zeichenkette Unnamed channel, und deshalb wird eine HLS-Media-Playlist als Liste gleichnamiger Zeilen importiert statt als nichts.n = 123.08.2026
Nichts im Client oder in den Diensten sucht nach einem #EXT-X--Tag. Eine Suche nach EXT-X über clients/windows/src und src liefert außerhalb der für diesen Artikel geschriebenen Testvorlagen keine Treffer.n = 123.08.2026
Eine Absicherung für den Content-Type beim Abruf von Playlists existiert, ist mit Unit-Tests abgedeckt und hat heute keinen Aufrufer im Produktivbetrieb. Sie hatte einen, bis die Umstellung auf den schlanken Katalog den serverseitigen Abrufer löschte, der sie nutzte.n = 123.08.2026
Die pauschale Ablehnung von audio/* in der Absicherung nimmt sowohl audio/x-mpegurl als auch audio/mpegurl aus. Das zweite davon ist einer der beiden Content-Types, die RFC 8216 nennt, ohne die Ausnahme würde die Absicherung also den Typ der Spezifikation selbst ablehnen.n = 123.08.2026
Die Upload-Absicherung des Katalogs lehnt ein Nullbyte irgendwo im Prüffenster ab, dazu sechs führende Kennungsfolgen (PDF, MZ, ELF und drei ZIP-Varianten) und zwei HTML-Anfänge, und wendet danach dieselbe Vorspann-Prüfung an. Nichts im Produktivbetrieb ruft sie auf.n = 823.08.2026
Beim Registrieren einer Playlist-Adresse wird die Positivliste aus .m3u und .m3u8 nur dann angewendet, wenn der Adresspfad überhaupt eine Endung hat, ein Pfad ohne Endung wird also ungeprüft registriert und ein Pfad mit der Endung .txt abgelehnt.n = 123.08.2026
Für denselben Stream gibt es im Verzeichnis zwei Xtream-Baumeister für Live-Adressen. Der, den das Gerät ausführt, hängt .ts an; der andere hängt .m3u8 an und hat außerhalb seines eigenen Tests keinen Aufrufer.n = 223.08.2026
Das Bedienelement Stream-Format je Quelle, beschriftet mit MPEG-TS und HLS (m3u8) und dem Hinweis Vom Xtream-Portal angefordertes Container-Format, wird nur auf nicht zusammengeführten Xtream-Quellen angeboten, läuft zum Server und zurück, und wird vom Adressbaumeister und vom Wiedergabepfad des Desktop-Kopfes nie gelesen.n = 123.08.2026
Der Wiedergabe-Wachhund ordnet eine Quelle ein, indem er prüft, ob die gesamte Adresse .m3u8 enthält; der Dialog mit den Stream-Informationen meldet einen Behälter, indem er die Pfadendung der Adresse in Großbuchstaben setzt. In der Datei mit 1.895 Zeilen sind sie sich auf 6 Zeilen uneinig, die alle .m3u8 nur innerhalb einer Abfragezeichenkette tragen.n = 189523.08.2026
Weil die Behälterzeile die in Großbuchstaben gesetzte Pfadendung der Adresse ist, würden in der größeren Datei 75 Zeilen einen Behälter PHP anzeigen, 17 MPD, 14 HTM, 3 2TS, 133 überhaupt nichts, und 15 eine Zeichenkette in der Form 1:1234, die das Ende einer Multicast-Adresse und ihres Ports ist.n = 189523.08.2026
Die Einordnung als ts oder hls erreicht im Wachhund keinen Schwellenwert, keine Zeitgrenze und keine Verzweigung. Sie wird für die Telemetrie mitgeführt und für Schwellenwerte je Art, die niemand geschrieben hat.n = 123.08.2026