SONOS TTS Script

Yes that’s what i figured out, anything local works fine

For anything streaming non-local it seems to not like being paused and resumed; your place in the current track is lost.

@Molodax Those lines are necessary because it is very common for the media player state to NOT be playing right after telling it to speak using TTS. This wait_template waits for the state to be playing before continuing. In reality, it is the absolute most important part of my example script because without it, it will completely skip the first TTS and jump to the second.

@mihalski You could set the timeout to 10 minutes if you wanted to. The timeout is in place to be a “fallback” in case the expression never returns true. Any timeout will work as long as the timeout is longer than how long it takes for your media player to change to the playing state.

2 Likes

@dale3h Ahh! That makes PERFECT sense to me now. Thanks for the clarification.

It seems that still does not solve the problem when set to 30 seconds.

It works if nothing is playing on the Sonos, but at the cost of not being able to send another voice notification until the script exits after about 30 seconds. If something IS playing it cuts the text short.

I really don’t understand what’s going on.

Here’s my updated Sonos TTS script that is working very well for me. You can find more details, including others scripts using the TTS script in my repo here.

  sonos_say:
    alias: "Sonos TTS script"
    sequence:
      - service: media_player.sonos_snapshot
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.livingroomsonos') }}"
      - service: media_player.sonos_unjoin
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.livingroomsonos') }}"
      - service: media_player.volume_set
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.livingroomsonos') }}"
          volume_level: "{{ volume|default(0.5) }}"
      - service: tts.google_say
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.livingroomsonos') }}"
          message: "{{ message }}"
      - delay: "{{ delay|default('00:00:00') }}"
      - wait_template: "{{ is_state(sonos_entity|default('media_player.livingroomsonos'), 'playing') }}"
        timeout: '00:00:05'
      - wait_template: "{{ not is_state(sonos_entity|default('media_player.livingroomsonos'), 'playing') }}"
        timeout: '00:02:00'
      - service: media_player.sonos_restore
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.livingroomsonos') }}"
6 Likes

@arsaboo Thanks for sharing… Will give it a go…

In my experiments I was having more success with local media playing and by adding a delay of 1 second right before the sonos_restore.

@arsaboo Your script appears to work MUCH better for me!

One odd thing is that for local audio it seems absolutely perfect with speech starting almost instantly and then resuming quickly… But for streaming audio there is a delay before it starts speaking of 3 - 4 seconds…

Now I understand a delay when it resumes and it needs to restart streaming… But why a delay at the beginning?

I’m struggling to get this to work.

I’m using the script from @arsaboo

Getting the following in the logs:

2017-07-31 23:18:16 WARNING (MainThread) [homeassistant.helpers.entity] Update for media_player.living_room is already in progress
2017-07-31 23:18:16 WARNING (MainThread) [homeassistant.helpers.entity] Update for media_player.living_room is already in progress
2017-07-31 23:18:16 WARNING (MainThread) [homeassistant.helpers.entity] Update for media_player.living_room is already in progress

I’m playing music from either a spotify playlist or from my iPhone. The TTS plays almost instantly using google_say, then stops… and stays. Doesn’t seem to restore.

Script (called, script.sonos_tts):

sequence:
  - service: media_player.sonos_snapshot
    data_template:
      entity_id: "{{ sonos_entity|default('media_player.living_room') }}"
  - service: media_player.sonos_unjoin
    data_template:
      entity_id: "{{ sonos_entity|default('media_player.living_room') }}"
  - service: media_player.volume_set
    data_template:
      entity_id: "{{ sonos_entity|default('media_player.living_room') }}"
      volume_level: "{{ volume|default(0.3) }}"
  - service: tts.google_say
    data_template:
      entity_id: "{{ sonos_entity|default('media_player.living_room') }}"
      message: "{{ message }}"
  - delay: "{{ delay|default('00:00:00') }}"
  - wait_template: "{{ is_state(sonos_entity|default('media_player.living_room'), 'playing') }}"
    timeout: '00:00:05'
  - wait_template: "{{ not is_state(sonos_entity|default('media_player.living_room'), 'playing') }}"
    timeout: '00:02:00'
  - service: media_player.sonos_restore
    data_template:
      entity_id: "{{ sonos_entity|default('media_player.living_room') }}"

Script 2:

  - service: script.sonos_tts
    data:
      sonos_entity: media_player.living_room
      volume: 0.2
      delay: '00:00:04'
      message: 'Testing!'

It restores after 2 minutes. Remove the second wait_template and it should restore immediately after the TTS playback. Also, remove the delay from the script call.

Are you sure? The 1st wait template waits for the TTS to start to play; with a 5 second timeout. Then the second waits for it to finish playing (not playing state); with a 2 minute timeout.

If I remove the 2nd wait longer TTS messages get cutoff as it restores as soon as it starts to play.

You need the wait_template only if you are not using delay. The problem with the second wait_template is that it sometimes does not restore until the timeout if Sonos was already playing something before the TTS.

Running a very simple script trying to get it to work and still having issues. It is creating the audio file in the TTS folder, but nothing happens and it just sits there. I can play it manually so it does not appear to be corrupt. Any clues as to what could be the issue here?

Thanks

test_sonos:
sequence:
- service: media_player.sonos_snapshot
data_template:
entity_id: media_player.study
- service: tts.google_say
data_template:
entity_id: media_player.study
message: “Test message.”
- delay: “00:00:{{ states.media_player.study.attributes.media_duration | int }}”
- service: media_player.sonos_restore
data_template:
entity_id: media_player.study

It works for me when there is something already playing.
When the Sonos is inactive there is no speech coming out.

I am having a similar issue as @badgerhome, I am also using the script form @arsaboo as this is the one that I like best, although I have tried other scripts on this page as well. Basicly, I have 1 out of 3 Sonos speakers that doesn’t restart playing after the announcement. Here is my setup:

Sonos Play1 --> office
Sonos Play3 --> kitchen
Sonos Play5 --> living room

Playing music and if I send a TTS announcement to my “office” speaker, I get the voice, but it never returns back to music although the other speakers continue playing. Sending the same announcement to either the kitchen or the livingroom works well with no issues, music restarts after the announcement, In summary, here are my results:

office --> music playback Does Not work
kitchen --> music playback works
livingroom --> music playback works

Of course, I want most of my announcements in the office, so I’m a little disappointed. I almost think that it’s a big in the way that the snapshot and restore works on the first speaker that was installed (office) Would this be considered my Master Speaker?

Any chance that this somehow could be fixed by a script?
IF not part of a group and music was playing, restore music
IF part of a group and music was playing, re-join the group

Any other ideas?

If you post your script I can try to help. I have no issues with my music being restored after the tts to either one or multiple speakers

@Jer78 - Thanks, much appreciated

Here is my Sonos TTS Script

  sonos_tts:
    alias: "Sonos TTS script - Testing"
    sequence:
      - service: media_player.sonos_snapshot
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.livingroom') }}"
      - service: media_player.sonos_unjoin
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.livingroom') }}"
      - service: media_player.volume_set
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.livingroom') }}"
          volume_level: "{{ volume|default(0.5) }}"
      - service: tts.google_say
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.livingroom') }}"
          message: "{{ message }}"
      - delay: "{{ delay|default('00:00:00') }}"
      - wait_template: "{{ is_state(sonos_entity|default('media_player.livingroom'), 'playing') }}"
        timeout: '00:00:05'
      - wait_template: "{{ not is_state(sonos_entity|default('media_player.livingroom'), 'playing') }}"
        timeout: '00:02:00'
      - service: media_player.sonos_restore
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.livingroom') }}"

Here is my Announcement:

  notificationgaragedoor:
    alias: 'Garage Door Open'
    sequence:
      - service: script.sonos_tts
        data:
          sonos_entity: 'media_player.office'
          volume: 0.35
          delay: '00:00:04'
          message: 'Garage door is open, please check!'

Here is my automation that calls the announcement, I just change the time everytime I want to test.

- alias: "Testing Sonos TTS"
  initial_state: True
  hide_entity: False
  trigger:
    platform: time
    at: '14:17:00'
  action:
    service: script.turn_on
    entity_id: script.notificationgaragedoor

@berniebl Do you happen to have another Sonos speaker acting as the “master”? If so, if you unjoin them after the snapshot but aren’t rejoining them maybe that’s causing the issue?? I’d try commenting out the unjoin service and see what happens.

I’m using one of the earlier methods and seems to work rock solid for me. Although this looks interesting, I can see where it has its limitations.

Well, this surely gave me better results, I don’t know why I didn’t think of that, but I think that I need to take a look at what a “master” is and if there is a way to not configure one of my speakers this way. Still not sure if one of them is or not.

What is happening now is that the announcement is broadcasted to All speakers, but the music starts … at least the music starts back now, but it forces a new track. I can live with the new track, but the wife will not appreciate having a message broadcasted over every speakers. I can always use this script if I need a broadcast to All Speakers, but will need to research what this “master” speaker is all about and how to reconfigure …

Thanks for leading me in this direction, I appreciate your help!

Well, at least it’s a step in the right direction! Glad we somewhat isolated the issue. Later tonight or weekend, I’ll post my script. It is hard coded, but in my case, I always wanted it to go to one particular speaker and it does resume properly if they were all previously grouped. This is probably what you want in this one case.