Script for Sonos Speakers to do Text-to-Speech and Handle Typical Oddities

@Talvish thanks!

Hey @Talvish great work on this - really love what you’ve done :slight_smile: and really takes some of the silly wrinkles out of TTS through Sonos for my automations.

I’m still fairly new to this - is there an easy way to call the script from Lovelace dynamically i.e. integrate it into a dashboard, with configurable parameters? I’ve tried the following but the script doesn’t seem to like me using Helpers as service_data. My Helper options for sonos_entity_selector are the entity_ids for each speaker e.g. media_player.sonos_move:

type: entities
title: Text to Speech
entities:
  - entity: input_text.sonos_tts_text
    type: custom:text-input-row
    name: Text
  - entity: input_select.sonos_entity_selector
    name: Select Sonos Device
  - type: call-service
    name: ' '
    icon: ' '
    action_name: Announce...
    service: script.text_to_speech_on_sonos
    service_data:
      entity_id: input_select.sonos_entity_selector
      message: input_text.sonos_tts_text
      volume_level: 0.4
show_header_toggle: true
state_color: false

Am I missing something obvious?

Thanks in advance!

Investigated a bit further and found this HACS repo, which basically enables what I’m after:

As you were :slight_smile: and thanks again for this script - it’s great.

Thanks @bungamungus … I know many (most?) people have customized their UIs, but oddly I never have. All my interactions with HA are automated (e.g. by events) or by physical hardware (e.g. Pico remotes), so I have no experience there.

Glad you found what you were looking for!

Would that be possible somehow to ungroup the speakers ( if they were left in group ) and play the announcement on a specific speaker only?

You could create a script to do a Media_player: unjoin then have the TTS script run. After the script rejoin the player to the group. It can get messy if you unjoin the master I’ve found so I don’t use that any longer. There is a Sonos: Snapshot if you need to track where all the speakers were. I haven’t found an easy way to exclude a speaker in my case.

I’m creating a calendar automation that speaks the calendar events through a sonos speaker. I would need to pass this {{ trigger.calendar_event.summary }} as message to the Text-to-Speech on Sonos script.
When trying this, the Sonos speaks the words “object object” instead of the value of the trigger.
Sorry if this was already discussed here or on the github page and I just completely missed it.

Note: When saving the automation and opening it again, I see the action is saved with this:
service: script.1676016944306
data:
entity_id: media_player.keuken
message:
"[object Object]": null
volume_level: 0.26
enabled: true

So that’s probably the reason why it says ‘object object’.
Anyone knows how to get this script say the contents of such variable?

Update. Ok, Looks like it might work like this:
message: "\"{{ trigger.calendar_event.summary }}\""

I have discovered a weird behavior when using this script with Groups integration. The issue may be related to an issue with that integration described here:

Media Player Group missing Attributes #85338

If I create a group of Sonos speakers using that integration and try an test this script in the Developer Tools it does not see the defined Group as an entity.

Using the Text-to-Speech service it does -

Here is the group defined using the integration -

Any idea on why it works with TTS but not the script?

The script’s entity_id field restricts the selection to media_players created by the Sonos integration.

You created the group of media_players, not the Sonos integration, so that’s why it’s excluded from selection.

In contrast, the TTS service call makes no restrictions other than the entity must be a media_player, so that’s why your grouped media_player is available for selection.

Hello @Talvish

First, thanks for this amazing blueprint :slight_smile:

I wanted to share something i’ve been adding to my script right before the tts_engine call :

  - service: media_player.play_media
    data:
      media_content_id: "media-source://media_source/local/TGP - Janet Bing.mp3"
      media_content_type: music
    target:
      entity_id: "{{ entity_group_leader }}"
  - delay:
      milliseconds: 800

with this sound : the good place janet sound effect - YouTube

it’s been working great, would be awesome to be an integrated feature if that inspires you :slight_smile:
it could be even more generic and allow to call an external script (and passing entity_group_leader to it), for example to make a lamp blink.

EDIT: realizing a few hours later, that in case of external script, that it should be in a parallel alongside the tts_engine call.

1 Like

For some reason no matter the entity specified, any message I run through this script gets played on EVERY sonos device in my account.

hey!
ive no idea what ive done wrong here but i keep trying and reading the comments but i cant get this to work.

ive imported the blueprint and then when i go to “blueprints” and try to create the script, i keep getting “error 500”

Same problem here. Error 500 when I try to create a script form the blueprint. Any advice? My automations.yaml file has ids set for each automation (which apparently need to be set in order to use blueprints)

Hey @Talvish: I have a strange behavior with playback resuming.
When I listen to a radio station resuming is working as expected.
But when I listen to Apple Music the script only resumes my spoken tts instead of resuming the playback.
So eg when someone rings I play “Ding Dong” and afterwards like an echo I hear it again (quieter because I raise the volume for TTS)
I even tested and confirmed it with Min. Wait, the time set is waited and afterwards the TTS sound is played again.
My setup is a group (of 2) symfonisk speakers.

Edit: When I do it on my own with a
-Sonos.snapshot
-stop music
-sonos.restore

it works as expected, even with Apple Music playing.
So I would guess it is a timing issue in script.

Edit2: Forget my edit. I tried it without tts in the middle.
The problem is in the tts, no matter if I use polly or google.
It looks like the playing of a different sound breaks the connection to Apple Servers which cannot be re-established on sonos.restore. But I’m just guessing and I think I need to address my problem to the Sonos module.

Edit3: Sorry for so many edits. But just FYI, the problem is not Apple Music itself, it is Alexa. When she starts Apple Music for me, this cannot be restored (but only when there is a TTS as interrupt between snapshot and restore). Maybe it is some queue problem that the queue cannot be restored.
But I don’t expect to find a fix for this problem

Hi,

great script but if I try to define two ore more playing entities the script did not work (speech is only choppy and not on all players). I think if there are more players the mus first grouped …

But it’s very complex script and I do not get it. May be a new advanced version?

Steffen

I have scrolled trough the tread and found many posts about playing announcements on ONE (or selected speakers) only but no answers. Right now all grouped speakers play the announcement :confused:
It would be great to be able to specify speakers to be used and the volume for each of them separately and let the other speakers in the group play what ever they were playing. I have my whole house grouped and would like to announce messages to specifik a speaker or group of speakers that after announcement return to the main group.

Best regards, L

Heads up: in the 2023.5 HA release the Sonos integration now supports the announce option on media_player.play_media service calls as described here. This will overlay the alert sound on top of any music currently playing (with an optional alert volume) and eliminate the need to snapshot/restore. TTS services will also use this feature automatically.

It’s a brand new feature, so please let me know if any issues are encountered. I hope it’s useful!

3 Likes

This is huge! Until now I was using the custom cloud integration for this. With the local Piper TTS and updated Sonos integration fully local TTS announcements are working. :partying_face:

Any idea to handle tts volume?

If I use the new tts.say service on my Sonos media Player while listen music in background the tts message is very silent. It would be nice to play the message always in on defined volume on all players …

Thanks, Steffen

service: media_player.play_media have an extra option for volume so I can play announces with my volume, but tts.say haven’t so it is very silent. How the best way to handle this problem?