OTT Navigator

M3U playlist format

This is the reference for playlist authors and providers. The app reads the common IPTV flavor of M3U (as used by other IPTV players and Kodi) plus a few tags of its own. A marker like (since 1.7.1.3) is the first app version that reads an attribute; attributes without a marker have been supported for years.

Contents:

A basic M3U file format sample

#EXTM3U url-tvg="http://example.com/epg.xml.gz"
#EXTINF:-1 tvg-id="music1" tvg-logo="http://example.com/logo/music1.png" group-title="Music",Music 1
http://example.com/channel/01.m3u8
#EXTINF:-1 tvg-id="sport.news" group-title="Sports",Sports News
http://example.com/channel/02.m3u8

A fuller sample with archive, headers and DRM:

#EXTM3U url-tvg="http://example.com/epg.xml.gz" catchup="shift" catchup-days="3" refresh="6"
#EXTINF:-1 tvg-id="news1" ch-number="1" tvg-logo="news1.png" group-title="News",News One HD
#EXTVLCOPT:http-user-agent=MyPlayer/1.0
#EXTVLCOPT:http-referrer=http://example.com/
http://example.com/live/news1/index.m3u8
#EXTINF:-1 tvg-id="movies" group-title="Movies" catchup-enable="0",Movies (no archive)
#EXTHTTP:{"Authorization":"Bearer abc123"}
http://example.com/live/movies/index.m3u8
#EXTINF:-1 tvg-id="premium" group-title="Premium",Premium (DRM)
#KODIPROP:inputstream.adaptive.license_type=clearkey
#KODIPROP:inputstream.adaptive.license_key=0123456789abcdef0123456789abcdef:fedcba9876543210fedcba9876543210
http://example.com/live/premium/manifest.mpd

How the file is read

#EXTM3U: playlist header

The first line of the playlist. Its attributes apply to the whole playlist:

#EXTINF: channel attributes

#EXTINF:-1 tag1="value1" tag2="value2",Channel name. The duration (-1 or 0) is ignored.

Identity, category and logo:

Restrictions:

TV guide:

Archive (catch-up), per channel: catchup, catchup-type, catchup-days, catchup-time, catchup-source, catchup-enable, tvg-rec, timeshift. See Archive (catch-up) in playlists.

Playback:

Media library entries (when the playlist is a media library, see below):

Stream URL

The first line after the tags that starts with a supported scheme (see How the file is read) is the stream address.

HTTP headers can be appended to it after |, as name=value pairs separated by &. This form is not recommended: values are cut at & and =; use #EXTHTTP instead.

http://example.com/channel/01.m3u8|User-Agent=MyPlayer/1.0&Referer=http://example.com/

Login and password in the address (http://user:pass@example.com/...) are sent as HTTP basic authorization.

The address may use ${token}, ${login}, ${password} and the other template variables: they are filled in at playback from the provider’s settings in the app.

#EXTGRP: Category Name

#EXTGRP:News sets the category of the next channel, the same as group-title.

Including other playlists

An entry with type="playlist" (or content-type="playlist") and an http(s) URL includes that playlist in place:

#EXTINF:-1 type="playlist",Sports
http://example.com/sports.m3u

TV guide (XMLTV)

The guide is given by url-tvg in the header (or epg in OTC). Users can add more guides themselves, see How to set up the TV guide.

HTTP headers

A channel’s requests can carry extra headers in these ways (pick one per channel):

Headers set by the user in the provider’s properties are sent too; a channel’s own header of the same name wins.

The User-Agent sent is the first one found of: the app-wide HTTP User-Agent setting, a User-Agent in the channel’s headers (#EXTHTTP, stream_headers), the channel’s http-user-agent / |User-Agent=, the provider’s User-Agent in its properties, the app’s own.

#EXTHTTP:{..http tags..}

Headers as a JSON object (since 1.6.6.9):

#EXTHTTP:{"User-Agent":"MyPlayer/1.0","Referer":"http://example.com/","X-Token":"abc"}

They go with every request of the stream (playlist, segments, keys) and with the DRM license request.

#EXTVLCOPT:parameter="value"

VLC-compatible options, one per line:

#EXTVLCOPT:http-user-agent=MyPlayer/1.0
#EXTVLCOPT:http-referrer=http://example.com/

Other VLC options are ignored.

DRM: #KODIPROP:parameter=value

Kodi-compatible properties (the syntax of Kodi’s inputstream.adaptive), one per line. Whether a DRM system works also depends on the device; see DRM-protected channels.

#EXTINF:-1 group-title="Premium",Premium HD
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
#KODIPROP:inputstream.adaptive.license_key=https://license.example.com/wv|X-Token=abc
#KODIPROP:inputstream.adaptive.manifest_type=mpd
http://example.com/live/premium/manifest.mpd

#EXTATTRFROMURL:http://some/url/for/data.m3u

Since 1.6.9.2. Keeps sensitive or short-lived data (DRM keys, tokens, the stream address itself) out of the playlist: the app requests this URL each time the user starts the channel or media library entry, and applies what it gets.

Playlist:

#EXTINF:-1 tvg-id="premium" group-title="Premium",Premium HD
#EXTATTRFROMURL:https://example.com/api/attrs?ch=premium&start={fromUnix}
http://example.com/placeholder

Response:

#EXTINF:-1,Premium HD
#KODIPROP:inputstream.adaptive.license_type=clearkey
#KODIPROP:inputstream.adaptive.license_key=0123456789abcdef0123456789abcdef:fedcba9876543210fedcba9876543210
http://example.com/live/premium/manifest.mpd?token=xyz

Movies and series in M3U

Two ways:

  1. A separate media library given by vod_library in the header (recommended). Every entry of that M3U is a library item:
    • group-title is the folder;
    • entries with tvg-season / tvg-episode or tvg-serie are gathered into series: by tvg-serie when given, otherwise by the same name; serie-title names the series;
    • tvg-logo is the poster, tvg-imdb / tvg-tmdb link the title to IMDb / TMDB;
    • an entry with type="playlist" is a folder whose content (another M3U) is loaded when the user opens it;
    • playback attributes (codec, headers, DRM, #EXTATTRFROMURL, …) work as for channels.
  2. Inside the channel playlist (when there is no vod_library): an entry is taken out of the channel list and put in the media library when it has type="movie" or type="series". Mark series episodes with tvg-season / tvg-episode.
#EXTM3U
#EXTINF:-1 tvg-logo="http://example.com/posters/show.jpg" tvg-serie="show1" serie-title="Some Show" tvg-season="1" tvg-episode="1" group-title="Drama",Some Show S01E01
http://example.com/vod/show1/s01e01.mp4
#EXTINF:-1 tvg-logo="http://example.com/posters/movie.jpg" tvg-imdb="tt0000001" group-title="Action",Some Movie (2020)
http://example.com/vod/movie.mp4