svrooij / node-sonos-ts

:speaker: Sonos control library, use this library in your own appliction.
https://sonos-ts.svrooij.io/
MIT License
84 stars 18 forks source link

Use audioClip endpoint? #67

Closed oscar-b closed 7 months ago

oscar-b commented 4 years ago

Wouldn't it make sense to use the /audioClip API for notifications?

https://developer.sonos.com/code/making-sonos-talk-with-the-audioclip-api/

svrooij commented 4 years ago

At first glance they mention these libraries, which makes me think that you would still need to run something yourself.

google-tts-api: This puts a nice, neat, promise-ready wrapper around the Google Text-to-Speech API. simple-oauth2: A handy package to simplify the process of getting and refreshing access tokens. node-persist: Mimics the HTML5 localStorage API used in browsers, so it’s pretty easily understood.

And the Sonos developer website, only talks about the cloud service to control your speakers. While ok, it lakes most functionality that you're getting when controlling the speakers locally.

Using the (cloud) audioClip endpoint sounds nice, but are only supported in a V2 system (and I'm on the "I'm not updating and splitting my system"-camp).

oscar-b commented 4 years ago

Using the (cloud) audioClip endpoint sounds nice, but are only supported in a V2 system (and I'm on the "I'm not updating and splitting my system"-camp).

Would you accept a PR adding this functionality to your library, as a separate endpoint?

svrooij commented 4 years ago

I'm willing to consider, but I'm kinda lost in how it should be working.

You probably need (might not be complete):

That said, it sounds like a nice improvement, I'm thinking you would be creating a new (as in extra) PlayNotification method? Like PlayNotificationCloud?

Apart from that, I'm wondering if they didn't make this endpoint locally on the S2 system, or if they made somewhat the same logic in the cloud. That would also be worth investigating. Because that would be thinks a lot easier. (Since you wouldn't need all cloud stuff.

oscar-b commented 4 years ago

Right, I didn't look that closely at all your code yet, I assumed you already had the auth handling done already. But if you're not using any cloud functionality yet that requires this I understand that you don't :/

I haven't seen any information about providing this directly on the speakers, unfortunately. Not sure why they don't, it's a shame, but the functionality it provides seem far superior than the workarounds of saving speaker state and restoring so it might be worth it anyway.

One thing that doesn't seem possible yet with the audioClip endpoint is targeting groups of speakers, only individual (or paired I think).

There's also this project, based on the Sonos example: https://github.com/kevinvincent/hassio-addons/tree/master/sonos-audioclip-tts

svrooij commented 4 years ago

I haven't seen any information about providing this directly on the speakers, unfortunately. Not sure why they don't, it's a shame, but the functionality it provides seem far superior than the workarounds of saving speaker state and restoring so it might be worth it anyway.

Have you seen the PlayNotification method? There isn't any saving/restoring required. It's all handled by this library (and so far, with a delay of 700ms, I haven't had any problems with it.)

Sonos either implemented the same logic in the cloud, or they made a local endpoint on the speaker with the same logic. Somewhere the current song/playlist/volume has to be saved and restored afterwards.

If they made this endpoint on the local devices it would be great to check it out and see if it's better then the current solution.

oscar-b commented 4 years ago

Have you seen the PlayNotification method? There isn't any saving/restoring required. It's all handled by this library (and so far, with a delay of 700ms, I haven't had any problems with it.)

Yeah, looked like the same way Home Assistant does it, and it have issues with resuming streaming from for instance Spotify.

Sonos either implemented the same logic in the cloud, or they made a local endpoint on the speaker with the same logic. Somewhere the current song/playlist/volume has to be saved and restored afterwards.

No, it ducks the playing audio and overlays the audioClip audio on top of it.

svrooij commented 4 years ago

How does your home assistant connect to sonos? Is it using this library or some other way (maybe sonos2mqtt? I think by default home assistant uses another library, that maybe didn't implement notifications correctly. They made a save/restore thing, that doesn't restore everything.

I know someone was trying to use sonos2mqtt together with home assistant, but I'm not sure what the status of that integration is. This library (and the sonos2mqtt) are for sure not the same as the default home assistant integration.

No, it ducks the playing audio and overlays the audioClip audio on top of it.

This means they changed the speaker software (and maybe there is an endpoint for it). Could you make a fork and run this command in the terminal (with an IP of a S2 speaker in it)?

cd src/generator/
SONOS_HOST=192.168.x.x node service-generator.js --save-description --load-files --generate

I'm really curious if it would change the discovered-services.json file.

oscar-b commented 4 years ago

No, it ducks the playing audio and overlays the audioClip audio on top of it.

This means they changed the speaker software (and maybe there is an endpoint for it). Could you make a fork and run this command in the terminal (with an IP of a S2 speaker in it)?

cd src/generator/
SONOS_HOST=192.168.x.x node service-generator.js --save-description --load-files --generate

I'm really curious if it would change the discovered-services.json file.

No changes to discovered-services.json after running that, it only generated a new file: discovered-services.gen2_S18.json

svrooij commented 4 years ago

No changes to discovered-services.json after running that, it only generated a new file: discovered-services.gen2_S18.json

Bummer.....

Your message still got me thinking. They made a cloud api and they also made a new actually rest (no more soap πŸ˜„:tada:) api on the local device, but I never could get it to respond. So what about if I take a token from the cloud, and use that on the local api.

Care to investigate?


My guess

Remote URI: https://api.ws.sonos.com/control/api/v1/players/{playerId}/audioclip.

Local URI http://sonosIp:1400/api/v1/audioclip


I'm not against using the new api, but would rather not sacrifice all the control we have at the moment (local control and super fast notifications on the local network) over using the cloud for everything. But if we could use the cloud token to control the speakers over the local network that would be great. You can then also switch between then (eg. devices reachable = local control / device unreachable = cloud control).

svrooij commented 4 years ago

Local API endpoints:

Screenshot 2020-08-13 at 10 52 30

Sadly no response (when tried with a cloud token):

Screenshot 2020-08-13 at 11 01 51

I found you need to set Header: Authorization value: Basic something1\r\nX-Sonos-Controller-ID: something2

where I don't know what to put in something1 and something2.

jnbht commented 3 years ago

To give some new sparks on this topic. I have tested the audioClip feature with this node-plugin: https://github.com/kevinvincent/hassio-addons/blob/master/sonos-audioclip-tts/

And it works on older speaker too (Play:3, Play:1, Playbar) He uses the cloud API though. I do not know if it is possible to push the commands locally.

I keep looking. Would be so awesome!

svrooij commented 3 years ago

I’m all for this endpoint, but for now I’m delaying the S2 upgrade for as long as possible, because I have some old Play5 speakers that cannot be upgraded, so I will be left with a splitted system. Anyone want to sponsor me a test speaker, so I can test this out. Creating this is probably easy. Also thinking about running some server to handle the redirect part

jnbht commented 3 years ago

Ah, the got old Play:5. Loved it! Allright. I get that you won't switch with this speaker ;)

hklages commented 3 years ago

SONOS documentation at developer page

The Control API on the LAN is not available for wide release. We’ll add a blog post when it is available. Use the Control API on the cloud to communicate with a Sonos player. The Sonos cloud manages ...

thoelzl commented 1 year ago

The Control API is also available on local networks via a websocket connection to the speaker. See my comment on this issue: https://github.com/bencevans/node-sonos/issues/530

svrooij commented 1 year ago

@thoelzl interesting find!! I always put this of because of the need for a cloud connection. In the mean time we switched to a splitted system so I should be able to test it.

Few questions though:

thoelzl commented 1 year ago

I have tested the use case of your first question. Send command to Player A with the id of player B does not work. You need a dedicated connection with the device for the audioclip command to work.

Groups should be supported but not with the audioclip command. This command is currently only supported on player level, not groups.

I have only tested a few simple commands, so i can't comment on your last question.

svrooij commented 1 year ago

@thoelzl πŸ‘€πŸ‘‡

image

thoelzl commented 1 year ago

Great, thanks for the fast solution!

github-actions[bot] commented 1 year ago

:tada: This issue has been resolved in version 2.6.0-beta.5 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

svrooij commented 1 year ago

@thoelzl could you let me know what you think? Does it work for you? If you also use sonos2mqtt, you can also switch to use the new endpoint. https://github.com/svrooij/sonos2mqtt/discussions/191

hklages commented 1 year ago

... that's a really cool feature - love it!

svrooij commented 1 year ago

@hklages does it work for you? What is your first experience?

hklages commented 1 year ago

The first tests were excellent. Even in a group the specified player played the clip. Tomorrow I will do more tests. What happens when I omit the volume? Do you set a default volume or is the current player volume used?

On Thu, Mar 16, 2023, 20:53 Stephan van Rooij @.***> wrote:

@hklages https://github.com/hklages does it work for you? What is your first experience?

β€” Reply to this email directly, view it on GitHub https://github.com/svrooij/node-sonos-ts/issues/67#issuecomment-1472652208, or unsubscribe https://github.com/notifications/unsubscribe-auth/AEDZCH7HFLD5WP6EBBVZBLLW4NVVBANCNFSM4PZME2PA . You are receiving this because you were mentioned.Message ID: @.***>

svrooij commented 1 year ago

It will either use the players volume if that is pre-loaded (when using the events) or 25.

All the way at the end in this line.

https://github.com/svrooij/node-sonos-ts/blob/0eb55f498178a3ef717077b5526d4f9d45e4f5a5/src/sonos-device.ts#L664

hklages commented 1 year ago

Did some more testing on Beam, Roam, Play:5, Play:3, Play:1. The audio clip works fine on all players with both http locally and https internet. If the players are grouped, all are going quite and the selected player plays the notification. To have them all playing the notification I can send to all players.

The "onlyWhenPlaying=true" does not work - maybe because I don't use your event manager.

I use PlayNotificationAudioClip:

await selectedPlayer.PlayNotificationAudioClip({
      trackUri: validatedUri,
      onlyWhenPlaying: validatedOnlyWhenPlaying, 
      volume: validatedVolume
    })
hklages commented 1 year ago

... looking at the code an api key is needed and I assume it is yours. Right?

svrooij commented 1 year ago

... looking at the code an api key is needed and I assume it is yours. Right?

No comment.....

πŸ‘‡ https://github.com/bencevans/node-sonos/issues/530#issuecomment-1430039043

svrooij commented 8 months ago

image