I had a couple of large IPTV playlists and a Jellyfin server, and I wanted the channels to show up as proper Live TV, with a guide, not a flat M3U dumped into a player. Dispatcharr bridges the gap.

What it does

It ingests M3U playlists and XMLTV guide data, lets you dedupe and organize channels, and exposes an HDHomeRun-style tuner plus an XMLTV guide that Jellyfin consumes natively. It also proxies the streams, so clients hit one stable endpoint.

The HDHomeRun emulation is the clever bit and worth understanding, because it is why this works with no Jellyfin plugin. A real HDHomeRun is a network tuner that answers a handful of JSON endpoints: one describing the device, one listing the channel lineup with a stream URL per channel, one reporting scan status. Jellyfin has spoken that natively for years. Dispatcharr simply answers those endpoints itself, hands back its own proxy URLs as the streams, and Jellyfin adds it as a tuner without ever knowing there is no hardware. Pair that with the XMLTV URL as the guide source and you have Live TV with a proper EPG.

Behind a VPN

IPTV fetching is best done through a VPN, so I run Dispatcharr sharing a gluetun container's network namespace. Every upstream request egresses through the tunnel, while Jellyfin reaches it on the internal network.

Sharing a namespace has a consequence that catches everyone once: the container no longer has its own network stack, so it cannot publish ports and it cannot be addressed by its own service name. Every port Dispatcharr listens on has to be declared on the gluetun service, and anything pointing at Dispatcharr, including Jellyfin's tuner URL and the Traefik label set, has to point at gluetun instead. Get that wrong and the app is running perfectly and completely unreachable.

The gotchas

  • Streams vs Channels. Importing an M3U creates streams; the lineup only shows channels. You generate channels from streams.
  • Dedup early. Around 2,000 raw streams collapsed to roughly 550 real channels once I merged duplicate sources into failover groups. That merge does more than tidy: a failover group means when the first source dies mid-stream, the proxy moves to the next one rather than handing your client a dead socket.
  • Guide matching is its own chore. The channel IDs in an M3U and the ones in an XMLTV file rarely agree, so a channel plays fine and shows no programme data until you map the two by hand.
  • Free IPTV is flaky. Plenty of channels are just dead upstream. That's the source, not your setup.

End result: live TV with a guide, right inside Jellyfin.