Skip to content

Channels and sources

One source plus one destination. The source is a URL Castmux pulls from; the destination is an IPv4 address and port it pushes MPEG-TS to. Everything else on the channel — engine, resolution profile, on-demand behaviour, expected bitrate — modifies how that one pipe is run, not what it carries.

Channels are independent. Each one is supervised on its own, restarted on its own, and measured on its own, so a dead origin on one channel does not disturb the others.

Over IP, four source types are supported today: HLS, SRT, RTMP and plain MPEG-TS, the last either over UDP multicast or over HTTP. The table below shows what else is supported and what is planned.

SourceStatusNotes
HLSSupportedMaster playlist or a single media playlist. See resolution profiles for how a rung is chosen.
SRTSupportedCaller mode, configured entirely from the URL. Latency is derived automatically.
RTMPSupportedRemux engine only. Typically a local encoder pushing into the appliance's network.
UDP multicast (MPEG-TS)SupportedRe-receiving an existing multicast feed, such as another headend's output. Source type mpegts with a udp:// URL. See MPEG-TS sources.
HTTP MPEG-TSSupportedA plain transport stream over HTTP, without a playlist. Source type mpegts with an http:// or https:// URL.
RTP multicastRoadmapTransport stream wrapped in RTP. Only plain MPEG-TS over UDP is read today. roadmap
RTSP camerasRoadmapFor lobby, chapel and CCTV feeds. roadmap
DVB-S/S2 tuner inputRoadmapSatellite services taken off air rather than off IP. Not available today: there is no tuner input of any kind, so do not buy a tuner card for it. roadmap
DVB-T tuner inputRoadmapTerrestrial services taken off air. roadmap
DVB-C tuner inputRoadmapTaking services off a cable network rather than off IP. roadmap

Give the channel a master playlist URL. Castmux reads the ladder it advertises and selects one variant to hand to the engine, according to the channel’s resolution profile. With no profile set — the default, and what every pre-existing channel has — the master playlist is passed through unchanged and the origin’s ordering decides.

The starting position at the live edge is configurable. Starting further back in the playlist buys resilience against an origin that publishes segments irregularly, at the cost of a longer delay behind live and a slower first picture after a channel change.

SRT channels run in caller mode: Castmux connects out to the origin. The whole configuration lives in the URL, and the following query parameters are translated to the engine:

streamid, passphrase, transtype, latency, rcvlatency, peerlatency, rcvbuf, sndbuf, maxbw, pbkeylen, payloadsize, tlpktdrop, linger.

Terminal window
srt://origin.example.net:9000?streamid=play/news&passphrase=••••••••&transtype=live

Castmux measures the round-trip time to the origin host and sets the SRT latency budget to four times the measured RTT, with a floor of 200 ms and a ceiling of 4000 ms. Any latency value present in the URL is replaced.

This exists because the usual default of 120 ms is wrong on any link with real jitter, and because the resulting failure is one nobody attributes to latency. An undersized budget does not break the channel; it produces intermittent artefacting — a few seconds of blocking every so often, at no predictable interval, on a channel whose dashboard is entirely green. Sites chase the encoder, the switch and the television for weeks before anyone suspects a transport setting that was copied from another installation with a shorter path.

The multiplier is the conventional SRT recommendation: a receiver must be able to wait out a retransmission, which costs a full round trip, with room for a second attempt. The floor stops a very short link from getting a budget too small to absorb any loss at all; the ceiling stops one bad measurement from adding seconds of delay to a channel.

If you would rather pin the value yourself, turn the behaviour off with overwrite_srt_latency: false in the global configuration, and the latency in the URL is left alone.

RTMP is supported on the remux engine, and is normally used for a local encoder on the same network as the appliance rather than for a feed arriving over the internet.

Source type mpegts takes a transport stream that arrives as-is, with no playlist and no container around it. The URL scheme decides the transport:

# a multicast group, e.g. another headend's output
source:
type: mpegts
url: udp://239.20.0.5:1234?localaddr=192.168.10.4
# a continuous transport stream over HTTP
source:
type: mpegts
url: https://origin.example.net/news/mpegts

Over UDP, the channel joins the group and reads transport-stream datagrams exactly as they arrive. The URL takes three optional parameters, spelled the same for both engines:

  • localaddr is the local address to receive the group on. Set it on an appliance with several interfaces, so the join goes out of the one facing the sender.
  • sources restricts reception to one sender, for source-specific multicast.
  • buffer_size is the kernel receive buffer in bytes. The default is generous, so that a scheduling stall does not drop datagrams.

Over HTTP, the channel reads a single, unending response, such as a streaming server’s /mpegts output. If the origin closes the connection, the channel restarts, as it would for any other source failure.

A few things differ from the other source types:

  • Resolution profiles do not apply. A transport stream carries one fixed rendition, and there is no ladder to choose from.
  • A channel cannot receive its own output. A udp:// source equal to the channel’s own destination address and port is refused when the channel is saved. The engine would otherwise ingest what it had just sent, forever, while the bitrate meter reported a healthy channel. Reading a different channel’s group is allowed, and is a deliberate way of chaining one channel into another.
  • Only plain transport stream is read. A multicast feed wrapped in RTP is not supported yet.

One IPv4 address and one port. The address may be a multicast group, which is the normal case for television distribution, or a unicast address for a single receiver or a test.

For multicast, use the administratively scoped range 239.0.0.0/8. It is reserved for exactly this purpose — private, organisation-local use — so nothing you choose inside it can collide with a well-known assignment.

One destination per channel today. Sending the same channel to several groups — for example one multicast group and one unicast probe — requires a second channel with the same source URL. Multiple destinations per channel is roadmap.

active

Whether the channel is under supervision at all. An inactive channel keeps its configuration but is never started and produces no metrics.

force_always_on

Keep the channel running whether or not anybody is watching. The default is off, which means on-demand: the channel runs only while a viewer is detected on its group. Set this for channels that must never take the cold-start delay on a channel change. See On-demand streaming.

engine

Override the global engine choice for this channel. Empty means inherit. See Streaming engines.

resolution_profile

Which rung of an HLS ladder to take. Empty means take the master playlist unchanged. Ignored for SRT and RTMP, which carry no ladder. See Resolution profiles.

min_output_kbps

The output bitrate below which this channel is treated as not producing anything, and therefore as needing a restart.

The channel name is not only a label in the interface. It becomes the DVB service name carried in the SDT, which is what a television displays in its channel list, and it is the label attached to every metric the channel produces.

That second consequence is the one that catches people out: renaming a channel renames its metric series. Historical data does not follow the rename, so a dashboard or alert keyed on the old name goes quiet, and a graph of the channel appears to start from nothing. Decide on names before you build dashboards, and treat a rename as an operation with a downstream cost rather than a cosmetic edit.

Channels are identified by an integer id. That id appears in the configuration file, in the HTTP API, and anywhere a channel is referenced from outside.

Ids are currently reused after a delete. If you delete channel 7 and then add a new channel, the new one can be given id 7. It is a different channel in every respect an operator cares about — different name, different source, different destination — but everything keyed on the id sees continuity where there is none.

The practical consequences are worth knowing before you rely on ids:

  • Anything storing per-channel state against the id — an external scheduler, a saved API call, a bookmark in the interface — can end up pointed at the wrong channel after a delete-and-add cycle.
  • Browsers restore form control state on a soft reload independently of what the server rendered, so a newly created channel can briefly display a setting inherited from the deleted channel that held its id. What the badge beside the control says is the truth.
  • On DVB-C, service identity is derived from position in a multiplex rather than from the channel id, so reordering or removing a channel moves the services around it.

Stable, non-reused identifiers and pinned service identity are roadmap. Until then, the safe rule is: an id identifies a slot, and a name identifies a channel.

A licence can carry a channel line-up as well as a permission to stream. On each licence check-in, the appliance compares that line-up with its own channels. Every channel records who owns it (managed_by in the configuration file), and two rules follow from that:

  • A channel the licence supplied belongs to the licence server. On each check-in, its source, destination, resolution profile, always-on mode and on/off state are updated to whatever the server sends, so a channel that moves is corrected without a site visit. If the server stops listing it, it is removed. The web interface marks these channels and will not edit or delete them, since the next check-in would undo the change.
  • A channel you added yourself is never touched. The server never changes or removes it, even if the line-up contains a channel of the same name. The one exception is a channel you have switched off: it is running nothing, so a licensed channel with the same name or destination may take it over. This is what makes migrating an older appliance work without deleting its old channels first.

The licence also sets a maximum number of channels that may run at once. A licensed channel beyond that limit is added switched off rather than dropped, so raising the plan later is a matter of switching it on, not re-entering it. The limit applies to channels you add yourself too: a channel added when the limit is already reached arrives switched off, with a message saying why.

A licensed channel that would send to a group another running channel already uses is refused rather than allowed to collide, and so is one the server sent without a source URL or destination. Refusals are shown in the web interface as well as logged, so “the server sent nothing” can be told apart from “the appliance refused what it sent”.

Two channels in config.yaml — one HLS with a resolution profile, one SRT with a lowered bitrate floor because it is a radio service:

streams:
- id: 1
name: BBC One
description: Reception and lounge
active: true
source:
type: hls
url: https://origin.example.net/bbcone/master.m3u8
destination:
address: 239.1.1.10
port: 5000
# Televisions here are 720p panels; the origin lists 1080p first.
resolution_profile: hd
force_always_on: true
- id: 2
name: Classic FM
description: Audio only
active: true
source:
type: srt
url: srt://origin.example.net:9000?streamid=play/classicfm&transtype=live
destination:
address: 239.1.1.11
port: 5000
# Radio: well under the video-oriented global floor, so lower it or the
# channel is treated as silent and restarted forever.
min_output_kbps: 64
force_always_on: true

No latency is given on the SRT URL because Castmux derives it from the measured round trip. No engine is given on either channel, so both inherit the global default.