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).
Example delivery paths
Section titled “Example delivery paths”- 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.
How a channel reaches a viewer
Section titled “How a channel reaches a viewer”Scroll, swipe, or click and drag to explore. Use the arrows to move, or fit the diagram above.
Drag to pan; zoom with the controls.
Channel import & auto-processing
Section titled “Channel import & auto-processing”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
Section titled “The stream proxy”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.
Scroll, swipe, or click and drag to explore. Use the arrows to move, or fit the diagram above.
| Responsibility | Detail |
|---|---|
| Multiplexing | One 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. |
| Transcoding | An FFmpeg manager remuxes or transcodes per a per-stream transcode decision. |
| SSRF protection | Upstream URLs are validated before they’re fetched. |
| Health & cleanup | A health monitor and orphan cleanup tear down streams with no viewers. |
| Clustering | Each 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.
Outbound proxy
Section titled “Outbound proxy”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:
| Traffic | Process | Mechanism |
|---|---|---|
| M3U/XMLTV import & refresh, channel logos, Xtream validation | web / worker | An undici ProxyAgent dispatcher attached to those (and only those) fetches. |
| Live stream + probe pulls | stream proxy | http_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.
Backup channels (failover)
Section titled “Backup channels (failover)”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.
Stream limits & contention
Section titled “Stream limits & contention”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.
- Setting up Live TV: turn the feature on and add your first source
- Codec & client support: what plays natively per client
- Playback decisions: the same transcode machinery, for on-demand video