Configuration reference
Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.
The file
Section titled “The file”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.
Command-line flags
Section titled “Command-line flags”—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.
Environment variables
Section titled “Environment variables”CASTMUX_WEB_USERNAME
Username for the web interface and API.
CASTMUX_WEB_PASSWORD
Password for the web interface and API.
A complete annotated example
Section titled “A complete annotated example”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.
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 IDGlobal settings
Section titled “Global settings”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.
| Key | Default | Purpose |
|---|---|---|
| Engines and output | ||
| default_engine | tsduck | Which 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_device | empty | Source 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_seconds | 3 | Gap 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 | -1 | Which 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_size | true | Force 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_latency | true | Derive 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_enabled | true | Master switch for viewer-driven streaming. With it off, every channel marked active runs continuously regardless of whether anything is watching. |
| on_demand_fail_open | true | Keep 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_query | true | Send 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_seconds | 90 | How 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_seconds | 30 | How 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_seconds | 30 | Interval 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_interfaces | all with an address | Which 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_listeners | true | Keep 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_hosts | empty list | Extra 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_name | empty | Site identification. Used as a label on exported metrics so a fleet of appliances can be told apart in one dashboard. |
| re_seller | empty | The partner or installer responsible for the site. Also a metric label, for filtering a dashboard down to one reseller's estate. |
Engine parameters
Section titled “Engine parameters”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.
Per-channel settings
Section titled “Per-channel settings”Each entry under streams is one channel: one source, one destination, one set of supervision rules.
| Key | Default | Purpose |
|---|---|---|
| Identity | ||
| id | assigned | Numeric 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. |
| name | required | Display 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. |
| description | empty | Free text for the operator. Not transmitted anywhere. |
| active | true | Whether 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.type | hls | One 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.url | required | The 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.address | required | IPv4 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.port | required | UDP 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_on | false | Run 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. |
| engine | inherits | Override 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_profile | empty | One 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_kbps | 500 | The 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_ms | 0 | Restart 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. |
DVB-C multiplex settings
Section titled “DVB-C multiplex settings”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.
| Key | Value | Purpose |
|---|---|---|
| Identity | ||
| id | assigned | Numeric identifier for the multiplex, used in API paths. |
| name | required | Operator-facing label for the multiplex. Not transmitted. |
| device | index or path | Which modulator hardware this multiplex is transmitted on, identified by index or device path depending on the card fitted. One multiplex per device. |
| RF parameters | ||
| frequency | Hz | Centre 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. |
| qam | 16 / 32 / 64 / 128 / 256 | Modulation 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_rate | ksym/s | Symbol 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_id | integer | Network identifier signalled to receivers. Keep it consistent across every multiplex at one site, so sets treat them as one network rather than several. |
| ts_id | integer | Transport 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_name | text | Network name signalled to receivers. This is the text a guest sees during tuning, so it is normally the name of the building. |
| active | true | Whether 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_ids | ordered list | The 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. |
Backing up and restoring
Section titled “Backing up and restoring”The backup is the file. Copy it somewhere else:
cp /config/config.yaml /backup/seaview-court-$(date +%F).yamlTo 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:
# on the appliancesystemctl stop castmuxcp /backup/seaview-court-2026-04-11.yaml /config/config.yamlsystemctl start castmuxBecause 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.