Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ErsatzTV/legacy/llms.txt

Use this file to discover all available pages before exploring further.

ErsatzTV Legacy exposes a standard M3U playlist at /iptv/channels.m3u that enumerates every enabled channel with its stream URL, channel number, name, group, logo, and a pointer to the XMLTV EPG feed. Any IPTV client that can consume an M3U URL — Plex, Jellyfin, Emby, Kodi, TiviMate, Infuse, VLC, or Channels DVR — can import this playlist and receive live, scheduled programming from ErsatzTV.

Playlist Endpoint

The playlist is served at:
GET /iptv/channels.m3u
HEAD /iptv/channels.m3u
Both GET and HEAD are supported. The HEAD method is useful for clients that check the playlist URL before importing it.

Query Parameters

ParameterDefaultDescription
modemixedOverride the streaming mode for every channel in the playlist.
access_token(none)JWT bearer token passed as a query parameter when authentication is enabled.

Streaming Modes

The mode parameter controls which stream URL format appears for each channel entry. When mode=mixed (the default), ErsatzTV uses each channel’s individually configured streaming mode.
mode valueStream URL formatNotes
mixedPer-channel configured modeDefault; respects each channel’s own streaming mode setting
ts/iptv/channel/{number}.tsTransport Stream Hybrid (recommended TS mode)
ts-legacy/iptv/channel/{number}.ts?mode=ts-legacyLegacy concat-based Transport Stream
segmenter/iptv/channel/{number}.m3u8?mode=segmenterHLS segmenter (recommended HLS mode)
hls-direct/iptv/channel/{number}.m3u8?mode=hls-directHLS direct passthrough
Use mode=ts or mode=segmenter to force all channels to a single streaming mode. This is helpful when your IPTV client handles one protocol better than another.

M3U Playlist Structure

The generated playlist begins with an #EXTM3U header that embeds the XMLTV EPG URL, then lists one entry per enabled channel, ordered by channel number ascending.
#EXTM3U url-tvg="http://ersatztv.local:8409/iptv/xmltv.xml" x-tvg-url="http://ersatztv.local:8409/iptv/xmltv.xml"
#EXTINF:0 tvg-id="C2.0.148.ersatztv.org" channel-id="ABC123==" channel-number="2.0" CUID="ABC123==" tvg-chno="2.0" tvg-name="Movies 24/7" tvg-logo="http://ersatztv.local:8409/iptv/logos/abc123.jpg" group-title="Movies" tvc-stream-vcodec="h264" tvc-stream-acodec="aac", Movies 24/7
http://ersatztv.local:8409/iptv/channel/2.0.ts
#EXTINF:0 tvg-id="C5.0.95.ersatztv.org" channel-id="DEF456==" channel-number="5.0" CUID="DEF456==" tvg-chno="5.0" tvg-name="News Loop" tvg-logo="http://ersatztv.local:8409/iptv/logos/gen?text=News%20Loop" group-title="News" tvc-stream-vcodec="h264" tvc-stream-acodec="aac", News Loop
http://ersatztv.local:8409/iptv/channel/5.0.m3u8?mode=segmenter

Per-Entry M3U Fields

Each #EXTINF line includes the following attributes:
AttributeDescription
tvg-idStable channel identifier, e.g. C2.0.148.ersatztv.org. Includes ETV_INSTANCE_ID when set.
channel-id / CUIDBase64-encoded channel UUID (URL-safe); stable across renames
channel-number / tvg-chnoChannel number (e.g. 2.0, 5.1)
tvg-nameChannel display name
tvg-logoLogo URL (see Channel Logos below)
group-titleChannel group / category
tvc-stream-vcodecVideo codec reported to TiviMate and compatible clients
tvc-stream-acodecAudio codec reported to TiviMate and compatible clients

Stream URLs

Each channel entry in the playlist points to one of the following stream endpoints depending on the streaming mode:

Transport Stream

TS Hybrid: /iptv/channel/{channelNumber}.tsTS Legacy: /iptv/channel/{channelNumber}.ts?mode=ts-legacyReturns an MPEG-2 Transport Stream (video/mp2t) via a spawned FFmpeg process. TS Hybrid uses a wrapped process for lower latency; TS Legacy uses the older concat playlist approach.

HTTP Live Streaming

Segmenter: /iptv/channel/{channelNumber}.m3u8?mode=segmenterHLS Direct: /iptv/channel/{channelNumber}.m3u8?mode=hls-directReturns an HLS multi-variant playlist (application/vnd.apple.mpegurl). The segmenter mode maintains a live HLS session. HLS Direct passes through source stream segments without re-encoding.

HDHomeRun Stream

/iptv/hdhr/channel/{channelNumber}.tsAlways delivers a Transport Stream regardless of channel configuration. Used by HDHomeRun-compatible clients that discover ErsatzTV via the HDHR emulation layer.

HLS Session Playlist

/iptv/session/{channelNumber}/hls.m3u8Internal endpoint used by segmenter sessions. The client is redirected here after a segmenter session starts. Not intended for direct use.

Channel Logos

Channel logos are served from:
GET /iptv/logos/{fileName}
GET /iptv/logos/{fileName}.jpg
If a channel has no logo artwork configured, ErsatzTV generates a text placeholder logo automatically:
/iptv/logos/gen?text={channelName}
Logo endpoints are exempt from JWT authentication even when JWT is enabled, because logos are also displayed in the ErsatzTV management UI.

Multi-Instance Disambiguation (ETV_INSTANCE_ID)

When running multiple ErsatzTV instances, the tvg-id field in the M3U playlist — and channel IDs in the XMLTV feed — would otherwise clash if two instances have channels with the same number. Setting the ETV_INSTANCE_ID environment variable gives each instance a unique suffix:
# Without ETV_INSTANCE_ID
tvg-id="C2.0.148.ersatztv.org"

# With ETV_INSTANCE_ID=home
tvg-id="C2.0.148.home.ersatztv.org"
The tvg-id in the M3U and the id attribute of <channel> elements in the XMLTV feed must match. ErsatzTV ensures they always match as long as ETV_INSTANCE_ID is consistent between restarts.

Kodi Integration

When ErsatzTV detects a Kodi user-agent, it automatically prepends #KODIPROP directives before each channel entry to configure the inputstream.ffmpegdirect addon:
Kodi-Specific Playlist Entries
#KODIPROP:inputstream=inputstream.ffmpegdirect
#KODIPROP:mimetype=video/mp2t
#KODIPROP:inputstream.ffmpegdirect.open_mode=ffmpeg
#EXTINF:0 tvg-name="Movies 24/7" ..., Movies 24/7
http://ersatztv.local:8409/iptv/channel/2.0.ts
The MIME type is set to video/mp2t for Transport Stream channels and application/x-mpegURL for HLS channels.

Client Configuration

Plex supports live TV through the Live TV & DVR section using either HDHR emulation (recommended) or a direct M3U import via a Plex plugin.
  1. Navigate to Settings > Live TV & DVR in Plex Web.
  2. Click Set Up Plex DVR and choose Network Tuner.
  3. Enter the ErsatzTV HDHR discovery address (see HDHomeRun).
  4. Alternatively, use a Plex IPTV plugin and provide the M3U URL:
    http://ersatztv.local:8409/iptv/channels.m3u
    
Replace ersatztv.local:8409 with the actual hostname or IP address and port where your ErsatzTV Legacy instance is running. The default port is 8409.

Build docs developers (and LLMs) love