Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stream to Sonos breaks at any pause in music #71

Closed
genekellyjr opened this issue Aug 23, 2022 · 25 comments
Closed

Stream to Sonos breaks at any pause in music #71

genekellyjr opened this issue Aug 23, 2022 · 25 comments

Comments

@genekellyjr
Copy link

genekellyjr commented Aug 23, 2022

I've ended up with a Sonos Playbar and tried out this program to stream computer audio to it (thx for making it btw, I'd be up a creek w/o a paddle otherwise).

Sometimes I can start a stream without music playing and then start playing music without issue. (I do this in the attached log) It doesn't always work and sometimes a "running start" is needed (music playing before starting the stream).

I cannot pause the music at all (miliseconds - like tapping pause and unpause as quick as you can is too long) or the stream will break (on the Sonos side I'm guessing). Resuming after pausing either gets no sound out of the Sonos or, if I'm terribly unluckly, a garbled version of the stream.

The stream will abruptly close a while later. If I leave music playing for a long time it seems just fine, but any pause will make the stream to the Sonos fail. Restarting the stream will fix it, until I pause again.

I'm using VB-Audio Virtual Cable as the sound in/out for the computer and sending WAV from 48kHz/24 bit (also tried 41kHz/16 bit with no difference in the pause issue). swyh-rs version 1.4.3.

It seems like a Sonos-specific issue related to silence. I saw in another issue you mentioned that after 2 seconds of no samples you have the program send silence - maybe have an option for immediate silence (or just if device==sonos, immediate silence)? (just guessing since I don't understand how local streaming works deep down)

Also I wasn't able to send FLAC or LPCM to the Sonos, stream just immediately closes when trying either format.

log_nogo.txt

Addtl. info: Autoresume play will automatically restart the stream after the stream abruptly ends from the silence. Takes a bit for Sonos to kill the stream so it's not quite a good bandaid. "No Chunked Tr. Enc." (disable_chunk) being checked doesn't seem to change any behavior.

@dheijl
Copy link
Owner

dheijl commented Aug 24, 2022

A few thoughts,

  • LPCM does not work with Sonos
  • I did not know that WAV/24bit worked with Sonos
  • I would have expected FLAC to work with Sonos

About the silence "hack" not working: is it possible that some configuration in the Sonos is responsible, like the amount of buffering that is too small or some timeout value? I've never used a Sonos, I have no idea, but it seems to work for some.

Reducing the "silence" timeout value is going to cause even more problems, as the HTTP stream does not contain timing information, and the Sonos has to use a reasonable amount of buffering (read ahead) to prevent drop-outs due to network latency.

I might consider making the silence feature an option with a configurable timeout in the UI, allowing people to experiment.

@genekellyjr
Copy link
Author

genekellyjr commented Aug 25, 2022

Thanks for getting back to me!

I suspect swyh-rs was having the WAV audio remuxed to 16 bit - red herring there, my b.

I found two "levers" in the Sonos app which were:

  • audio compression - only for line-in audio syncing with other Sonos devices, I don't have any others so that didn't change anything
  • group delay - I'm guessing also for syncing with other Sonos devices, changing it (was set to 75 ms as default) to 2000 ms changed nothing so it doesn't do anything here either sadly

This Sonos thing I ended up with doesn't support airplay or anything modern, it might be on a different codebase vs the newer things that can do airplay - so others with different Sonos things might be just fine.

I loaded up the original swyh and its MP3 mode was able to stream but suffered from the same issue - when there's no samples for a moment then there's no sound afterward and then the stream is closed shortly after. Seems its definitely a Sonos-specific thing (and might even be Sonos Playbar specific) since both implementations don't work with it.

I tried several other speaker methods (Steam streaming speakers, digital audio S/PDIF, monitor speakers) and nothing different, so not the VB-Audio Virtual Cable.

I understand that shortening the silence timeout may be problematic; I saw in another thread you suggested injecting too-quiet-to-hear white noise (for FLAC compression side-stepping), that might work well here. Constant samples for the Sonos to work with would keep it busy and the stream alive - maybe a toggle for that (even if hidden in the config file and not the UI itself for ease) might be the right bandaid for Sonos' issues.

I tested playing a 10 hr white noise youtube video in the background on minimum volume and that made the stream work as you'd expect, so if the swyh-rs program could do that automatically that would probably fix the issue without extra steps.

Let me know if you implement it for the FLAC issue or this and I'll test it out!

@dheijl
Copy link
Owner

dheijl commented Aug 28, 2022

I think that shortening the "silence" timeout will unavoidably introduce hiccups in the audio, as the bitrate of the network is much higher than the bitrate of the audio stream, so the streaming part of swyh-rs is constantly waiting for an audio buffer to arrive that can be sent on to the network. There is really no way to tell what is a "normal" delay between audio buffers before it becomes a "no audio is being played".
There is also no way (that I know of) for the audio capturing thread to know that nothing is being played, it just waits for audio buffers to arrive on a WASAPI callback and forwards those to the streaming thread(s).
I could easily send the low-volume white noise instead of silence for WAV/LPCM, but the problem remains that there is really no way to know when to start sending it to keep the Sonos happy without introducing white noise hiccups in the "normal" audio.
If you are prepared to test it I'll make a new beta with the white noise and a (hidden) silence time-out later this week.

@genekellyjr
Copy link
Author

Happy to test! I see there's plenty of issues with silence detection and buffers, etc. - but constant really quiet white noise should be an acceptable bandaid. Definitely not this program's fault that Sonos isn't following local streaming standards; but I'm grateful for a targeted "fix" to try!

A suggestion might be to "target" the noise to like 21.5 kHz via not true white noise but rather a fuzzed 21.5 kHz sine wave (fuzzing isn't even required - but may be important for that FLAC compression issue in the short term). I don't know what methods you have available to produce sound in rust, but at that frequency no one would be able to pick out the very quiet noise/tone anyway! I suggest 21.5 kHz since it's above the possible human hearing max freq (20 kHz) and below the Nyquist freq for the usual sampling freq of 44100 Hz (22.05 kHz) - sounds above that freq would get aliased to audible freqs (if there's not digital filters in the sound chain to keep it within human hearing/the Nyquist range).

@dheijl
Copy link
Owner

dheijl commented Aug 31, 2022

If you feel like it you can test with the new 1.4.4-beta2.

The default timeout (CaptureTimeout in config.toml) is now 250 msec.

@omoknen
Copy link

omoknen commented Aug 31, 2022

Hi.
I am a new user, and I was also having a similar problem with sonos sl one. I don't use a virtual cable. I am also going to try the new beta and see if this helps.

I really appreciate the quality of the sound. Thank you for creating this streamer.

@genekellyjr
Copy link
Author

genekellyjr commented Sep 1, 2022

Looks like unfortunately it did not affect the Sonos silence issue. The cut out issue is the same on 1.4.3 and 1.4.4-beta2. Thank you for making a build to try, though!

Here is a recording of the issue using 1.4.4-beta2: https://www.dropbox.com/s/s0a45638wv7mjx3/sonos_issues.mp3?dl=0 Very quick pauses are OK but if it's too long it will either be garbled or completely fail. In the recording I pause quick enough to keep the music going, and eventually pause long enough to make it be garbled. Then I pause for long enough to kill the stream (music cuts out).

See edit- A very short timeout might fix it (my estimate of the pauses that don't cause issues are 120 ms, based on the audio sample - so 75 ms to be safe?), though I don't know if it will impact the stream or other streamer receivers. A constant, quiet white noise/high-frequency noise generator would also be a "band-aid" fix though less elegant than actually getting it to work (as correct as it can work).

Edit: I realized the config.toml wasn't "cargo.toml" and the value was editable live! 250/100/75/20 ms didn't fix the issue but didn't seem to impact the stream in anyway that I could tell. 10 ms started to get a bit weird and it started to fall behind live. Setting it to 2 ms causes many problems (dropped bits, fell behind live quickly) but still doesn't fix the silence breaking the stream issue. I'm not sure why but this Sonos thing seems to want a constant flow of something else it kicks up its feet nearly instantly. Let me know if you build in an option for constant, low-level noise of some kind; that may be the only "fix" for Sonos...

@dheijl
Copy link
Owner

dheijl commented Sep 1, 2022

Thanks for testing!
Unfortunately this looks like a "can't be fixed", except at the Sonos side, and that isn't likely to happen because AFAIK Sonos does not officially support DLNA.
I will revert to the previous behaviour (send 250 msec of silence after 2 seconds of no sound), but keep it configurable in the config.toml.

@dheijl dheijl added the wontfix This will not be worked on label Sep 1, 2022
dheijl added a commit that referenced this issue Sep 1, 2022
- handle multiple identical soundcards
- make CaptureTimeout configure in config.toml (see issue #71)
- use fltk-bundled on Windows
@omoknen
Copy link

omoknen commented Sep 1, 2022

I have two Sonos One SL's and had similar results. I would agree it is probably Sonos behavior
I use Windows 10 with MusicBee as my podcast source.
I have SWYH-RS with WAV - No Chunked Tr. Enc. selected.
Most of my initial problems were that I needed to turn off sound enhancements and needing to set the speaker to 16 bit 44.1KHz.

I don't know how it works actually but here is what I have seen.

I have to use SWYH-RS Sonos Renderers to get them to play on the Sonos speakers without the sound breaking up. (Can not use the http stream)
I can't group the Sonos speakers together using the Sonos App because it actually will cause the sound to break up, but that is okay because they play in sync when I turn each one individually.
If I turn off the sound source (MusicBee) while leaving SWYH-RS causes SONOS to turn off the speaker after about 29 seconds (tried it several times so I believe this is an autoshutoff?)
I can turn the stream back on by selecting Play on the Sonos App (either pc version or android)
When I first start SWYH-RS it is better if I turn on the source (MusicBee) on first, and on the first try I have to turn on the RS Sonos Renderer more than once before the Sonos App will accept it, or maybe I am being patient and it takes Sonos awhile before it acquires it.

I am still using the beta so I will see if things change later. It is fairly stable right now.

@dheijl
Copy link
Owner

dheijl commented Sep 2, 2022

Thanks for your insights! This is really useful information, that could go in the Readme.

When you say:
I have to use SWYH-RS Sonos Renderers to get them to play on the Sonos speakers without the sound breaking up. (Can not use the http stream)

Not having any Sonos myself, what does this mean exactly? Do you have to use the renderer buttons in the app, and you can't use the Sonos app to point it at the http stream? If that is the case, it is to be expected because according to their docs the Sonos adds some extra HTTP requests using range headers that are not supported by swyh-rs before it starts streaming.

@omoknen
Copy link

omoknen commented Sep 2, 2022

Yes. I have to use the renderer buttons in the SWYH-RS application.
Okay that is good to know about Sonos. I am new to Sonos as well, so I am often confused.

You would thing after all these years their applications would be better documented and were actually good, but that hasn't been my experience.

@genekellyjr
Copy link
Author

genekellyjr commented Sep 3, 2022

Thanks to this being open source I was actually able to finagle something that fixes my issue! I don't know how to use github's push and pull and branch stuff, but attached are the main.rs (added a silence injector using cpal, I tried rodio but it wouldn't even install?? rust is difficult) and the configuration.rs (which has a new InjectSilence boolean). The silence injector is just the basic example in the cpal docs. The other edits also involve mimicry of what was there!

For the changed code, in main.rs look for "run_silence_injector" for the two places that code was added (the thread maker that runs run_silence_injector and the run_silence_injector function itself) and in configuration.toml look for "inject_silence".

I think it is definitely looping over itself and causing larger than needed CPU usage - but I def can't figure out how to "wait until play is done" to start the loop over. Hopefully someone wiser in the ways of rust can help with that.

Would you ponder adding this into the main branch @dheijl? Since it is behind a hidden config option the wasteful CPU code won't hurt anyone unless they actually need it to make their very difficult Sonos Playbar work. (and if you or someone else can make it wait, hopefully it's not so bad then)

github wouldn't accept an uploaded .rs so they're .txt
main.txt
configuration.txt

Here is a link to the build that injects silence so the stream never dies (if the boolean InjectSilence=true in the config.toml file in %UserProfile%\.swyh-rs; defaults to false): https://www.dropbox.com/s/9g2o4x7w1fj6cc0/swyh-rs.exe?dl=0

Edit: if you do implement it, it might be better to put it in the UI code where the silence injector activates when streaming (on click) but stops when not.

@dheijl
Copy link
Owner

dheijl commented Sep 3, 2022

That's a brilliant idea, using the Windows soundmixer to mix in a never ending stream of silence with the actual audio! This is definitely going in. Just have to check how Linux handles this. This indeed what open source is all about.

@dheijl dheijl removed the wontfix This will not be worked on label Sep 3, 2022
@omoknen
Copy link

omoknen commented Sep 3, 2022

I made another observation about my Sonos One SL Speakers which specifically is a Sonos PROBLEM. I have used some direct internet streams (radio paradise, somafm) and my PC SWYH-RS stream. The Sonos will shut off (sometime over an hour plus) even when there is NO SILENCE in the stream. I even tried keeping either the PC application or the mobile version active, but it seems to want you to wake either app or it will shut off over time. Anyway, It just shut offs and I have to restart it, so it if this happens it isn't SWYH-RS. (These are all apart of "Tune-In" Guest service "My Radio" which is where it allows you to save and access custom radio streams.)

dheijl added a commit that referenced this issue Sep 4, 2022
This should fix Sonos aborting the connection when pausing music, contributed by @genekellyjr (see issue #71)
@dheijl
Copy link
Owner

dheijl commented Sep 4, 2022

I integrated your suggestion in 1.4.5-beta, I'll try to make a new prerelease tomorrow or Tuesday.
The only change I made is remove the CPU usage problem, by moving the stream/play out of the loop and keeping the thread alive indefinitely doing nothing just to keep the silence stream playing.
You also have to make sure that the audio output of swyh-rs is the same as your music source in the Windows audio mixer.
Not tested on Linux yet.

@genekellyjr
Copy link
Author

I built the 1.4.5-beta successfully and it does work and solve the CPU usage problem! Clever solution - thanks so much for the help on this issue!

I'll run this solution for an extended time today, but this is def as good as it gets I think! Hope this new build fixes your playback issues though @omoknen (at least that 29 sec auto shutoff issue...)! Here is the 1.4.5-beta .exe I built if you want to try it: https://www.dropbox.com/s/buwdo8t42yiz4sz/swyh-rs.exe?dl=0 - or you can wait for the official prerelease!

@dheijl
Copy link
Owner

dheijl commented Sep 5, 2022

The 1.4.5-beta prerelease is now available.

@omoknen
Copy link

omoknen commented Sep 5, 2022

I tried the new beta, but what happens is as soon as there is no sound Sonos stopped. Sonos is so Picky! You can't access your own diagnostic logs for devices.

@genekellyjr I also wanted to tell you if you didn't already know that there is a web interface to the Sonos device.
It doesn't help specifically with this problem, but I don't know all the values. It did tell me that I don't have a wireless problem which is the stock answer from Sonos for all problems with cutting out.

http://<sonos_ip>:1400/status
http://<sonos_ip>:1400/support/review

References:
https://en.community.sonos.com/troubleshooting-228999/how-i-fixed-my-sonos-installation-ie-no-dropouts-6814453
https://bsteiner.info/articles/hidden-sonos-interface

@dheijl
Copy link
Owner

dheijl commented Sep 5, 2022

Did you edit the config.toml file and change InjectSilence to true?

@genekellyjr
Copy link
Author

1.4.5-beta works great as well!

Only question for the prerelease text: since swyh-rs is pulling audio from the device audio_output_device and injecting silence into device audio_output_device, should that take precedent over the Windows sound mixer default setting? Basically the silence should always be on the device that swyh-rs is capturing - I might be misunderstanding how complicated sound devices and the OS interaction are though!

Also did not know about the special web interface, the status works but is just cryptic stuff and the support/review does not work on the Sonos Playbar (times out, so it tries). Playbar seems to be in its own special little rung of Sonos hell - at least it seems to work well now - tested for hours with no issues!

@omoknen
Copy link

omoknen commented Sep 5, 2022

Did you edit the config.toml file and change InjectSilence to true?

My bad. No I did not. I missed that in the rush. I will go that and try again.

@omoknen
Copy link

omoknen commented Sep 7, 2022

The beta works great. I do not get closures from pausing a source. Your program works better than Sonos. :)
Thanks for all your hard work.

@dheijl
Copy link
Owner

dheijl commented Sep 7, 2022

Thanks for your kind words!

@DanteDT
Copy link

DanteDT commented Feb 24, 2023

Thanks for testing! Unfortunately this looks like a "can't be fixed", except at the Sonos side, and that isn't likely to happen because AFAIK Sonos does not officially support DLNA. I will revert to the previous behaviour (send 250 msec of silence after 2 seconds of no sound), but keep it configurable in the config.toml.

Just to enthusiastically and gratefully note that updating config.toml works for me:

  • CaptureTimeout = 250

The default for version 1.6.0 for me was 2000.

This solves my issue of sonos going silent every time my Win11 app (VLC, Firefox, etc.) advances tracks or has some sort of brief silence. This makes this SWYH and now SWYH-RS the most helpful fixes that I can remember for something that should have not been broken in the first place (i.e., Sonos refusing to play what I hear). This tip should be in the root README for all Sonos users.

(I'm pretty sure this helped at least as much as the 1.6.0 fix of changing the default for InjectSilence from false to true, a tip which is emphasized in the root README for this current v1.6.0)

Many thanks!

@dheijl
Copy link
Owner

dheijl commented Feb 24, 2023

Thanks, I added the 250 msec recommendation to the Readme.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants