Hey. I’ve been a VFIO/Scream Audio Driver user for years. A few weeks ago I had an idea to make a mixer/router that allows configuring many to many sink<->source setups. After a few weeks this is what I have.
https:// github .com/netham45/screamrouter
(Remove the spaces, I can’t post links yet)
This allows routing of many<->many Scream sources to Scream renderers. It also allows adjusting equalization, volume, and audio delay. It uses ffmpeg to mix multiple sources together for a single output. It allows any source/route/sink to be disabled/enabled.
This uses Python Multiprocessing so it can be multi-threaded without worrying about GIL latency, and it uses Unix pipes a fair bit so it’s unix-like only. It’s designed to be able to support as many source to sink mappings as possible.
It is all configured over a FastAPI API with a basic first-draft interface. It also exposes sinks as MP3 streams that are available from the API or web interface.
I don’t have a proper installer set up for it but I was eventually going to upload it to one of the Python repos.
It uses FastAPI with API docs available at /docs once it is running.
It’s still early in development but I have a Home Assistant custom component that will allow setting the volume/enabling/disabling sinks. I’m planning on extending it to having routes and sources, too. This supports the ‘Media Playback’ in Home Assistant so sinks can be used for text to speech or to play sounds from Home Assistant. A full list of features is on the repo.
If anyone gives this a try please let me know how it works for you. Right now the only non-functional feature I’m aware of is adding/editing groups through the interface, this can currently be done by YAML or via the API.
If anyone tries it and has any feature suggestions or bugs they’ve found please let me know.
1 Like
I have done so many updates on this, lol.
Here’s a link to the repo: https:// github .com/netham45/screamrouter
These are the sources it can play from
-
RTP/Linux Source with fixed MTU
-
Windows Source
-
ESP32S3 USB Audio Card Senders
-
Raspberry Pi Zero W / Raspberry Pi Zero 2 USB Gadget Sound Card Sender
-
Amazon Music Docker Container
-
Firefox Docker Container
-
Spotify Docker Container
-
Rooted LG WebOS TVs via ScreamStreamer
-
Many Linux PCM sources via ScreamStreamer
These are the receivers it can play to
-
Windows Receivers
-
Raspberry Pi/Linux Receiver
-
ESP32/ESP32s3 spdif/USB UAC 1.0 audio receiver
-
ESP32 A1S Audiokit Receiver
-
Android Receiver
-
Python Scream Receiver
-
Anything that can play an MP3 stream
All the documentation is linked from the readme at https:// github .com/netham45/screamrouter/blob/main/README.md
1 Like
hy @netham45
It doesn’t seem to support cross-compilation. I’ve already built lame first and screamrouter doesn’t see it.
2025-10-13T14:37:21.7662101Z 22:37:21 [DEBUG] replace_variables: self.arch=x64, machine_arch=X64
2025-10-13T14:37:21.7662391Z replace_variables: self.arch=x64, machine_arch=X64
2025-10-13T14:37:21.7662670Z 22:37:21 [DEBUG] replace_variables: input='--with-pic'
2025-10-13T14:37:21.7663056Z replace_variables: input='--with-pic'
2025-10-13T14:37:21.7663327Z 22:37:21 [DEBUG] replace_variables: output='--with-pic'
2025-10-13T14:37:21.7663586Z replace_variables: output='--with-pic'
2025-10-13T14:37:21.7664365Z 22:37:21 [DEBUG] Running: ./configure --prefix=/sdk/build_dir/target-aarch64_generic_musl/pypi/screamrouter-0.3.12/build/deps --disable-shared --enable-static --disable-frontend --with-pic
2025-10-13T14:37:21.7665620Z Running: ./configure --prefix=/sdk/build_dir/target-aarch64_generic_musl/pypi/screamrouter-0.3.12/build/deps --disable-shared --enable-static --disable-frontend --with-pic
2025-10-13T14:37:21.7666736Z 22:37:21 [DEBUG] in: /sdk/build_dir/target-aarch64_generic_musl/pypi/screamrouter-0.3.12/src/audio_engine/deps/lame
2025-10-13T14:37:21.7668504Z in: /sdk/build_dir/target-aarch64_generic_musl/pypi/screamrouter-0.3.12/src/audio_engine/deps/lame
2025-10-13T14:37:21.8750224Z configure: loading site script /sdk/include/site/aarch64
2025-10-13T14:37:21.9403263Z checking build system type... x86_64-unknown-linux-gnu
2025-10-13T14:37:21.9403900Z checking host system type... x86_64-unknown-linux-gnu
2025-10-13T14:37:21.9468781Z checking for a BSD-compatible install... /sdk/staging_dir/host/bin/install -c
2025-10-13T14:37:21.9491917Z checking whether build environment is sane... yes
2025-10-13T14:37:21.9589654Z checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
2025-10-13T14:37:21.9594366Z checking for gawk... gawk
2025-10-13T14:37:21.9670186Z checking whether make sets $(MAKE)... yes
2025-10-13T14:37:21.9716673Z checking whether make supports nested variables... yes
2025-10-13T14:37:21.9766247Z checking whether to enable maintainer-specific portions of Makefiles... no
2025-10-13T14:37:21.9797725Z checking for style of include used by make... GNU
2025-10-13T14:37:21.9808751Z checking for gcc... ccache aarch64-openwrt-linux-musl-gcc
2025-10-13T14:37:22.0669705Z checking whether the C compiler works... yes
2025-10-13T14:37:22.0670303Z checking for C compiler default output file name... a.out
2025-10-13T14:37:22.1007188Z checking for suffix of executables...
2025-10-13T14:37:22.1391564Z configure: error: in `/sdk/build_dir/target-aarch64_generic_musl/pypi/screamrouter-0.3.12/src/audio_engine/deps/lame':
2025-10-13T14:37:22.1393026Z configure: error: cannot run C compiled programs.
2025-10-13T14:37:22.1393620Z If you meant to cross compile, use `--host'.
2025-10-13T14:37:22.1394105Z See `config.log' for more details
2025-10-13T14:37:22.1618806Z Command failed: ./configure --prefix=/sdk/build_dir/target-aarch64_generic_musl/pypi/screamrouter-0.3.12/build/deps --disable-shared --enable-static --disable-frontend --with-pic
2025-10-13T14:37:22.1621165Z checking whether we are cross compiling... 22:37:22 [ERROR] Command failed: ./configure --prefix=/sdk/build_dir/target-aarch64_generic_musl/pypi/screamrouter-0.3.12/build/deps --disable-shared --enable-static --disable-frontend --with-pic
2025-10-13T14:37:22.1624586Z Error building lame: Command '['./configure', '--prefix=/sdk/build_dir/target-aarch64_generic_musl/pypi/screamrouter-0.3.12/build/deps', '--disable-shared', '--enable-static', '--disable-frontend', '--with-pic']' returned non-zero exit status 1.
2025-10-13T14:37:22.1626458Z Build failed for lame
2025-10-13T14:37:22.1626925Z Build failed for lame, stopping
2025-10-13T14:37:22.1627324Z Some dependencies failed to build
2025-10-13T14:37:22.1629203Z 22:37:22 [ERROR] Error building lame: Command '['./configure', '--prefix=/sdk/build_dir/target-aarch64_generic_musl/pypi/screamrouter-0.3.12/build/deps', '--disable-shared', '--enable-static', '--disable-frontend', '--with-pic']' returned non-zero exit status 1.
2025-10-13T14:37:22.1630715Z 22:37:22 [ERROR] Build failed for lame
2025-10-13T14:37:22.1631132Z 22:37:22 [ERROR] Build failed for lame, stopping
2025-10-13T14:37:22.1631601Z 22:37:22 [ERROR] Some dependencies failed to build
2025-10-13T14:37:22.1640295Z Traceback (most recent call last):
2025-10-13T14:37:22.1657394Z File "/sdk/staging_dir/hostpkg/lib/python3.13/site-packages/pyproject_hooks/_in_process/_in_process.py", line 389, in <module>
This should be resolved now, I also have aarch64 wheels getting built and uploaded to PyPI now.
I wanted to post an update on ScreamRouter, I’ve added many features since I last posted here.
ScreamRouter
System Audio
- PulseAudio Emulation
- ALSA and WASAPI support
- WASAPI loopback capture
ScreamRouter can now capture audio from ALSA and WASAPI inputs, output to ALSA and WASAPI outputs, and provides a PulseAudio emulation layer so libpulse applications can directly play to ScreamRouter.
RTP
- RTP Support - changed focus from Scream protocol to using more standard RTP
- RTCP Support - RTCP sender reports with wall clock/tick count correlation for player synchronization
- Opus and PCM support
- ScreamRouter can play to other instances of ScreamRouter as well
WebRTC
- ScreamRouter can play low latency streams to WebRTC listeners through the Web UI
- Set up GitHub build matrix to build PyPI packages for x86/ARM glibc/musl and windows x86/x64, install ScreamRouter with ‘pip install screamrouter’
UI
I’ve completely redone the UI since I posted here. I’ve rebuilt it to be a responsive React based site.
-
Speaker Layout
-
Timeshift Buffer Viewer
- ScreamRouter keeps a 5 minute rolling timeshift buffer for every source and allows users to scrub them, delay sources, download the buffer or snippets as WAV files, or export fingerprints
Desktop Menu
I’ve added a desktop menu that sits in the notification bar
- Created an ESP32 firmware for streaming to/from RTP sources
- Supports acting as a USB sound card and playing out over RTP
- Supports capturing SPDIF and playing out over RTP
- Supports taking in RTP and playing to a USB UAC 1.0 device
- Supports taking in RTP and playing out over SPDIF
- Supports playing to unicast or multicast receivers, supports playing to/from PulseAudio, Pipewire, and VLC as well as ScreamRouter and other ESP32-RTP modules
- Syncs time over NTP for playback synchronization
I’m sure there’s more I’ve added that I’m forgetting, too