mirror of
https://github.com/lox-audioserver/lox-audioserver.git
synced 2026-04-25 22:35:53 +03:00
[GH-ISSUE #127] ESP32 based sendspin/snapcast clients not discovered by lox-audioserver #69
Labels
No labels
bug
enhancement
pull-request
released
released on @beta
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/lox-audioserver#69
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @martinsefcik on GitHub (Jan 19, 2026).
Original GitHub issue: https://github.com/lox-audioserver/lox-audioserver/issues/127
I tried the following Snapcast ESP32-based client: https://github.com/CarlosDerSeher/snapclient
and also a draft Sendspin client implementation for ESPHome from this PR: https://github.com/esphome/esphome/pull/12284
Both work with MusicAssistant, and the clients are automatically discovered—I don’t need to provide the server URL in the client configuration.
However, if I try the same with lox-audioserver, no clients are found.
Both MusicAssistant and lox-audioserver are running in Docker containers on my server, using host network mode.
I’m not sure what I’m doing wrong, but I would expect that if MusicAssistant is able to discover these clients, then lox-audioserver should be able to do the same. Could it be that something is missing or not yet implemented in lox-audioserver that affects client discovery for these protocols?
@mr-manuel commented on GitHub (Jan 19, 2026):
Snapcast clients discover the server. Since you have MA and Lox Audioserver enabled on the same host, this could be an issue. Also because Lox Audioserver is using port 7090 and not the default port.
@rudyberends commented on GitHub (Jan 19, 2026):
I dont think that client has a snapcast ws implementation. So even if it discovers the Snapcast server, it will not be able to actually operate it.
The latest 4.x branch now also implements Snapcast over TCP and advertises that transport via mDNS.
However, this TCP transport runs on the default Snapcast port.
If you are running a Music Assistant instance on the same host, this can indeed cause conflicts.
@martinsefcik commented on GitHub (Jan 21, 2026):
I’ve always run either lox-audioserver or Music Assistant, never both simultaneously.
After adding TCP support for the Snapcast protocol in lox-audioserver and providing the lox-audioserver IP address in the Snapcast client, I can connect. However, playback behaves strangely: roughly 1 second of music plays, followed by 3–5 seconds of silence, then 1 second plays again, and so on.
The same client configuration works fine with Music Assistant. I’ve tried both 500ms and 1000ms buffers for the Snapcast protocol in Music Assistant, and both work correctly.
I haven’t tested whether autodiscovery via mDNS works yet, because my development environment for lox-audioserver is in WSL2, so mDNS likely cannot reach my local network from the WSL environment. I will retest once this functionality is available in the beta Docker image.
@martinsefcik commented on GitHub (Jan 26, 2026):
I was looking into the mDNS behavior, and in my setup (MA and lox-audioserver running in Docker containers with network: host), I noticed a difference:
Could this be a problem? These Snapcast and SendSpin clients (ESP32-based, but probably not only ESP32) might not be smart enough to pick the correct IP address from the same subnet. They may simply choose the first advertised address, which could be an internal Docker IP, and then fail to discover the SendSpin/Snapcast server automatically.
I also looked briefly into the Music Assistant source code to understand how mDNS is handled there, but so far I haven’t been able to identify the part responsible for selecting the single “correct” IP address to advertise via mDNS.
But mDNS is not an area I’m deeply familiar with yet, so my assumptions may be incorrect.
@rudyberends commented on GitHub (Jan 26, 2026):
Ah yeah, thanks for spotting this. I couldn’t reproduce it myself, but I can see how it happens with the current code. Music Assistant likely avoids it because they either use a different mDNS stack that can bind to a single interface/IP, or they explicitly advertise just one address. We use bonjour-service, which publishes A/AAAA records for all non‑internal interfaces, and Snapcast was advertising a hostname, which pulls in every address for that host.
This is fixed now in
ff722ca: we now prefer config.system.audioserver.ip for all mDNS advertisements (loxAudio, sendspin, snapcast), and Snapcast no longer converts a provided IP into the hostname. That forces a single IP in the mDNS target, which avoids clients picking Docker/IPv6 addresses.@rudyberends commented on GitHub (Feb 1, 2026):
mdns fixes are now in beta4. Could you try again?
@martinsefcik commented on GitHub (Feb 2, 2026):
It’s still not working in some scenarios. I’ll provide more details, but I need some more time to finish the testing.
@martinsefcik commented on GitHub (Feb 10, 2026):
When running lox-audioserver in a Docker container with host network mode, it looks like the mDNS fix—where you used the audioserver IP directly as the hostname in the mDNS record for the Sendspin server—successfully fixed client autodiscovery (at least when using sendspin-cli).
However, it is not working with the ESP32 Sendspin client from this draft ESPHome implementation:
https://github.com/esphome/esphome/pull/12284
That said, the draft implementation has recently changed and currently does not even compile, so I cannot continue testing with it for now. I’ll try again later once it’s usable.
For Snapcast, mDNS autodiscovery is still not working. The audioserver IP is not used as the hostname in mDNS, and the service is advertised for many IP addresses (including Docker-related ones).
I did my own experiment here:
github.com/lox-audioserver/lox-audioserver@4117ace59aI rewrote the mDNS publishing implementation and replaced
bonjour-servicewith@homebridge/ciao. Unlike bonjour-service, ciao supports publishing mDNS records only on specific network interfaces.This is how the mDNS records look in beta5:
And this is how they look with my fix:
What this change improves:
→ This fixed Snapcast client discovery and removed the need to embed the audioserver IP directly into Sendspin mDNS records (which looks to me like a workaround).
This solution is not ideal:
https://github.com/homebridge/ciao/issues/8
A potentially better solution would be to fork bonjour-service and add support for selecting which interface(s) mDNS should be published on. I already found a fork where this functionality was added:
github.com/LGSInnovations/bonjour-service@7ad3304bccWhat do you think about this?
@tokylo commented on GitHub (Feb 13, 2026):
I am using the ESP32-Audio-Dock project from Sonocotta and recently purchased the new Amped ESP32‑S3‑Plus model.
First of all: these devices are fantastic. The Amped ESP32‑S3‑Plus includes:
I think these devices are an excellent match for Lox-Audioserver when using external speakers.
Here is the product link (not meant as advertising, just for reference):
https://github.com/sonocotta/esp32-audio-dock
https://www.tindie.com/products/sonocotta/amped-esp32-plus/
Problem
I flashed the
amped-esp32-s3-plus-idf-sendspinfirmware and the device works perfectly as a Sendspin player in Music Assistant.Music Assistant discovers it immediately without any issues.
However, the same device is not discovered by Lox-Audioserver (V4 BETA5).
I also run several Linux-based Sendspin players, and these are detected correctly by Lox-Audioserver.
These Linux players actively connect to the Lox-Audioserver using a WebSocket URL, for example:
--url ws://192.168.x.x:7090/sendspin
This is configured via systemd and works reliably.
Expected behavior
The ESP32 Sendspin player should appear in the Lox-Audioserver device list, just like the Linux Sendspin clients.
Actual behavior
Analysis
The Linux Sendspin client actively connects to the Lox-Audioserver via WebSocket.
The ESPHome Sendspin component does not currently support specifying a WebSocket URL or initiating an outbound connection.
This results in:
My Steps
amped-esp32-s3-plus-idf-sendspinfirmware.Environment
amped-esp32-s3-plus-idf-sendspin(ESPHome-based)Feature request / question
Would it be possible to add support for active WebSocket connections in Lox-Audioserver or adapt the discovery mechanism so that ESP32-based Sendspin players are detected the same way as in Music Assistant?
Music Assistant discovers the Amped ESP32‑S3‑Plus Sendspin player without any problems, so it would be great if Lox-Audioserver could support the same discovery method or allow ESP32 Sendspin clients to register themselves.
Additional context
Adding compatibility would make Lox-Audioserver even more flexible and attractive for users who want to integrate external speakers.
Thanks a lot for your work on this project!
@rudyberends commented on GitHub (Feb 13, 2026):
Right now, this behavior is intentional and not a bug. Lox-AudioServer SendSpin implementation expects clients to connect either via a direct URL or through autodiscovery handled by the client itself. The WebUI only displays clients that are actively connected and does not perform any discovery on its own.
This is the same approach used for Snapcast and Squeezelite. It provides a clean and controlled connection model and works reliably even when running in a container without host network support, as it does not depend on mDNS discovery.
That said, adding client discovery for SendSpin is technically straightforward. If discovery is required for these clients, I will add it in the next beta.
@martinsefcik commented on GitHub (Feb 13, 2026):
In the Sendspin protocol specification, it is stated that:
So we can expect that various Sendspin client implementations rely on the server initiating the connection.
@tokylo commented on GitHub (Feb 13, 2026):
That would be great if you could add this in the next beta – thank you very much.
Of course, a “client‑initiated mode” in ESPHome would also be a possible solution. I already asked in the esp32‑audio‑dock project, but they cannot implement this on their side.
However, if lox‑audioserver were able to perform automatic discovery (similar to how Music Assistant does it), the current ESPHome Sendspin implementation would work immediately and without any modifications.
Since the Sendspin specification explicitly recommends server‑initiated connections, adding this in the next beta would be a great improvement – especially for everyone using ESP32‑based hardware.
I’m looking forward to testing the feature.
@rudyberends commented on GitHub (Feb 15, 2026):
The latest beta includes support for server-initiated connections. I validated it with functional testing, but it has not yet been extensively tested over longer runtimes.
@tokylo commented on GitHub (Feb 15, 2026):
Thanks for adding automatic discovery — my ESP32 is now detected.
However, it still does not play any audio, and the log shows continuous reconnect attempts.
[2026-02-15T11:11:04.528Z][INFO][Sendspin|Connector] [service=direct url=ws://esphome-web-2cc01c:8927/sendspin] Sendspin dialing client
[2026-02-15T11:11:05.097Z][DEBUG][Sendspin|Connector] [message="connect ECONNREFUSED 192.168.178.128:8927" url=ws://esphome-web-2cc01c:8927/sendspin] Sendspin socket error
[2026-02-15T11:11:05.598Z][INFO][Sendspin|Connector] [service=direct url=ws://esphome-web-2cc01c:8927/sendspin] Sendspin dialing client
[2026-02-15T11:11:05.659Z][DEBUG][Sendspin|Connector] [message="connect ECONNREFUSED 192.168.178.128:8927" url=ws://esphome-web-2cc01c:8927/sendspin] Sendspin socket error
[2026-02-15T11:11:05.760Z][INFO][Sendspin|Connector] [service=direct-fallback url=ws://esphome-web-2cc01c:8928/sendspin] Sendspin dialing client
@martinsefcik does it work on your setup?
If yes, I will continue troubleshooting my ESP32.
@rudyberends commented on GitHub (Feb 15, 2026):
I can currently only test using the official sendspin-cli, and with that I can confirm that both discovery and playback via server-side initiated connections are working.
Is the IP address shown in your logs correct? Can you manually connect to 192.168.178.128:8927, for example using a browser, to verify that the service is reachable?
@martinsefcik commented on GitHub (Feb 15, 2026):
I can confirm the client is discovered now in lox-audioserver.

But no payback yet. Based on the logs it ends in some reconnection loop.
@rudyberends commented on GitHub (Feb 16, 2026):
Could you test using this testing image?
ghcr.io/lox-audioserver/lox-audioserver:testing-20260216140139
@tokylo commented on GitHub (Feb 17, 2026):
Thanks for the new testing image — the continuous reconnect issues are gone.
However, my ESP32‑S3 Amped client (ESPHome + PCM5122 + speaker_source + sendspin_source) still cannot play audio coming from the lox-audioserver via Sendspin.
When using Music Assistant, audio plays.
Copilot possible cause:
The lox-audioserver may be sending a different or older Sendspin/FLAC framing format that the new ESPHome speaker_source implementation cannot decode.
@tokylo commented on GitHub (Feb 17, 2026):
How can I update Sendspin? Maybe that would help.
@rudyberends commented on GitHub (Feb 17, 2026):
With the testing container you are already fully up to date. I am still deciding if I want to use that update functionality from within the webbrowser and it is for development only. Those current version numbers are hardcoded and will never reflect the real current version numbers. You are already on 0.2.2
To troubleshoot further we will need the logs. Preferably spam logs from a play attempt and if you can collect them, also the player logs.
@tokylo commented on GitHub (Feb 18, 2026):
Here my logs from Lox‑Audioserver:
[2026-02-18T19:48:01.180Z][DEBUG][LoxoneHttp|Processor] [command=audio/4/roomfav/play/1/noshuffle] command received
[2026-02-18T19:48:01.182Z][INFO][Zones|Manager] [hasParentContext=false normalizedTarget=http://stream.streambase.ch/radiopilatus/aac-64/tunein resolvedTarget=http://stream.streambase.ch/radiopilatus/aac-64/tunein station="" type=favorite uri=http://stream.streambase.ch/radiopilatus/aac-64/tunein/ zoneId=4] playContent
[2026-02-18T19:48:01.184Z][DEBUG][Zones|Manager] [expandedCount=0 isAppleMusic=false isMusicAssistant=false queueSourcePath=http://stream.streambase.ch/radiopilatus/aac-64/tunein/ resolvedTarget=http://stream.streambase.ch/radiopilatus/aac-64/tunein zoneId=4] queue build resolved
[2026-02-18T19:48:01.184Z][DEBUG][Zones|Manager] [authority=local items=1 startIndex=0 target=tunein🚉b64_aHR0cDovL3N0cmVhbS5zdHJlYW1iYXNlLmNoL3JhZGlvcGlsYXR1cy9hYWMtNjQvdHVuZWlu zoneId=4] queue rebuilt
[2026-02-18T19:48:01.186Z][DEBUG][Audio|UrlProxy] [proxyUrl=http://127.0.0.1:7090/streams/proxy?u=http%3A%2F%2Fstream.streambase.ch%2Fradiopilatus%2Faac-64%2Ftunein targetUrl=http://stream.streambase.ch/radiopilatus/aac-64/tunein] proxying audio url for ffmpeg
[2026-02-18T19:48:01.187Z][INFO][Audio|Manager] [hasStream=false label=tunein🚉b64_aHR0cDovL3N0cmVhbS5zdHJlYW1iYXNlLmNoL3JhZGlvcGlsYXR1cy9hYWMtNjQvdHVuZWlu sourceKind=url zoneId=4] startWithResolvedSource
[2026-02-18T19:48:01.188Z][DEBUG][Audio|Manager] [source=tunein🚉b64_aHR0cDovL3N0cmVhbS5zdHJlYW1iYXNlLmNoL3JhZGlvcGlsYXR1cy9hYWMtNjQvdHVuZWlu zoneId=4] playback continued on same source
[2026-02-18T19:48:01.188Z][DEBUG][Zones|Manager] [action=play outputCount=1 outputTypes=["sendspin"] zoneId=4] dispatchOutputs
[2026-02-18T19:48:01.189Z][INFO][Output|Sendspin] [clientId=amped-esp32-essen source=tunein🚉b64_aHR0cDovL3N0cmVhbS5zdHJlYW1iYXNlLmNoL3JhZGlvcGlsYXR1cy9hYWMtNjQvdHVuZWlu zoneId=4 zoneName="OG Bad"] Sendspin play
[2026-02-18T19:48:01.193Z][DEBUG][Output|Sendspin] [activeFormat={"codec":"flac","sampleRate":48000,"channels":2,"bitDepth":16} requestedFormat={"codec":"flac","sampleRate":48000,"channels":2,"bitDepth":16} zoneId=4] Sendspin stream reusing existing pipeline
[2026-02-18T19:48:01.195Z][INFO][Audio|Player:4] [playContentToStartedMs=6 profile=flac ready=true sincePlaybackStartedMs=7 sincePlayContentMs=13 source=tunein🚉b64_aHR0cDovL3N0cmVhbS5zdHJlYW1iYXNlLmNoL3JhZGlvcGlsYXR1cy9hYWMtNjQvdHVuZWlu zoneId=4] playback first audio ready
[2026-02-18T19:48:01.246Z][INFO][Output|Sendspin] [clientId=amped-esp32-essen sincePlayMs=57 sinceStreamStartMs=null zoneId=4] Sendspin first audio frame sent
and ESP32 Sendspin Player:
[20:48:10.832][D][sendspin.hub:625][httpd]: Stream Started
[20:48:10.833][D][sendspin.hub:628][httpd]: Requesting high performance networking for playback
[20:48:10.833][D][media_player:113][httpd]: 'Media Player' - Setting
[20:48:10.835][D][media_player:120][httpd]: Media URL: sendspin://current
[20:48:10.835][D][media_player:126][httpd]: Announcement: no
[20:48:10.835][W][sendspin.decoder:042][Sendspin_0]: Need more data to decode FLAC header
[20:48:10.836][E][sendspin_media_source:583][Sendspin_0]: Failed to process audio codec header
[20:48:10.836][D][pcm5122:130][httpd]: Mute OFF entered
[20:48:10.836][D][pcm5122:180][httpd]: Volume: -29dB
[20:48:10.837][D][pcm5122:130][httpd]: Mute OFF entered
[20:48:10.837][D][pcm5122:180][httpd]: Volume: -29dB
[20:48:10.837][D][speaker_source_media_player:347]: Pipeline 0: Stopping active source before playing: sendspin://current
[20:48:10.850][D][sendspin.hub:534]: Persisted last played server: server (hash: 0x9707005C)
[20:48:10.850][D][sendspin.hub:874]: Group update - state: playing, id: 4, name: OG Bad
[20:48:10.850][D][pcm5122:130][httpd]: Mute OFF entered
[20:48:10.851][D][pcm5122:130][httpd]: Mute OFF entered
[20:48:10.851][D][sendspin_media_source:257]: Pipeline 0 stopping
[20:48:10.851][D][sendspin_media_source:262]: Pipeline 0 stopped
[20:48:10.855][D][sendspin_media_source:105]: sendspin_id: current
[20:48:10.857][D][sendspin_media_source:237]: Started generate task for pipeline 0
[20:48:10.870][D][switch:026]: 'Enable AMP' Turning OFF.
[20:48:10.876][D][switch:065]: 'Enable AMP' >> OFF
[20:48:10.877][D][speaker_source_media_player:303]: State changed to IDLE
[20:48:10.877][D][sendspin_media_source:246]: Pipeline 0 starting
[20:48:10.877][D][sendspin_media_source:251]: Pipeline 0 running
[20:48:10.877][D][switch:022]: 'Enable AMP' Turning ON.
[20:48:10.877][D][switch:065]: 'Enable AMP' >> ON
[20:48:10.882][D][speaker_source_media_player:303]: State changed to PLAYING
[20:48:12.856][D][sensor:118]: 'Amped-ESP32-S3-Plus-SP-Essen Free PSRAM' >> 5740.6 kB
@martinsefcik commented on GitHub (Feb 22, 2026):
I see the same codec related error in my ESP32 Sendspin client log: