Giter VIP home page Giter VIP logo

Comments (6)

stephen avatar stephen commented on June 14, 2024

Unfortunately, I haven't found a way to get Sonos devices to support direct PCM streams, as AirSonos currently takes advantages of Sonos' mp3 radio stream support to work.

from airsonos.

rainforest1155 avatar rainforest1155 commented on June 14, 2024

It looks like Sonos does accept WAV if it's coming from a UPNP server like this Foobar plugin (http://www.foobar2000.org/components/view/foo_upnp). Capturing a UPNP packet, it looks like this:

Origin: OpenSource.UPnP.HTTPSession [13092880]
Time: 31.07.2014 02:38:15

NOTIFY /RINCON_xx_MR/urn:upnp-org:serviceId:AVTransport HTTP/1.1
HOST:  serverIP:53702
CONNECTION:  close
CONTENT-TYPE:  text/xml
SEQ:  24
NTS:  upnp:propchange
SID:  uuid:RINCON_xx_sub0000000009
NT:  upnp:event
Content-Length: 2195

<e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0"><e:property><LastChange><Event xmlns="urn:schemas-upnp-org:metadata-1-0/AVT/" xmlns:r="urn:schemas-rinconnetworks-com:metadata-1-0/"><InstanceID val="0"><TransportState val="TRANSITIONING"/><CurrentPlayMode val="NORMAL"/><CurrentCrossfadeMode val="0"/><NumberOfTracks val="1"/><CurrentTrack val="1"/><CurrentSection val="0"/><CurrentTrackURI val="http://serverUUID.x-udn/content/6955e868e77566245c13b19f2fd49146.wav?profile_id=0&convert=wav"/><CurrentTrackDuration val="0:00:00"/><CurrentTrackMetaData val="<DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:r="urn:schemas-rinconnetworks-com:metadata-1-0/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"><item id="-1" parentID="-1" restricted="true"><res protocolInfo="http-get:*:audio/wav:*">http://serverUUID.x-udn/content/6955e868e77566245c13b19f2fd49146.wav?profile_id=0&amp;convert=wav</res><r:streamContent></r:streamContent><r:radioShowMd></r:radioShowMd><dc:title>6955e868e77566245c13b19f2fd49146.wav?profile_id=0&amp;convert=wav</dc:title><upnp:class>object.item.audioItem.musicTrack</upnp:class></item></DIDL-Lite>"/><r:NextTrackURI val=""/><r:NextTrackMetaData val=""/><r:EnqueuedTransportURI val="http://serverUUID.x-udn/content/6955e868e77566245c13b19f2fd49146.wav?profile_id=0&convert=wav"/><r:EnqueuedTransportURIMetaData val=""/></InstanceID></Event></LastChange></e:property></e:propertyset>

I did a bit of trial and error hacking and managed to replace the Lame encoder in nicercast with the wav writer (https://www.npmjs.org/package/wav). To show you, I forked nicercast here:
https://github.com/rainforest1155/nicercast/blob/master/index.js

and in Airsonos, I changed this section:
device.play({
uri: 'x-rincon-mp3radio://' + ip.address() + ':' + port + '/listen.m3u',

to:
device.play({
uri: 'http://' + ip.address() + ':' + port + '/listen.m3u',

While playback is not without interruptions, Sonos does recognize and play back the stream.

I was now thinking of trying to utilize the AVTransport.prototype.SetAVTransportURI function to see if that would allow for a better (uninterrupted) stream. I suspect that the Foobar UPNP server might be utilizing that as well to serve up the wav stream.

Note that I'm not versed at using Github or coding in general, so I'm not sure if I did the forking properly or if I would still need to update any of the package.json info to make it proper, like in terms of attribution.
The code is also just a trial and error attempt at replacing existing code with something else. So it's not following any coding guidelines nor did I do proper testing.

from airsonos.

stephen avatar stephen commented on June 14, 2024

Ah, amazing. This is awesome!

The trick for the interruptions is the mp3 metadata interleaving. You can remove this by changing 8192 to 0 https://github.com/rainforest1155/nicercast/blob/master/index.js#L55-L61.

One problem is it does seem like there are more audio frames being dropped via PCM, assumably because there's more PCM data to send over the wire.

Possible solution could be to add some buffering mechanisms to nicercast.. I'll investigate further when I have some time. :)

from airsonos.

rainforest1155 avatar rainforest1155 commented on June 14, 2024

Thank you for the pointer. Though, setting those values to 0 seemed to make the matter worse. Therefore, I simply commented the 2 metadata related sections out for now. That seems to improve things.

from airsonos.

stephen avatar stephen commented on June 14, 2024

Hmm, interesting. The values are basically the offsets at which the stream attempts to inject metadata for the Sonos controller to read; removing the metadata-related streaming would be sufficient to stop the (corrupted stream data) related problem.

from airsonos.

jishi avatar jishi commented on June 14, 2024

I just wanted to share my experience with this.

Sonos identifies stream-type using url suffixes when you set a AVTransportURI directly, and disregards any content-type passed by http headers. Because of this, a raw PCM stream, need to generate a url which simulates a file with the ending .wav, like this:

http://10.0.0.1/stream.wav

I'm not sure how it handles m3u files (the poster claimed that it worked? did the embedded url end with .wav?)

Regarding buffering and dropouts, the optimal buffering method would be having the Sonos player buffer and delay playback accordingly. This is however not possible to control, since it is expected to be able to read the complete file in advance (since we are emulating a UPnP Media server). My solution to this was to generate silent data and send it initially before the actual stream starts, that way the player is busy rendering silent data until it will consume the actual stream.

Sonos players are also especially dumb when it comes to handling buffer underruns. It will actually drop samples, when it can not keep up, making the situation even worse. I'm not sure about the reasoning for that, but very annoying in this case.

I have made some tests, and I seem to get a pretty stable streaming using raw PCM when initially sending 150 000 samples of silence (4 bytes per sample). This translates to roughly 3 seconds delay.

Using a wired connected between both computer and the Sonos player, I could actually manage as low as 100ms delay with a small enough silent buffer, but this is really a best case scenario. Also, the quality of your WiFi and SonosNet will affect which buffering size that is appropriate.

from airsonos.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.