zwfm-encoder: The Raspberry Pi That Acts Like a Broadcast Encoder Rack
A single Go binary captures studio audio, fans it out to multiple SRT destinations, watches for silence, and keeps radio engineers in the loop with real-time monitoring and alerts.
FM stereo encoder with RDS
- zwfm-encoder turns a Raspberry Pi into a broadcast appliance by treating capture, fan-out, monitoring, and alerting as one system.
- Its main trick is a Distributor that copies one live PCM source into multiple encoder workers without making the Pi feel like a lab experiment.
- Silence detection is stateful, so the system avoids alert flapping and produces failures engineers can act on.
- The embedded web UI is not decoration, because it exposes the live machine in the same binary that runs the machine.
The first thing that matters here is not encoding. It is coordination. `zwfm-encoder` takes a hardware audio feed from a small Linux box and makes it behave like an appliance a station can trust, with one-to-many output, live telemetry, and alerting baked into the same binary.
That is a sharper idea than “Go app plus FFmpeg.” The repo uses ALSA capture, FFmpeg workers, WebSockets, silence detection, and systemd in a way that reads less like a toolbox and more like a purpose-built broadcast rack condensed onto a Raspberry Pi.
The Pi stops being a gadget
The repository is aimed at a very specific operational problem: keep radio audio moving from the studio to multiple live destinations without adding a pile of moving parts. The README frames it as audio streaming software for ZuidWest FM and Radio Rucphen, and the implementation leans into that brief with a single executable, an embedded web UI, and service files that assume always-on use.
That matters because the software is not trying to abstract away hardware reality. It embraces it. ALSA, `arecord`, HiFiBerry-style audio capture, and low-latency Linux plumbing are treated as normal parts of the system, not inconveniences to be hidden behind a container.
One audio feed, many live destinations
This is the project’s most interesting mechanism. The repository’s internal model is simple and strong: capture PCM once, feed it into a Distributor, and write those bytes into multiple FFmpeg processes, one per destination. The result is efficient fan-out without re-reading the hardware source for every output.
That architecture does two useful things at once. It keeps the capture side lean, and it makes output management explicit. If one stream needs different codec settings or reconnect behavior, that complexity lives at the edge, not in the audio source itself.
For a station, that means a single Pi can act like a distribution point instead of a single-purpose pipe. For an engineer, it means every live destination becomes an observable worker with its own status, while the input stays stable and boring, which is exactly what broadcast hardware should be.
How the pipeline hangs together
audio input -> capture process -> Distributor -> FFmpeg worker A -> SRT destination A
\-> FFmpeg worker B -> SRT destination B
\-> FFmpeg worker C -> SRT destination C
side channels:
- VU metering from the same stream
- silence detection from sampled levels
- web UI subscribes over WebSockets
- alerting subscribes to silence and recovery events
Silence is a state machine, not a warning light
The silence detector is where the project stops feeling like a streaming utility and starts feeling like broadcast engineering. A raw threshold would flap whenever the room gets quiet between songs, or when speech pauses long enough to matter but not long enough to mean failure.
Instead, the code uses hysteresis. Silence has to persist for a configured duration before it becomes an event, and audio has to recover for a separate window before the alert clears. That gap between trigger and recovery is the difference between noise and signal.
The silence dump feature tightens the loop further. When the station goes quiet, the system can preserve the audio leading up to the failure, which turns an alarm into evidence. That is a small feature with a big operational payoff.
The web UI is part of the machine
The embedded UI is not a dashboard tacked on for convenience. It is the operational surface of the appliance. The repository serves configuration, live meters, update notifications, and WebSocket-driven feedback from inside the same binary that handles capture and encoding.
That choice fits the rest of the design. If the Pi is acting as station infrastructure, then the operator needs a direct way to see what the box sees. A headless daemon is fine until something sounds wrong. Then the live VU meter, the silence state, and the status of each destination become the product.
The frontend stack is deliberately light. That keeps the machine easy to reason about and easier to deploy. It also preserves the article’s central point: the web layer is there to expose a broadcast appliance, not to redefine it.
Why this beats the obvious alternatives
`zwfm-encoder` is not trying to outgrow its niche. It sits in a useful middle ground between commercial broadcast suites, general SDR frameworks, and Raspberry Pi transmitter hacks. That focus is the advantage.
| Project | What it is good at | What it is not trying to be |
|---|---|---|
| zwfm-encoder | Open-source broadcast appliance on a Pi with fan-out, monitoring, and silence alerting | A giant all-purpose broadcast suite or a general SDR lab |
| Stereo Tool | Deep commercial processing and mature FM tooling | A minimal, Pi-focused operational encoder for a narrow station workflow |
| GnuRadio | Flexible signal processing and SDR experimentation | A ready-made appliance that operators can run with little assembly |
| rpitx / PiFmAdv | Direct Raspberry Pi transmission and hardware-specific experimentation | A multi-destination, monitored streaming control plane |
That comparison is the real story. The repo wins by being intentionally smaller in scope and larger in operational usefulness. It optimizes for the thing radio stations actually need: dependable audio in, dependable audio out, and fast visibility when something breaks.
The broader lesson is that software-defined broadcasting does not have to feel abstract. This project shows the opposite. The winning shape is often the one that respects the hardware, keeps the control plane compact, and makes failure visible without making deployment fragile.
What this repo says about modern broadcast engineering
`zwfm-encoder` is interesting because it collapses a lot of broadcast discipline into one small system. It captures once, distributes many times, watches for silence, and pushes meaningful state into the browser and alert channels. That is what a mature appliance does.
It also shows why open source matters in narrow infrastructure categories. A team can build exactly what its stations need instead of buying a large platform and adapting around it. In that sense, the repo is less a curiosity than a template for how edge infrastructure gets productized when the requirements are specific and the tolerance for drama is low.