MCPcopy Index your code
hub / github.com/dheijl/swyh-rs

github.com/dheijl/swyh-rs @1.20.4

Chat with this repo
repository ↗ · DeepWiki ↗ · release 1.20.4 ↗ · + Follow
348 symbols 907 edges 34 files 114 documented · 33%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

swyh-rs

CI status

rs-tall

What is it

A "Stream-What-You-Hear" implementation written in Rust, MIT licensed.

Contents

Current Release

The current release is 1.20.3, refer to the Changelog for more details.

You can find x86/64 Windows setup and binaries and Linux (Ubuntu/Debian) appimages in Releases.

You can find Arm binaries here. They are provided by Jamie Duk (@Jay), I have not tested them. He also provides his build recipe.

Why this SWYH alternative ?

swyh-rs implements the idea behind the original SWYH (source repo https://github.com/StreamWhatYouHear/SWYH) written in Rust. It allows you to stream the music you're currently playing on your PC (Windows or Linux) to an UPNP/DLNA/OpenHome compatible music player (a "Renderer").

I wrote this because

  • I wanted to learn Rust
  • SWYH does not work on Linux
  • SWYH did not work well with Volumio (push streaming did not work)
  • SWYH has a substantial memory leak due to the use of an old and unmaintained Intel .Net UPNP/DLNA library it uses.

NOTE swyh-rs does not support lossy mp3 or aac re-encoding, only lossless LPCM/WAV/RF64/FLAC for obvious reasons.

It has been tested with

  • MoOde audio, with Moode configured as UPNP renderer in Openhome mode, and using FLAC (preferable) or LPCM (since 1.8.7) or WAV format. See Known problems for solving the 5-second delay with WAV/RF64/LPCM format. Use FLAC instead if you can.
  • Volumio
  • Harman Kardon AV network streamers (thanks @MX10-AC2N!)
  • Denon Heos devices. Wav Format with NoneChunked streamsize seems to work best with Denon. And if you change format or streamsize you may have to restart swyh-rs to make the Denon recognize this. See issue #183. If you select an invalid combination the Denon app will also tell you this.
  • Sony AV streamers & Bravia TVs
  • Goldenwave HiFiMan Serenade DAC/Headphone amlpifier using WAV/RF64/FLAC.
  • Chromecast devices exposed as an OpenHome or DLNA devices in Bubble UPNP Server (thanks Bubblesoft for providing the necessary information!). If you have multiple devices in the same Bubble UPNP server, you need version 1.12.3 or later, because there are multiple devices at the same IP address. At a certain point Bubble changed the SSDP headers causing swyh-rs to no longer "see" these device. This is also fixed in 1.12.3. See issue #157 (thanks @kenkuo). Prior to 1.12.3 devices were identified by their IP address, from 1.12.3 on they are identified by their SSDP "Location".
  • Sonos speakers/soundbars using the WAV format (thanks @Cunkers !). update: A recent update to the Sonos Play 1 also enabled FLAC. Depending on your network a Sonos may stutter when using WAV, if you are affected you should use FLAC if your device supports it. See issues #84 and #75. Software version "15.9 (Build 75146030)" on the Play:1 is known to support FLAC without stuttering (thanks @beWAYNE !). Important: if you are streaming to a stereo pair, you should only stream to the master of the pair, and never to both, as this can/will break the stereo pair (see issue #141)! See also this wiki entry for Sonos stuttering.
  • If you want to pause music without losing the connection you can enable the Inject Silence option. The InjectSilence flag is automatically added to the config file when you first start version 1.4.5 and defaults to false. Contributed by @genekellyjr, see issue #71, and @DanteDT. Since 1.12.0 Inject Silence should work with FLAC too. If you don't enable Inject Silence for FLAC, swyh-rs will automatically periodically inject some faint white noise in the absence of sound so that you hopefully don't loose the connection.
  • injecting silence will eat a neglegible amount of cpu cycles.
  • it seems that stuttering can occur with Sonos gear, especially with WiFi connections. You can try to set an initial buffering value to prevent this. According to @konyong installing ccproxy can also help, refer to issue #130 for more details.
  • Kef Wireless LS50 II (thanks @Turbomortel via Twitter)
  • Xbox 360, using Foobar2000 and entering the streaming url in foo_upnp (thanks @instinctualjealousy)
  • iEast Audiocast M5 using the WAV format header (thanks @Katharsas)
  • Yamaha WXAD-10 since 1.6.1 (see issue #89), and possibly other Yamaha devices?
  • for QPlay devices, like the Xiaomi S12, you need version 1.8.2 or later, see issue #99. Older versions wrongly try to use Openhome instead of AVTransport.
  • Roon with FLAC and using U32MaxChunked for streamsize (swyh-rs 1.10.5 and up). Thanks to @DrCWO for figuring this out (issue #55).
  • playback on Squeezebox players connected to Logitech Media Server (now known as Lyrion Music Server) works by adding the swyh-rs URL as a favorite to LMS: http://pcipaddress:5901/stream/swyh.flac, as pointed out by @Cornelisj (issue #40).

but any OpenHome/DLNA streamer that supports FLAC (except older Sonos software versions that do not do FLAC over upnp) will probably work (since version 1.4.0).

If a device supports both OpenHome and DLNA, the OpenHome endpoint is used, and the DLNA AVTransport endpoint is ignored.

Music is streamed with the sample rate of the music source (the chosen audio output device, I personally use VBAudio HiFi Cable Input as a bit-perfect audio source).

Supported audio streaming formats:

  • 16 bit or 24 bit FLAC (lossless compression, I'm using the lowest compression level for performance and latency reasons). It is available since version 1.4.0
  • audio/wav (16 bit) with a "maximum length" (4 GB) WAV header, available since version 1.3.5
  • uncompressed 16 bit LPCM format (audio/l16)
  • audio/rf64 (16 bit) basically WAV with unlimited size since version 1.9.1.

Note that older libsndfile based renderers may not be able to decode the WAV format, because the stream is not "seekable".

Audio is captured using the excellent Rust cpal library. fltk-rs is used for the GUI, as it's easy to use, and it's small, cross-platform, fast and works well. For FLAC encoding the of use flac-bound made adding FLAC encoding using the libflac-sys Rust bindings a breeze. This allowed me to link libflac statically in the swyh-rs binary, no dlls needed!

Tested on Windows 10/11, Ubuntu 20.04 LTS and later, and Debian (LMDE 7) with Raspberry Pi/Hifi-Berry based devices, currently running MoodeAudio 10.x. I don't have access to a Mac, so I don't know if that also works.

Because it is written in Rust it uses almost no resources (CPU usage barely measurable, Ram usage around or below 8 MB).

swyh-rs as your local internet radio station

You can also use swyh-rs as an internet radio station on your local network. swyh-rs is available at

  • http://{your-pc-ip}/stream/swyh.raw when streaming "raw" LPCM format
  • http://{your-pc-ip}/stream/swyh.wav when streaming WAV format
  • http://{your-pc-ip}/stream/swyh.rf64 when streaming RF64 format
  • http://{your-pc-ip}/stream/swyh.flac when streaming FLAC format

You can append query parameters to the url for bits per sample (bd = bit depth, 16 or 24) and streamsize (ss: nonechunked, u32maxchunked, u64maxchunked, u32maxnotchunked, u64maxnotchunked). The query parmeters in the query string override the configured values.

Example: http://{your-pc-ip}/stream/swyh.flac?bd=24&ss=nonechunked

When running the CLI with the -x option, that is effectively the only way to access the swyh-rs audio server. This is also true when running the GUI if SSDP discovery has been disabled by setting the SSDP interval to 0.0.

Where to get it and how to install

You can get the latest Windows binary from the Release page. No install needed, no runtime, no dependencies. Just unzip the binary in a convenient place and run it.

Debug build and a release builds and a setup for Windows 64 bit are included in the release assets, I also add Linux appimages for Ubuntu 20.04 LTS and Debian Bookworm. You would only ever need the debug build in the unlikely case rust "panics", and the program vanishes without a message. In a release build you will have a logging file in the .swyh-rs folder in your home directory. But when rust "panics" you can't log it, so you will need to start the debug build from a console/terminal window. A debug build automatically raises the log level to "DEBUG". This will also allow you to catch the Rust "panic" message in the console window (release builds do not have a console on Windows). Depending on the log level you set (info/warn/debug) the release build will provide all information needed to help in troubleshooting, aside from "panics".

If you want to build swyh-rs yourself, you can find some information in the wiki.

If it doesn't work for you, please open a new issue and include all the debug log level information. I will try to provide a fix ASAP.

Todo

  • I'm open to suggestions, but I definitely hate GUI programming...

Known problems

  • On a freshly installed Windows system you may get an error "VCRUNTIME140.dll was not found". Rust Windows binaries built with the MSVC toolchain need the Visual Studio 2015..2019 runtime. Because so much software relies on it, is almost always already present, but if not you can get the Visual C++ 2015..2019 runtime installer from https://aka.ms/vs/16/release/vc_redist.x64.exe. The current Windows installer will automatically do this if necessary.
  • On linux you may have to enable audio monitoring with pavucontrol to make audio capture work
  • make sure that your firewall or anti-virus do not block the default incoming HTTP port 5901 for streaming requests (or the port number you configured in the UI if not the default), and that outgoing UDP traffic is allowed for SSDP
  • resizing a window in fltk 1.4 is not ideal, but thanks to @MoAlyousef it is now usable in swyh-rs. But if you resize vertically to a very small window you risk losing the horizontal scrollbar in the textbox at the bottom.
  • simultaneous streaming to multiple renderers is only limited by the number of renderer buttons that can be shown in the available space in the window.
  • Kaspersky Antivirus can prevent audio capture, so you may have to add an exception for swyh-rs (thanks @JWolvers).
  • streaming to Logitech Media Server does not work (issue # 40)
  • Since 1.20.4 the published x86-64 binaries require SSSE3 support (any x86-64 CPU made in roughly the last 20 years has this). If you run on very old hardware you will need to recompile without the target-cpu=native / SSSE3 flags in .cargo/config.toml.
  • CPAL 0.18 (used since 1.20.3-RCx) is more thorough when enumerating audio device configurations, which causes a noticeable increase in startup time on Linux. Debug builds are significantly slower than release builds in this regard. This has been fixed in the current CPAL master (June 3, 2026).
  • streaming to Linn devices may now work: basic HTTP Range header support was added in 1.20.3-RC4 to handle Linn's partial-content requests (see issue #45). This has not been tested with real hardware.
  • if for some reason your config file gets corrupted/invalid it will be replaced with a default configuration at startup instead of panic-ing when deserializing.
  • when using WAV/RF64/LPCM with an MPD/FFMPEG based player like MoOde, you get a 5 second delay caused by FFMPEG analyzing the input stream. You can reduce this by specifying acceptable limits for analyzing audio in the MPD config like shown below, or you can use FLAC instead (recommended).
decoder {
plugin "ffmpeg"
enabled "yes"
analyzeduration "5000"
probesize "1024"
}

Artwork Credits

The icon was designed by @numanair, thanks!

How does it work?

When swyh-rs starts, it:

  • captures audio from the selected audio source (WasApi on Windows, Alsa on Linux)
  • starts a built-in HTTP audio streaming web server on the configured port (default 5901)
  • runs SSDP discovery to find all UPnP/DLNA/OpenHome media renderers on the local network (takes about four seconds)
  • displays a button for every discovered renderer, together with a volume slider if the renderer supports volume control — drag the slider to change t

Extension points exported contracts — how you extend this code

FwSlashPipeEscape (Interface)
fltk `choice` needs escaping the `pipe` character when showing strings so add this trait for escaping the `|` in &str [1 …
src/utils/traits.rs
SanitizeArg (Interface)
Be lax when parsing cli `bool` arguments strings [1 implementers]
src/utils/traits.rs

Core symbols most depended-on inside this repo

ui_log
called by 120
src/utils/ui_logger.rs
parse
called by 54
src/utils/commandline.rs
update_config
called by 25
src/utils/configuration.rs
get_config_mut
called by 25
src/globals/statics.rs
parse
called by 16
src/utils/commandline.rs
name
called by 16
src/audio/audiodevices.rs
downmix_to_stereo
called by 14
src/audio/samples_conv.rs
f32_to_i32
called by 12
src/audio/samples_conv.rs

Shape

Function 229
Method 86
Class 21
Enum 10
Interface 2

Languages

Rust95%
Python5%

Modules by API surface

src/utils/commandline.rs55 symbols
src/renderers/rendercontrol.rs43 symbols
src/audio/samples_conv.rs41 symbols
src/utils/configuration.rs38 symbols
src/audio/audiodevices.rs20 symbols
src/audio/rwstream.rs17 symbols
deploy/flatpak/alt_method/flatpak-cargo-generator.py17 symbols
src/enums/streaming.rs16 symbols
src/bin/swyh-rs-cli.rs14 symbols
src/server/streaming_server.rs13 symbols
src/bin/swyh-rs.rs11 symbols
src/ui/mainform.rs10 symbols

For agents

$ claude mcp add swyh-rs \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact