Skip to content

Quick start

Four things need to be true. If any of them is not, sort it out now — every one of them produces a symptom later that looks like a fault in Castmux and is not.

  • A source URL you have already played. Open it in VLC on your laptop first. If VLC cannot play it, Castmux cannot either, and you will spend the next hour reading logs about a problem that lives at the origin.
  • A multicast group you are allowed to use. 239.10.0.1:1234 is a reasonable first choice: 239.0.0.0/8 is the administratively scoped range, so it will not collide with anything routed. Check with whoever runs the network that the group and port are free.
  • The appliance on the same layer 2 segment as the televisions. Multicast does not cross a router unless somebody has configured PIM, which is out of scope here. Same VLAN, same switch fabric.
  • Knowledge of which network interface faces the televisions. You will need the name — eth0, eth1, enp1s0 — not just “the one on the right”. Almost every failure at the end of this page is the multicast route pointing at the other one.

Create a directory on the host for the configuration, then start the container:

Terminal window
# A plain host directory, so config.yaml stays readable and backup-able
mkdir -p /opt/castmux/config
docker run -d --name castmux --restart unless-stopped \
--network host \
--cap-add NET_RAW \
--cap-add NET_ADMIN \
-v /opt/castmux/config:/config \
-e CASTMUX_WEB_USERNAME=admin \
-e CASTMUX_WEB_PASSWORD=choose-something-better \
castmux/castmux:latest

Each flag is load-bearing:

—network host

Multicast has to be emitted onto the real LAN. On a Docker bridge network the packets are produced perfectly and then go nowhere, because the bridge is a separate segment from the one the televisions are on. There is no counter anywhere that shows this; it simply looks like everything is working and nobody receives anything.

—cap-add NET_RAW

Permits packet capture. Castmux uses libpcap for two things: detecting which clients have actually joined a group, which is what drives on-demand streaming, and measuring the real bitrate leaving the interface. Without it both features are blind.

—cap-add NET_ADMIN

Permits inspection and management of the multicast route. Castmux checks the routing table from outside the streaming process, because a stream sent to an unroutable destination reports success from inside it.

-v /opt/castmux/config:/config

The single YAML file lives here as /config/config.yaml. Bind-mount a host directory rather than using a named volume, so that when the web interface is unreachable you can still read and edit the configuration with an ordinary text editor.

Browse to http://<appliance>:8080 and sign in with the credentials you set in the environment. Port 8080 is the default and can be changed with --port.

The footer should show a version string, CPU and memory figures, and per-interface network rates. If it does, the process is healthy and you can start adding channels.

On the UDP channels page, choose Add channel and fill in:

FieldWhat to enter for this first test
NameAnything recognisable. It is used in the log view and, on the pass-through engine, as the service name in the transport stream.
Source typeHLS.
Source URLThe URL you played in VLC. A master playlist is fine.
Destination address239.10.0.1
Destination port1234
EngineLeave the default, the pass-through engine. If the source turns out to be fMP4/CMAF rather than MPEG-TS segments, switch to the remux engine — see Streaming engines.
Force always-onTick it. See the note below.

Save the channel and wait a few seconds. A pass-through channel typically produces its first packet about two seconds after starting; the remux engine takes around four and a half.

On the channel card, look at the UDP bitrate tile. It must be non-zero.

This is the tile that matters, and it is worth understanding why. The other metrics — frame rate, speed, source bitrate — come from the engine reporting on itself. An engine can be entirely convinced it is streaming while nothing reaches the network. UDP bitrate is measured with libpcap off the interface itself: it counts packets that genuinely left. It is the only signal that cannot be produced by a process that is lying to you, and it is also the only one that works identically for both engines.

From a machine on the same segment as the televisions:

Terminal window
ffplay udp://@239.10.0.1:1234
# or, with VLC
vlc udp://@239.10.0.1:1234

The @ is not decoration. Without it the client tries to send to the group rather than join it, and you will see nothing while the appliance looks perfectly healthy.

With the channel confirmed working, edit it and untick force always-on. The channel will stop shortly after the last viewer leaves and start again when one joins. Expect the first picture roughly two seconds after the join on the pass-through engine.

A television that has been switched to a different channel does not always announce its departure immediately, so there is a short linger before Castmux stops the stream. This is intentional: stopping and restarting on every channel hop would be worse for the viewer than running a few seconds longer than strictly necessary.

One caveat while testing: the browser preview counts as a viewer. An on-demand channel with a preview open will stay up, which is convenient and occasionally confusing.

[

📡

Deliver the same channels over the coaxial network already in the building.

](/docs/dvb-c/)[

👥

How viewer detection works, and what happens when it cannot see anything.

](/docs/on-demand/)[

📊

Which numbers are measured, which are reported, and which to trust.

](/docs/monitoring/)

Before adding the rest of the channels, read Requirements. Capacity on a small appliance is limited by memory, and memory runs out abruptly rather than gradually.