Release v1.1
WiFi Audio Streaming Desktop - v1.1 🎉
Well... I promised 1.0 would be the release where I stopped rewriting everything.
That lasted approximately five minutes.
The original plan was simple: fix some issues, polish the UI a little, maybe fix a couple of bugs and finally let the project rest for a while.
Instead, I somehow ended up designing an entirely new version of the streaming protocol, writing a reference C implementation for embedded devices, adding automatic updates, building a proper first-run experience, creating a command-line interface that grew way beyond what I originally intended, and making the firewall slightly less of an existential threat.
On the bright side... I passed my C exam. Apparently spending months writing C code for your own project does count as studying. I wouldn't recommend relying on that strategy tho, but somehow it worked.
⚠️ Breaking Changes
Before upgrading, there's one important thing to know.
This release introduces WFAS Protocol Version 2. That means Desktop 1.1 is not wire-compatible with previous releases, and neither is the updated Android app.
If you're upgrading, make sure both the desktop and Android applications are updated together. You already know the drill, every new release is like this atp.
BUT!! Unlike previous versions, incompatible peers are now detected immediately during the initial handshake. Instead of sitting there forever pretending everything is working while absolutely nothing happens, both applications now reject the connection with a clear error explaining that the other device is using an incompatible protocol version and needs to be updated. Hopefully that should eliminate one of the most common support questions.
🌐 WFAS Protocol v2
Probably the biggest change in this release isn't something you'll immediately notice.
It's the protocol itself.
Until now, the wire format mostly lived inside the applications. It worked perfectly fine, but documenting it meant digging through Kotlin, Java and native C code whenever someone wanted to implement it elsewhere.
That wasn't exactly ideal.
So WFAS now has something I never imagined it would need when I first started this project: its own repository.
The new WFAS Protocol v2 specification now lives here:
👉 https://github.com/marcomorosi06/wfas-protocol
Alongside the documentation is a tiny dependency-free C99 reference implementation intended for embedded and firmware developers. Whether you're building an ESP32 network speaker, an STM32 audio receiver, an RP2040 project, a Raspberry Pi appliance or something much stranger, the goal is to make integrating WFAS as painless as possible.
The implementation is intentionally tiny:
- C99
- no heap allocation
- transport agnostic
- endianness-safe
- only two source files (
wfas.c+wfas.h) - optional authentication
- optional ChaCha20-Poly1305 encryption
- RFC test vectors included
Drop the two files into your firmware project, plug them into whatever UDP stack you're already using, and you're done. No RTOS assumptions, no networking library requirements, no hidden dependencies.
"Does it actually work?"
I figured somebody would eventually ask that. So instead of just writing the library and hoping for the best, I decided to test it on actual hardware.
I grabbed an ESP32, sacrificed an old pair of earphones, cut the cable in half, soldered together an analog circuit made of two resistors and a capacitor, and used the headphone output as an improvised audio source. Physics, guys.
And it worked!
The ESP32 happily streamed audio to both the Desktop and Android applications using the exact same WFAS v2 implementation that's now in the repository. The signal isn't studio quality, feeding line-level audio into a microcontroller through what is essentially "electronics drawer engineering" introduces a fair amount of analog noise, but it's absolutely recognizable and perfectly listenable.
In fact, while testing this setup I ended up adding an optional Noise Reduction setting under Developer Settings in both the Desktop and Android apps. It's mainly intended for experiments like this and other analog capture setups, where reducing the constant background hiss makes a surprisingly noticeable difference.
I definitely didn't expect one of the first WFAS v2 implementations outside the official apps to be held together by a cut headphone cable and three passive components. Yet here we are.
A Protocol, Not Just Two Apps
One thing I really wanted with v2 was to separate the protocol from the applications. Desktop and Android are now simply implementations of WFAS rather than being the definition of the protocol. Anyone can build a compatible implementation without reverse engineering packets or reading through thousands of lines of Kotlin.
Here you can find the protocol-lab... I'm still working on this site: https://www.marcomorosi.eu/wifi-audio-streaming/developers/
🤝 Smarter Compatibility Checks
Protocol negotiation also became much more explicit.
Every connection now advertises its protocol version during the initial HELLO handshake.
- If both sides agree, streaming begins normally.
- If they don't, the connection is rejected immediately with a dedicated
WFAS_INCOMPATIBLEresponse.
Both the Desktop and Android applications now explain exactly what's happening instead of silently timing out. No more wondering whether it's your firewall, your router, your Wi-Fi, your audio driver, or Mercury being in retrograde. If you're talking to an older version, the application simply tells you to update.
🚀 Automatic Update Checker
Another long-requested feature finally made it into the application.
WiFi Audio Streaming can now check GitHub for new releases automatically and notify you whenever a newer version becomes available. No more periodically opening the Releases page wondering whether I've disappeared again.
The updater includes:
- automatic update checks at startup (optional)
- manual "Check for Updates" button
- release notes directly inside the application
- direct download links
- proper version comparison
- detection of development builds newer than the latest public release
Everything runs in the background and can be disabled entirely if you'd rather keep the application blissfully unaware that newer versions exist.
🔒 Password Protection & ChaCha20-Poly1305 Encryption
This release brings a massive security upgrade. You can now control who is allowed to connect to your stream, and ensure nobody else can listen in on the network.
Authorization Modes
Servers can now operate in three different authorization modes:
| Mode | Behaviour |
|---|---|
| Off | Accept every incoming client automatically. |
| Ask | Prompt the user before allowing a new client to connect. |
| Key | Only clients that know the shared password may connect. |
If you use the Key mode, it doesn't just block unauthorized connections during the handshake. Setting a key actually lets you enable authenticated end-to-end encryption based on ChaCha20-Poly1305.
During the initial handshake, the client must provide the password. If it's wrong, the connection is rejected immediately (mutual HMAC challenge-response, the password itself is never sent over the wire).
But if it matches, that same key is then used to physically encrypt the stream. Every single audio packet is encrypted before it leaves the server and authenticated before the receiver accepts it. Even if someone intercepts your network traffic, all they'll get is cryptographic noise.
This makes accidental or unwanted connections considerably less likely, which is especially useful if you're on a larger or shared network (like a dorm or an office) and don't want your coworkers unexpectedly tuning into your stream.
🖥️ Firewall Assistant
One surprisingly common support request looked something like this: "The client just says Waiting..."
Nine times out of ten, Windows Firewall had silently decided that audio streaming wasn't going to happen today.
The application now tries to help before you spend half an hour debugging something that isn't actually your fault.
- Windows: A built-in helper can automatically create the required inbound firewall rule with administrator privileges. One click. Done.
- Linux: Automatic configuration isn't practical across every distribution, but the application now detects common firewall managers such as
ufwandfirewalldand shows the exact command needed to open the required ports.
⌨️ The Command Line Interface (wfas)
Sometimes you just don't want to click buttons. Maybe you want to start a stream from a script, maybe you live in the terminal, or maybe you just like text-based interfaces.
I originally intended to add a simple launch script. Naturally, I got completely carried away, and WiFi Audio Streaming now comes with wfas, a massively overpowered, fully-featured Command Line Interface. During the welcome setup, the app will offer to install it to your system's PATH.
This isn't just a shortcut to launch the GUI. It's a complete headless daemon and control tool:
- Full Headless Operation: Start an audio server (
wfas --server --rtp), connect as a client, or discover devices directly from the terminal. - Runtime IPC Control: Open another terminal and type
wfas control volume 75orwfas control muteto command the running instance on the fly. - Configuration Manager: Type
wfas config listorwfas config editto manage the JSON configuration shared with the GUI. You can even export/import profiles. - Firewall Management: Run
wfas firewall allowto fix Windows Firewall without leaving the command prompt. - Automation Ready: Add
--jsonto almost any command for machine-readable output perfect for scripting.
For all the commands, type wfas --help. And don't be scared by the wall of text, give it to an AI idk.
The "I Got Distracted" Visualizer
If you run wfas --viz, it turns your terminal into a real-time ASCII audio visualizer for the incoming stream.
But I didn't stop at raw audio levels. I added theming (--viz rainbow or --viz "#1e88e5"). Then I added --monitor, so you can just use the visualizer to look at your local system audio without even starting a network server.
Then, because raw FFT spectrums usually result in bass frequencies pinning the left bars to the top while everything else flattens out, I added --groove. This applies an adaptive DSP envelope: it compares bands to their frequency neighbours and subtracts the constant parts of the mix. The result? The visualizer actually highlights the melody and individual notes poking out of the mix, instead of just bouncing mindlessly to the kick drum.
It serves absolutely zero practical purpose, but it looks incredibly cool, and I personally use it as my default server streaming config.
💖 Support & Ko-fi
WiFi Audio Streaming has grown a lot, and it takes a considerable amount of time (and coffee, and occasionally sacrificed earphones) to maintain. To help support the project, I've added a Ko-fi donation popup.
Before you panic: it is designed specifically not to be annoying.
While simply clicking "Maybe later" keeps it in the regular popup rotation, there is an explicit "Don't show for 30 days" button. Click that, and the application will happily leave you alone for a whole month.
But if you do use the app regularly and want to help fund future development, a coffee goes a long way! ☕
🔧 Other Improvements
- Live Debug HUD: Start the CLI with
--debugfor a live updating table of UDP packets and internal state. - Open Source Licenses Page: A proper, dedicated screen listing all the open-source libraries that make this project possible, because giving credit where it's due is important.
- General UI Polish: Smoother transitions, better state management for devices stuck on "Waiting", and lots of tiny layout fixes across Windows, macOS, and Linux.
❤️ Community Contributions
This is a big milestone: the very first external pull requests have been merged! A massive thank you to our new contributors for making the app better:
- @mvanhorn for fixing an incredibly frustrating issue where the main window wouldn't scroll using the keyboard on low-resolution displays. (#11)
- @kitsumed for updating and cleaning up the GitHub Actions CI/CD release workflow. (#16)
Open source at its finest.
As always, thank you to everyone who tested the early builds and reported bugs. Using a program is the best way to test its limits.
Enjoy v1.1!