Skip to content

Live TV

Lumastra organizes broadcasts from your own tuner and feeds licensed for third-party playback by a broadcaster or authorized TV provider. It supplies no channels or subscriptions. The architecture has two main parts: a dedicated stream proxy that shares an upstream connection between permitted viewers, and backup channels that switch between alternate feeds you are entitled to use.

Live TV is gated by FEATURE_LIVETV (off by default); when on, channels come from sources added in the admin UI (LIVETV_SOURCE defaults to standalone).

  • Home tuner: a compatible HDHomeRun supplies broadcasts you lawfully receive for private viewing at home. Lumastra imports the lineup and guide, and household viewers watching the same channel share one upstream pull.
  • Official broadcaster feed: a broadcaster-published feed for external players enters through an M3U playlist. Its channels appear in the same guide as your tuner channels; permitted HD, SD or alternate feeds of a station can form a backup group.
  • Your own live programme: a compatible source carries a production you own or are licensed to stream to the intended audience. Lumastra handles channel delivery while your production system supplies the live feed.

See Example setups for the source choices. Each path uses the same pipeline below; a managed network can route its source connections through its required outbound gateway.

Live TV processing and delivery

Scroll, swipe, or click and drag to explore. Use the arrows to move, or fit the diagram above.

Live TV processing and delivery Your tuner / approvedfeed HDHomeRun · M3U · Xtream Import & auto-process channels · EPG · backupgroups · quality tiers Lumastra app resolve channel · orderedURLs (primary + backups) ·access policy Stream Proxy one upstream per channel(multiplex) · FFmpeg · SSRFcheck Permitted live feed configured upstream ·permitted backups Permitted viewers HLS · shared upstreamconnection hand off · secret pull · failover HLS

Drag to pan; zoom with the controls.

Sources are added from the admin UI (LIVETV_SOURCE=standalone selects this mode): an approved M3U playlist, a provider-issued Xtream Codes account permitted for this use, or your own HDHomeRun tuner for broadcasts you are entitled to receive. Each is imported into channels, along with EPG (program guide) data that is matched to each channel. During import, Lumastra auto-processes the channel list to:

  • drop playlist section headers and use them as the group (and often the country) of the channels below them,
  • group alternate permitted feeds of one station (for example HD, FHD and mobile) into backup groups (see below),
  • detect quality tiers (SD / HD / FHD / …) within a group,
  • detect each channel’s country or region, and sub-group by it so regional variants aren’t mistaken for backups,
  • sort channels into genre categories (Sports, News, Movies, Kids and so on).

Configure Lineup then hides the channels outside the countries, categories and options an admin picks. The choices are stored with the source, so a re-import and a refresh apply them again. See Setting up Live TV.

Channels, groups, and visibility are then managed in Administering Lumastra → Live TV.

The stream proxy is a standalone process (start-proxy.sh → build/stream-proxy.js), kept isolated: it imports only Node built-ins and a small shared module, with no app framework or database access. It exists to do one job well: deliver the configured sources efficiently within the operator’s viewing and distribution permissions.

The diagram below shows how the containers relate: the web app handles channel selection and policy, while clients stream HLS directly from the proxy container.

Live TV container connections

Scroll, swipe, or click and drag to explore. Use the arrows to move, or fit the diagram above.

Live TV container connections Clients browser · Jellyfin /Streamyfin apps Lumastra app web container · channelresolve · access & streampolicy Stream Proxy separate container ·multiplex · FFmpeg Postgres channels · EPG · backupgroups Valkey proxy heartbeat · cluster ·cache Tuner / approvedprovider permitted feeds · failover select channel HLS playback hand off ·STREAM_PROXY_SECRET heartbeat pull · failover
ResponsibilityDetail
MultiplexingOne upstream connection per active channel, shared by its permitted viewers (reference-counted). This reduces duplicate network work; it does not grant extra viewing or redistribution rights.
TranscodingAn FFmpeg manager remuxes or transcodes per a per-stream transcode decision.
SSRF protectionUpstream URLs are validated before they’re fetched.
Health & cleanupA health monitor and orphan cleanup tear down streams with no viewers.
ClusteringEach proxy replica sends a heartbeat to Valkey, so it appears in the admin cluster overview.

The app talks to the proxy over an authenticated channel, configured with STREAM_PROXY_MODE, STREAM_PROXY_URL, and STREAM_PROXY_SECRET. Because it’s a separate role, the proxy can be scaled and deployed independently of the web tier.

Encoder behaviour is tuned with the LIVETV_PROXY_* variables (GPU, preset, CRF, target codec, transcode mode) and the passthrough flags. See Administering Lumastra.

On managed networks that require an outbound HTTP gateway, LIVETV_UPSTREAM_PROXY_URL sends all outbound Live TV traffic to the source through an HTTP CONNECT forward proxy. It’s applied in two places, because the work happens in two processes:

TrafficProcessMechanism
M3U/XMLTV import & refresh, channel logos, Xtream validationweb / workerAn undici ProxyAgent dispatcher attached to those (and only those) fetches.
Live stream + probe pullsstream proxyhttp_proxy / https_proxy injected into the FFmpeg / ffprobe child environment.

Both halves are fail-closed: when the variable is set there’s no direct fallback, so a dead proxy fails the request instead of bypassing the proxy. SSRF validation still runs first; when proxied, the connection is handed to the proxy (which resolves DNS), so the anti-DNS-rebinding IP-pinning step is skipped.

Because both processes need it, set LIVETV_UPSTREAM_PROXY_URL on the app, the worker and the stream-proxy container. Only HTTP CONNECT proxies are supported; for a SOCKS-only proxy, put a socks→http shim (e.g. gost or privoxy) in front.

Live TV streams can be unreliable, so a channel can belong to a backup group: a set of alternate feeds for the same station, each permitted for your use. Failover changes which configured feed is used; it does not unlock an unavailable subscription or add access to another region.

Viewers see a backup group as one channel: its primary feed when that is visible, else its best visible feed (a normal feed before a transcoded or mobile one, then the higher quality).

When a viewer starts a channel, the app builds an ordered list of stream URLs: the channel’s primary URL followed by the other URLs in its backup group. The proxy plays the first that works and fails over to the next if a stream drops or won’t start. With preferHighQuality, higher-quality tiers in the group are tried first.

Backup groups are detected automatically during import (by normalizing channel names, separating regional variants by country, and ranking quality tiers), and can be curated by an operator under Backup Groups on the Channels tab: make another feed the primary, show or hide single feeds, create a group from ungrouped channels, split a group, or remove members. A refresh keeps the primary an operator chose. If every source in the group fails, the client shows a stream-failure overlay.

Concurrent upstream channels are bounded per source. Configure those caps and viewer access within the tuner’s capacity and the broadcaster/provider’s permissions. The proxy counts upstream connections, so its cap alone is not a viewer, device or redistribution entitlement check. Access is restricted to the groups in LIVETV_GROUPS, and members of LIVETV_HIGH_PRIORITY_GROUPS can preempt a stream when capacity is contended (governed by LIVETV_KICK_POLICY). Idle viewers are reaped using LIVETV_VIEWER_TIMEOUT_SECONDS and LIVETV_GRACE_PERIOD_SECONDS.