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.

8 min read • View on GitHub • More from oszuidwest

A Raspberry Pi sits on a studio desk beside an audio interface, with one captured signal splitting into multiple routed paths toward live destination nodes. Small meters and status lights suggest a machine built for unattended broadcast work rather than a hobby setup. The scene explains how a single input can become a managed distribution system.
One hardware feed, many live outputs. The repo turns a small Pi into something closer to a compact encoder rack than a tinkerer board.

FM stereo encoder with RDS

oszuidwest, Project Owner/Maintainer · oszuidwest/zwfm-encoder on GitHub
Key Takeaways

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.

A hedcut-style portrait of the oszuidwest GitHub account, rendered from the verified GitHub avatar. It gives the article a recognizable source anchor without inventing a personal headshot.

One audio feed, many live destinations

The heart of the repo is a fan-out engine. One captured stream is distributed to many live outputs, while monitoring and alerting ride alongside it.

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

A close-up mechanical relay with two doors, one for silence and one for recovery, shown as a calibrated mechanism rather than a flashing alarm. A small cassette-like diagnostic attachment suggests that the system can preserve evidence of what happened before the alert. The image explains why hysteresis makes silence detection trustworthy.
The repo treats silence as a stateful condition. That avoids alert flapping and makes each alarm more actionable.

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.

ProjectWhat it is good atWhat it is not trying to be
zwfm-encoderOpen-source broadcast appliance on a Pi with fan-out, monitoring, and silence alertingA giant all-purpose broadcast suite or a general SDR lab
Stereo ToolDeep commercial processing and mature FM toolingA minimal, Pi-focused operational encoder for a narrow station workflow
GnuRadioFlexible signal processing and SDR experimentationA ready-made appliance that operators can run with little assembly
rpitx / PiFmAdvDirect Raspberry Pi transmission and hardware-specific experimentationA 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.