Zum Inhalt springen

Configuration reference

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

The configuration is deliberately a plain, readable text file rather than a database. It can be backed up with cp, diffed against last week’s copy, committed to version control, and edited by hand over SSH when the web interface is unreachable — which is exactly when you most need to change something. There is no separate state store to keep in step with it.

Castmux rewrites the file whenever a change is made in the web interface, so hand edits and UI edits are the same operation on the same file. Editing by hand while the service is running risks having your change overwritten by the next UI action; stop the service, edit, start it again.

On upgrade, keys added by a newer release are backfilled with their defaults automatically, so an older file continues to work. A .pre-migration copy of the original is written before anything is changed, which is the file to restore if a migration turns out to disagree with you.

—config

Path to the configuration file. Defaults to config.yaml in the working directory. Container deployments pass an explicit path into a mounted volume, normally /config/config.yaml.

—port

TCP port for the web interface and the HTTP API. Defaults to 8080. The API is not on a separate port; there is one listener.

-debug

Verbose logging, including full engine command lines and per-restart detail. Useful when diagnosing a channel that will not start. It is noisy; do not leave it on permanently on an appliance with a small log partition.

CASTMUX_WEB_USERNAME

Username for the web interface and API.

CASTMUX_WEB_PASSWORD

Password for the web interface and API.

A working file for a small site: two channels, one from HLS and one from SRT, both carried on one DVB-C multiplex as well as on multicast.

/config/config.yaml
global:
default_engine: tsduck # pass-through unless a channel overrides it
udp_device: 192.168.10.4 # source address, NOT the egress interface
startup_stagger_seconds: 3
hls_live_start_index: -1
on_demand_enabled: true
on_demand_fail_open: true # viewer detection broken => keep streaming
igmp_active_query: true
igmp_grace_seconds: 90
igmp_linger_seconds: 30
igmp_query_interval_seconds: 30
igmp_interfaces:
- eth0
- eth1
enable_dummy_listeners: true
overwrite_srt_latency: true
overwrite_pkt_size: true
ping_hosts:
- 192.168.10.1 # the site gateway
- origin.example.net # the content provider
hotel_name: Seaview Court
re_seller: Northern AV
streams:
- id: 1
name: Example One # also the DVB service name and metric label
description: Main lounge line-up
active: true
source:
type: hls
url: https://origin.example.net/one/master.m3u8
destination:
address: 239.10.0.1
port: 5000
force_always_on: false # on-demand: runs when somebody joins
engine: tsduck
resolution_profile: hd # closest rung wins; not an exact-match filter
min_output_kbps: 500
pdt_shift_ms: 0 # 0 disables the PDT drift restart
- id: 2
name: Example Two
description: Contribution feed from the studio
active: true
source:
type: srt
url: srt://feed.example.net:9001?streamid=two
destination:
address: 239.10.0.2
port: 5000
force_always_on: true # always on air, viewers or not
engine: tsduck
resolution_profile: "" # SRT has no ladder; nothing to select
min_output_kbps: 500
dvb_muxes:
- id: 1
name: Mux A
device: 0 # modulator device index
frequency: 474000000 # Hz, not MHz
qam: 256
symbol_rate: 6900
network_id: 1
ts_id: 1
network_name: Seaview Court
active: true
channel_ids: [1, 2] # order decides slot, PID block, service ID

Everything under global applies to every channel unless the channel overrides it. A change made through the web interface is applied to running channels without a restart, so these are live settings, not boot-time ones.

KeyDefaultPurpose
Engines and output
default_enginetsduckWhich engine channels use when they do not name one themselves. The pass-through engine preserves original PIDs, audio tracks and language descriptors; the remux engine rewrites them, which some downstream equipment requires. See Streaming engines.
udp_deviceemptySource address for outbound UDP. Note carefully that this binds the source address and does not choose the egress interface — the kernel still consults the routing table to decide which port the packets leave by. If multicast is going out of the wrong interface, fix the route, not this.
startup_stagger_seconds3Gap between channel starts at boot. Every channel opens its source at once otherwise, and eight simultaneous HLS starts on a 100 Mbit uplink saturate it during the initial segment burst, so all eight fail rather than one. Set 0 to disable if your uplink genuinely does not care.
hls_live_start_index-1Which segment of the live playlist to begin at, counted from the live edge. -1 is the last segment. Closer to the edge means lower latency and less buffer to absorb origin jitter; further back is more tolerant and further behind live.
overwrite_pkt_sizetrueForce full 1316-byte UDP datagrams on HLS channels — seven transport packets per datagram, which is what set-top boxes expect. Left alone, some sources produce short datagrams and waste a noticeable share of the wire.
overwrite_srt_latencytrueDerive the SRT latency setting from the measured round-trip time to the sender rather than using a fixed figure. A hand-set latency that was right for one path is usually wrong for the next site.
On-demand and IGMP
on_demand_enabledtrueMaster switch for viewer-driven streaming. With it off, every channel marked active runs continuously regardless of whether anything is watching.
on_demand_fail_opentrueKeep channels streaming when viewer detection is unavailable — capture cannot start, the interface disappears, the watcher dies. Leave this on. The failure mode with it off is a building of black screens caused by a monitoring component, which is worse in every way than a little wasted bandwidth.
igmp_active_querytrueSend our own IGMP general queries. Clients report unsolicited only at the moment they join and then stay silent until asked, so without querying a restart loses all knowledge of existing viewers. Turn this off only if the segment already has a real querier; two queriers on one segment is untidy but not fatal.
igmp_grace_seconds90How long a viewer may stay silent before it is treated as gone. Must comfortably exceed igmp_query_interval_seconds, or a single lost report evicts a viewer who is still watching.
igmp_linger_seconds30How long a channel keeps running after the last viewer leaves. This is what makes channel surfing bearable: returning within the linger window is instant instead of paying a cold start.
igmp_query_interval_seconds30Interval between general queries. Lower means faster detection of a set that has been switched off at the wall, at the cost of more control traffic.
igmp_interfacesall with an addressWhich interfaces to capture membership on. The default covers every interface that has an address configured. Name them explicitly on a box with several NICs where only one faces the televisions.
enable_dummy_listenerstrueKeep a local consumer attached to each group. Without one, packets sent to a group nobody has joined accumulate against socket buffers and eventually cause overruns that look like source faults.
Monitoring and site identity
ping_hostsempty listExtra hosts for the reachability monitor, on top of what is derived from the configuration. The useful entries are the site gateway and the content origin: when a channel fails, the first question is whether the site lost the internet or the provider lost the channel, and this answers it.
hotel_nameemptySite identification. Used as a label on exported metrics so a fleet of appliances can be told apart in one dashboard.
re_selleremptyThe partner or installer responsible for the site. Also a metric label, for filtering a dashboard down to one reseller's estate.

The file also contains low-level argument strings handed to the underlying streaming engines. They are read from the configuration but are deliberately not exposed in the web interface, and they are not documented key by key here.

The reason is blast radius. These strings apply to every channel that uses the engine, and an engine that refuses to start because of one malformed argument takes the whole line-up off air at once, not one channel. A field that can do that to a building should not be one keystroke away from an operator who is trying to rename a channel. The per-channel settings below cover what sites actually need to change.

Each entry under streams is one channel: one source, one destination, one set of supervision rules.

KeyDefaultPurpose
Identity
idassignedNumeric identifier, unique within the file. It is the identifier used in API paths and in channel_ids on a multiplex. Identifiers are reused after a delete, so do not treat one as a permanent handle for an external system.
namerequiredDisplay name. This is not cosmetic: it also becomes the DVB service name shown in the television's channel list, and the label attached to this channel's exported metrics. Renaming a channel changes what viewers see and what your dashboard groups by.
descriptionemptyFree text for the operator. Not transmitted anywhere.
activetrueWhether the channel is configured to run at all. An inactive channel is kept in the file but never started, which is how you retire a channel without losing its settings.
Source
source.typehlsOne of hls, srt or rtmp. The type governs more than the fetch: only HLS has a ladder, so resolution profiles apply to HLS alone.
source.urlrequiredThe origin URL. For HLS this should normally be the master playlist, not a variant — give Castmux the ladder and let the resolution profile choose, so the channel survives the origin reorganising its rungs.
Destination
destination.addressrequiredIPv4 destination. Use the administratively scoped multicast range 239.0.0.0/8 for distribution inside a building. Unicast is accepted for point-to-point links.
destination.portrequiredUDP destination port. Distinct groups may share a port; the same group and port used by two channels is a duplicate sender and produces unwatchable pictures on both.
Behaviour
force_always_onfalseRun this channel continuously, ignoring viewer detection. Use it for a channel that must be instantly available, or one carried on a DVB-C multiplex where there is no IGMP membership to observe in the first place.
engineinheritsOverride default_engine for this channel. The usual reason is a source the pass-through engine cannot read, or one downstream device that insists on remuxed output.
resolution_profileemptyOne of 4k, fullhd, hd, sd, mobile, or empty for the origin's own choice. Selection is closest height wins, ties going to the higher bitrate — a channel that streams 480p when nobody publishes 576p is better than a channel that refuses to start. The choice is applied per start and never written back to this file. See Resolution profiles.
Supervision — configuration file only
min_output_kbps500The floor below which this channel is considered not to be producing, and is restarted. Lower it for radio and other audio-only services: a 128 kbps radio channel measured against a video-sized threshold is permanently judged silent and restarted in a loop. Not exposed in the web interface.
pdt_shift_ms0Restart threshold for programme-date-time drift, in milliseconds: if the source's declared timeline jumps by more than this, the channel is restarted rather than left to run on a broken clock. 0 disables the check, which is the default because a legitimately re-stamping origin would otherwise cause restarts. Not exposed in the web interface.

Each entry under dvb_muxes is one RF carrier: a set of channels assembled into a single transport stream and modulated onto the coaxial network. See DVB-C multiplexing for how to choose the RF parameters.

KeyValuePurpose
Identity
idassignedNumeric identifier for the multiplex, used in API paths.
namerequiredOperator-facing label for the multiplex. Not transmitted.
deviceindex or pathWhich modulator hardware this multiplex is transmitted on, identified by index or device path depending on the card fitted. One multiplex per device.
RF parameters
frequencyHzCentre frequency of the carrier, in hertz, not megahertz. 474000000, not 474. Must match the plan for the building's existing cable network and must not collide with a carrier already present on it.
qam16 / 32 / 64 / 128 / 256Modulation order. Higher carries more bitrate in the same 8 MHz and tolerates less noise. On healthy in-building coax 256-QAM is normal; drop it if the cabling is old, heavily split or of unknown quality.
symbol_rateksym/sSymbol rate of the carrier. With the modulation order this fixes the total bitrate available to every service in the multiplex, so it is the number that decides how many channels fit.
Signalling
network_idintegerNetwork identifier signalled to receivers. Keep it consistent across every multiplex at one site, so sets treat them as one network rather than several.
ts_idintegerTransport stream identifier. Must be unique among the multiplexes at the site; duplicates cause sets to overwrite one line-up with another during a scan.
network_nametextNetwork name signalled to receivers. This is the text a guest sees during tuning, so it is normally the name of the building.
activetrueWhether the multiplex is transmitted. Setting it false stops the carrier; televisions will show the whole line-up as missing, not as one dead channel.
Contents
channel_idsordered listThe channels carried, by id. The order is significant. Position in this list determines the slot, the PID block allocated to the service, and the service identifier. Reordering the list therefore re-identifies services, and televisions that have already scanned may need a re-tune to agree with you again. Add to the end where you can.

The backup is the file. Copy it somewhere else:

Terminal window
cp /config/config.yaml /backup/seaview-court-$(date +%F).yaml

To restore, stop the appliance, put the file back, and start it again. Replacing the file under a running service does not work, because the running service will write its own copy over yours at the next change:

Terminal window
# on the appliance
systemctl stop castmux
cp /backup/seaview-court-2026-04-11.yaml /config/config.yaml
systemctl start castmux

Because the file is plain YAML, the same copy also serves as the starting point for a second site: change the addresses, the names and the RF parameters, and the rest carries over. That is a manual process today.

One-click export and import from the web interface, and cloning a configuration across a fleet of sites, are roadmap.