Hoping for help with announcement notification using multiple sonos speakers (announcement cuts off mid sentence 1-3 seconds in)

Hello all,

Can someone help me figure out why my announcements don’t seem to be working correctly.

I have a media player group called “sonos_group” that contains 2 sonos speakers in it.

Essentially, the announcement stops 1-3 seconds into starting on the living room sonos speaker but I can hear it continuing on the downstairs sonos speaker (the 2nd speaker in the “sonos_group” as normal.

The script takes a snapshot of the living room sonos speaker (one of the 2 speakers in the “sonos group” media player)

The script then unjoins the living room speaker (I’m not 100% sure why I did this as this was written a while ago and I’m not completely sure I ever had this working correctly from the beginning)

I then set the volume for the announcement. Next I complete the announcement.

I have a delay waiting for the living room speaker to become paused (end the announcement??)

Next I set the volume back to its original volume

Lastly, I restore the snapshot to the living room speaker.

Hopefully someone can help me track down the bug, I think I’m just using a service call inappropriately but I’m not sure.

  speech_engine:
    mode: queued
    sequence:
      # - service: mqtt.publish
      #   data_template:
      #     topic: 'house/polly/lastmsg'
      #     payload: 'This message is from {{ now().strftime("%-I") }}:{{ now().strftime("%M") }} {{ now().strftime("%p") }}. {{ message | striptags | truncate(220)}}'
      #     retain: true
      # - service: mqtt.publish
      #   data_template:
      #     topic: 'house/polly/lastloc'
      #     payload: '{{ who }}'
      #     retain: true
      - condition: state
        entity_id: input_boolean.audible_notifications
        state: "on"
      - condition: state
        entity_id: group.family
        state: "home"
      - condition: state
        entity_id: input_boolean.vacation_mode
        state: "off"
      - service: sonos.snapshot
        data_template:
          entity_id: >
            {% if who == 'back porch' %}
              media_player.back_porch_speaker
            {% elif who == 'front porch' %}
              media_player.front_porch_speaker
            {% elif who == 'dining room' %}
              media_player.dining_room_wifi
            {% elif who == 'office' %}
              media_player.office_wifi
            {% elif who == 'master bedroom' %}
              media_player.master_bedroom_speaker
            {% elif who == 'master bathroom' %}
              media_player.master_bathroom_speaker
            {% elif who == 'gym' %}
              media_player.gym_speaker
            {% elif who == 'guest bedroom' %}
              media_player.guest_bedroom_speaker
            {% elif who == 'garage' %}
              media_player.garage_speaker
            {% elif who == 'guest bathroom' %}
              media_player.guest_bathroom_speaker
            {% elif who == 'everywhere inside' %}
              media_player.everywhere_inside
            {% elif who == 'kitchen' %}
              media_player.kitchen_display
            {% else %}
              media_player.living_room_sonos_speaker
            {% endif %}
      - service: media_player.unjoin
        data_template:
          entity_id: >
            {% if who == 'back porch' %}
              media_player.back_porch_speaker
            {% elif who == 'front porch' %}
              media_player.front_porch_speaker
            {% elif who == 'dining room' %}
              media_player.dining_room_wifi
            {% elif who == 'office' %}
              media_player.office_wifi
            {% elif who == 'master bedroom' %}
              media_player.master_bedroom_speaker
            {% elif who == 'master bathroom' %}
              media_player.master_bathroom_speaker
            {% elif who == 'gym' %}
              media_player.gym_speaker
            {% elif who == 'guest bedroom' %}
              media_player.guest_bedroom_speaker
            {% elif who == 'garage' %}
              media_player.garage_speaker
            {% elif who == 'guest bathroom' %}
              media_player.guest_bathroom_speaker
            {% elif who == 'everywhere inside' %}
              media_player.everywhere_inside
            {% elif who == 'kitchen' %}
              media_player.kitchen_display
            {% else %}
              media_player.living_room_sonos_speaker
            {% endif %}
      - service: media_player.volume_set
        data_template:
          entity_id: >
            {% if who == 'back porch' %}
              media_player.back_porch_speaker
            {% elif who == 'front porch' %}
              media_player.front_porch_speaker
            {% elif who == 'dining room' %}
              media_player.dining_room_wifi
            {% elif who == 'office' %}
              media_player.office_wifi
            {% elif who == 'master bedroom' %}
              media_player.master_bedroom_speaker
            {% elif who == 'master bathroom' %}
              media_player.master_bathroom_speaker
            {% elif who == 'gym' %}
              media_player.gym_speaker
            {% elif who == 'guest bedroom' %}
              media_player.guest_bedroom_speaker
            {% elif who == 'garage' %}
              media_player.garage_speaker
            {% elif who == 'guest bathroom' %}
              media_player.guest_bathroom_speaker
            {% elif who == 'everywhere inside' %}
              media_player.everywhere_inside
            {% elif who == 'kitchen' %}
              media_player.kitchen_display
            {% else %}
              media_player.living_room_sonos_speaker
            {% endif %}
          volume_level: >
            {{ states('input_number.tts_volume') | float }}
      - service: tts.google_cloud_say
        data_template:
          entity_id: >
            {% if who == 'back porch' %}
              media_player.back_porch_speaker
            {% elif who == 'front porch' %}
              media_player.front_porch_speaker
            {% elif who == 'dining room' %}
              media_player.dining_room_wifi
            {% elif who == 'office' %}
              media_player.office_wifi
            {% elif who == 'master bedroom' %}
              media_player.master_bedroom_speaker
            {% elif who == 'master bathroom' %}
              media_player.master_bathroom_speaker
            {% elif who == 'gym' %}
              media_player.gym_speaker
            {% elif who == 'guest bedroom' %}
              media_player.guest_bedroom_speaker
            {% elif who == 'garage' %}
              media_player.garage_speaker
            {% elif who == 'guest bathroom' %}
              media_player.guest_bathroom_speaker
            {% elif who == 'everywhere inside' %}
              media_player.everywhere_inside
            {% elif who == 'kitchen' %}
              media_player.kitchen_display
            {% else %}
              media_player.sonos_group
            {% endif %}
          message: >-
            {{ message }}
      - delay: 00:00:05
      - wait_template: >-
          {{ states('media_player.living_room_sonos_speaker') == 'paused' }}
      - service: media_player.volume_set
        data_template:
          entity_id: >
            {% if who == 'back porch' %}
              media_player.back_porch_speaker
            {% elif who == 'front porch' %}
              media_player.front_porch_speaker
            {% elif who == 'dining room' %}
              media_player.dining_room_wifi
            {% elif who == 'office' %}
              media_player.office_wifi
            {% elif who == 'master bedroom' %}
              media_player.master_bedroom_speaker
            {% elif who == 'master bathroom' %}
              media_player.master_bathroom_speaker
            {% elif who == 'gym' %}
              media_player.gym_speaker
            {% elif who == 'guest bedroom' %}
              media_player.guest_bedroom_speaker
            {% elif who == 'garage' %}
              media_player.garage_speaker
            {% elif who == 'guest bathroom' %}
              media_player.guest_bathroom_speaker
            {% elif who == 'everywhere inside' %}
              media_player.everywhere_inside
            {% elif who == 'kitchen' %}
              media_player.kitchen_display
            {% else %}
              media_player.living_room_sonos_speaker
            {% endif %}
          volume_level: >
            {{ states('input_number.current_speaker_volume') | float }}
      - service: sonos.restore
        data_template:
          entity_id: >
            {% if who == 'back porch' %}
              media_player.back_porch_speaker
            {% elif who == 'front porch' %}
              media_player.front_porch_speaker
            {% elif who == 'dining room' %}
              media_player.dining_room_wifi
            {% elif who == 'office' %}
              media_player.office_wifi
            {% elif who == 'master bedroom' %}
              media_player.master_bedroom_speaker
            {% elif who == 'master bathroom' %}
              media_player.master_bathroom_speaker
            {% elif who == 'gym' %}
              media_player.gym_speaker
            {% elif who == 'guest bedroom' %}
              media_player.guest_bedroom_speaker
            {% elif who == 'garage' %}
              media_player.garage_speaker
            {% elif who == 'guest bathroom' %}
              media_player.guest_bathroom_speaker
            {% elif who == 'everywhere inside' %}
              media_player.everywhere_inside
            {% elif who == 'kitchen' %}
              media_player.kitchen_display
            {% else %}
              media_player.living_room_sonos_speaker
            {% endif %}

Also, here is the message I am passing to the tts service:

>
  {# Morning Report #}
  {%- macro getReport() -%}
    <p>
      {% if now().strftime('%H')|int < 12 and now().strftime('%H')|int > 6 %}
        Good morning.
      {% elif now().strftime('%H')|int >= 12 and now().strftime('%H')|int < 17 %}
        Good afternoon.
      {% else %}
        Good evening.
      {% endif %}
      </p>
      <p>
      {% if now().strftime('%H')|int < 12 %}
        {% if now().strftime('%M')|int == 0 %}
          It is {{ now().strftime("%I:%M %p") }}.
        {% else %}
          It is {{ now().strftime("%I:%M %p") }}.
        {% endif %}

      {% elif now().strftime('%H')|int > 12 %}
        {% if now().strftime('%M')|int == 0 %}
          It is {{ now().strftime("%I:%M %p") }}.
        {% else %}
          It is {{ now().strftime("%I:%M %p") }}.
        {% endif %}
      
      {% else %}

      {% endif %}
      </p>
      <p>
      {{ [
          'Today is ',
          'If you have not been keeping track today is ',
          'Do you know what day of the week it is? Today is',
          'I hate to be the bearer of bad news, but today is '
      ]|random }}
      {{states('sensor.today_is') }}.
      </p>
      <p>
        It is currently {{states('sensor.openweathermap_condition')}} and {{ states('sensor.openweathermap_temperature') | round }} degrees in Morristown. 
      </p>
      <p>
        {% if states('sensor.weatheralerts_1') | int > 0 %}
          There are currently {{states('sensor.weatheralerts_1') }} active weather alerts for our area.
          The National Weather Service Has issued and it states,
          {% if states.sensor.weatheralerts_1_alert_5.attributes.spoken_title is not none %}
            {{ states.sensor.weatheralerts_1_alert_5.attributes.spoken_title }}.
          {% elif states.sensor.weatheralerts_1_alert_4.attributes.spoken_title is not none %}
            {{ states.sensor.weatheralerts_1_alert_4.attributes.spoken_title }}.
          {% elif states.sensor.weatheralerts_1_alert_3.attributes.spoken_title is not none %}
            {{ states.sensor.weatheralerts_1_alert_3.attributes.spoken_title }}.
          {% elif states.sensor.weatheralerts_1_alert_2.attributes.spoken_title is not none %}
            {{ states.sensor.weatheralerts_1_alert_2.attributes.spoken_title }}.
          {% elif states.sensor.weatheralerts_1_alert_1.attributes.spoken_title is not none %}
            {{ states.sensor.weatheralerts_1_alert_1.attributes.spoken_title }}.
          {% else %}
            There have been no issued alerts from the National Weather Service.
          {% endif %}
        {% endif %}
      </p>
        <p>
        {{ [
            'The rest of the day should be,',
            'Todays forecast should be ,'
        ]|random }}
          {{ states('sensor.current_forecast') }}.
        </p>
        <p>
          {% if is_state('input_boolean.heartworm', 'on') %}
            Today is the day Wrigley gets his heartworm medicine. 
          {% endif %}
        </p>
        <p>
          {% if is_state('sensor.today_is', 'Wednesday') %}
            {% if now().strftime('%H')|int > 17 %}
            {{ [ 'Do not forget tomorrow is Trash Day. ',
              'I advise you move the trash cans to the curb for the weekly pickup. ',
              ' The trash and recycle should go out.'
            ] | random }}
            {% endif %}
          {% endif %}
        </p>
        <p>
        {% if is_state('sensor.halloween_countdown','0') %}
          Happy Halloween!
        {% endif %}
        {% if is_state('sensor.christmas_countdown','0') %}
          Merry Christmas Everyone!
        {% endif %}
        {% if is_state('sensor.anniversary_the_snackies','0') %}
          Happy Anniversary! It been an amazing {{ state_attr('sensor.anniversary_the_snackies', 'years_at_next_anniversary') }} years!
        {% endif %}
        {% if is_state('calendar.holidays_in_united_states', 'on') %}
          Today is {{state_attr('calendar.holidays_in_united_states', 'message')}}. 
        {% endif %}
        {%- set event=state_attr('calendar.natdaycal_com_national_day_calendar', 'message') %}
        {% if 'Day' in event and 'National' in event%}
          {{ [
            'And a very special Happy ',
            'It is also ',
            'Today is also known as ',
            'Oh <emphasis>Look</emphasis>. Today is ',
            'Want to know a fact? Today is ',
            'Everyday can be a holiday. So today is '
        ]|random }}
        {{state_attr('calendar.natdaycal_com_national_day_calendar', 'message') | replace("&"," and ") }}.
        {%- endif -%}
        </p>
        <p>

          {%- if states('sensor.home_to_eyecenter')|round > 65 %}
            Traffic to the Eye Center appears heavier than normnal.Traffic looks like it is going to take you over an hour to get to work.
          {% else %}
            Traffic to the Eye Center is normal.
          {% endif %}
          Currently it will take {{states('sensor.home_to_eyecenter')|round}} minutes to get to the Eye Center.

          {%- if states('sensor.home_to_tdot')|round > 45 %}
            Traffic to TDOT appears heavier than normnal. Over 45 minutes to work.
          {% else %}
            Traffic to TDOT is normal.
          {% endif %}
          Currently it will take {{states('sensor.home_to_tdot')|round}} minutes to get to TDOT.
      </p>
  {%- endmacro -%}


  {# a macro that removes all newline characters, empty spaces, and returns formatted text  #}
    {%- macro cleanup(data) -%}
      {%- for item in data.split("\n")  if item | trim != "" -%}
        {{ item | trim }} {% endfor -%}
  {%- endmacro -%}

  {# a macro to call all macros :)  #}
    {%- macro mother_of_all_macros() -%}
      {{ getReport() }}
    {%- endmacro -%}
    
    {# Call the macro  #}
    {{- cleanup(mother_of_all_macros()) -}}

I feel like it is possibly related to the “wait template” I have in the script. It is waiting for “paused”, is it possible that “paused” is showing up in the state of the sonos living room media player in the middle of the announcement due to how I have the message paragraph formatted??

I really don’t know but just pitching ideas to see if someone can shed some light on what may be going on.

Where in the script does it reference a ‘sonos_group’?

All I can find in the script is that it picks one speaker, unjoins it from all others, and then plays the TTS message to that one speaker.

Also, if it selects a speaker, why is the script hard-coded to wait for ‘media_player.living_room_sonos_speaker’?

In the cloud say service call. In the else clause.

- service: tts.google_cloud_say
        data_template:
          entity_id: >
            {% if who == 'back porch' %}
              media_player.back_porch_speaker
            {% elif who == 'front porch' %}
              media_player.front_porch_speaker
            {% elif who == 'dining room' %}
              media_player.dining_room_wifi
            {% elif who == 'office' %}
              media_player.office_wifi
            {% elif who == 'master bedroom' %}
              media_player.master_bedroom_speaker
            {% elif who == 'master bathroom' %}
              media_player.master_bathroom_speaker
            {% elif who == 'gym' %}
              media_player.gym_speaker
            {% elif who == 'guest bedroom' %}
              media_player.guest_bedroom_speaker
            {% elif who == 'garage' %}
              media_player.garage_speaker
            {% elif who == 'guest bathroom' %}
              media_player.guest_bathroom_speaker
            {% elif who == 'everywhere inside' %}
              media_player.everywhere_inside
            {% elif who == 'kitchen' %}
              media_player.kitchen_display
            {% else %}
              media_player.sonos_group
            {% endif %}
          message: >-
            {{ message }}

Because I don’t want the living room media player changing the volume back to its default until the media player goes back to “paused”, i.e. finished announcment.

I also have no clue what I’m doing though, so if this stuff is just wrong, I wouldn’t turn down guidance. I just don’t understand why the upstairs player would stop while the bottom one keeps going if they’re in the same group.

Something is causing the living room one to stop for some reason.

So if the else clause selects to play to:
media_player.back_porch_speaker

why would it wait for a completely different player: media_player.living_room_sonos_speaker

to change state to paused?

Shouldn’t it wait for the speaker it chose to play to?

I’ll add to Taras answer: all my sonos devices are in idle at the end of the tts, not paused.

Clearly there is some logic somewhere but mine definitely (almost always) are paused.
:man_shrugging:

It’s my understanding that a call to tts.speak or tts.<whatever> gets converted to a call to media_player.play_media and its announce option is automatically set to true. Users have reported that when announce is true, the player doesn’t report playing while it’s playing the announcement.

In other words, while playing the announcement, it doesn’t change state to playing and then, when it’s done, to either idle or paused but just remains either idle/paused. That makes it challenging to determine when the announcement has finished playing.

If you take that into account, plus the fact that this script isn’t necessarily monitoring the state of the media_player that’s handling the announcement, it’s clear that it will experience problems.

For starters, you have to fix the part that is hard-coded to wait for the living room speaker and, unless you really must have the announce feature, you may wish to use media_player.play_media directly with announce set to false.

The following example is untested and may require adjustments to work in your environment.

service: media_player.play_media
data:
  media_content_id: 'media-source://tts/google_cloud?message=Your message goes here'
  media_content_type: 'provider'
  announce: false
target:
  entity_id: media_player.your_chosen_player

This is true. And despite the obvious goodness of the new announce capability I cannot beleive it got through the QA process. I still maintain that the state (database/machine/engine - whatever it is called) should not be allowed to be wrong

Which is also true except you are being too kind with your choice of word. Challenging it isn’t. Impossible it is.

But hey ho, You can’t have everything.

PS I believe this is an issue related to the Sonos api being used but as an outsider I find it hard to understand why some extra ‘announce’ attributes couldn’t be added to the media entity to facilitate working out when the announcement has started and finished.

You’re making the bold assumption that the hardware in question reports it’s state during announcements. The state machine only holds information that it gets from the device it communicates with. If the device does not report that information, is the state machine wrong? No.

E.g. Alexa doesn’t support this, so announcing on Alexa will never show a “announcement” status. I.e. Alexa media player cannot change it’s state to ‘playing’ when it’s announcing because that state is not provided by the hardware.

I see what you are saying. In my case the else clause to play to is the Sonos group.

I agree with you on your second statement though.

I should change my wait for pause to also use the Sonos group media player and see if this issue goes away.

I’ll report back and post new code either way.

Thank you @123

I didn’t realize any of this. Thank you for your understanding. I will look/ try this if my last reply doesn’t seem to correct anything.

Again ‘from the outside’, it still seems to me that the integration itself must ‘know’ it is making an announcement so it just ‘feels’ to me that the integration could add/set an attribute to that effect, along with another one that (at the least) says how long the announcement is.

I have no ‘real world’ knowledge about how integrations work under the hood or if that is even possible so I am just speaking as ‘user’.
I’m more than happy to be told it is impossible.
And although it would be nice I don’t even need someone to give me an explanation.
I’m certainly not looking to stir anything up :grin:

(Although, I will never be comfortable that it is ok for the state of a device to be knowingly wrong)

It’s not going to know that if the hardware doesn’t tell you how fast it’s going to announce. Like I said, you’re making assumptions. What happens if your hardware has a voice that speaks fast? You have another that speaks slow. Only the hardware knows this information because it’s handling the announcement. Therefor, only it can tell us how long the response is going to take.

But tts announcements are simply an mp3 created at run time and then played.

Maybe that isn’t the case for announce, I don’t know, I haven’t had time to experiment with it yet partly because the issue we’re talking about breaks a lot of my announcement system so will need some rewriting.

I do intend to get round to it one day because as I said, the new feature is good.

I’m fairly sure it does not create an MP3 file before streaming it. It’s just a service that causes it to say the words it receives. EDIT: for the tts.cloud_say, it may be that way.

ok, so here is what I have changed the script to. Does anyone see any issues with this one. I have not tested it yet but have simplified it (honestly more than I would like but it is what it is). I’m at my wants vs. abilities threshold for this one I believe.

Change the snapshot and restore to the “media_player.sonos group” entity, this is a media player group including 2 sonos speakers

Commented out wait template and just hardcoded 45 second delay before changing volume back to regular volume. Can you change the volume on a media player group that contains 2 sonos speakers?

I really don’t care for the 45 second hard code but I don’t know of any other way if the original looking for the pause state won’t work properly due to hardware limitations?

Thank you all for your input!!

  speech_engine:
    mode: queued
    sequence:
      # - service: mqtt.publish
      #   data_template:
      #     topic: 'house/polly/lastmsg'
      #     payload: 'This message is from {{ now().strftime("%-I") }}:{{ now().strftime("%M") }} {{ now().strftime("%p") }}. {{ message | striptags | truncate(220)}}'
      #     retain: true
      # - service: mqtt.publish
      #   data_template:
      #     topic: 'house/polly/lastloc'
      #     payload: '{{ who }}'
      #     retain: true
      - condition: state
        entity_id: input_boolean.audible_notifications
        state: "on"
      - condition: state
        entity_id: group.family
        state: "home"
      - condition: state
        entity_id: input_boolean.vacation_mode
        state: "off"
      - service: sonos.snapshot
        data_template:
          entity_id: >
            {% if who == 'back porch' %}
              media_player.back_porch_speaker
            {% elif who == 'front porch' %}
              media_player.front_porch_speaker
            {% elif who == 'dining room' %}
              media_player.dining_room_wifi
            {% elif who == 'office' %}
              media_player.office_wifi
            {% elif who == 'master bedroom' %}
              media_player.master_bedroom_speaker
            {% elif who == 'master bathroom' %}
              media_player.master_bathroom_speaker
            {% elif who == 'gym' %}
              media_player.gym_speaker
            {% elif who == 'guest bedroom' %}
              media_player.guest_bedroom_speaker
            {% elif who == 'garage' %}
              media_player.garage_speaker
            {% elif who == 'guest bathroom' %}
              media_player.guest_bathroom_speaker
            {% elif who == 'everywhere inside' %}
              media_player.everywhere_inside
            {% elif who == 'kitchen' %}
              media_player.kitchen_display
            {% else %}
              media_player.sonos_group
            {% endif %}
      # - service: media_player.unjoin
      #   data_template:
      #     entity_id: >
      #       {% if who == 'back porch' %}
      #         media_player.back_porch_speaker
      #       {% elif who == 'front porch' %}
      #         media_player.front_porch_speaker
      #       {% elif who == 'dining room' %}
      #         media_player.dining_room_wifi
      #       {% elif who == 'office' %}
      #         media_player.office_wifi
      #       {% elif who == 'master bedroom' %}
      #         media_player.master_bedroom_speaker
      #       {% elif who == 'master bathroom' %}
      #         media_player.master_bathroom_speaker
      #       {% elif who == 'gym' %}
      #         media_player.gym_speaker
      #       {% elif who == 'guest bedroom' %}
      #         media_player.guest_bedroom_speaker
      #       {% elif who == 'garage' %}
      #         media_player.garage_speaker
      #       {% elif who == 'guest bathroom' %}
      #         media_player.guest_bathroom_speaker
      #       {% elif who == 'everywhere inside' %}
      #         media_player.everywhere_inside
      #       {% elif who == 'kitchen' %}
      #         media_player.kitchen_display
      #       {% else %}
      #         media_player.living_room_sonos_speaker
      #       {% endif %}
      - service: media_player.volume_set
        data_template:
          entity_id: >
            {% if who == 'back porch' %}
              media_player.back_porch_speaker
            {% elif who == 'front porch' %}
              media_player.front_porch_speaker
            {% elif who == 'dining room' %}
              media_player.dining_room_wifi
            {% elif who == 'office' %}
              media_player.office_wifi
            {% elif who == 'master bedroom' %}
              media_player.master_bedroom_speaker
            {% elif who == 'master bathroom' %}
              media_player.master_bathroom_speaker
            {% elif who == 'gym' %}
              media_player.gym_speaker
            {% elif who == 'guest bedroom' %}
              media_player.guest_bedroom_speaker
            {% elif who == 'garage' %}
              media_player.garage_speaker
            {% elif who == 'guest bathroom' %}
              media_player.guest_bathroom_speaker
            {% elif who == 'everywhere inside' %}
              media_player.everywhere_inside
            {% elif who == 'kitchen' %}
              media_player.kitchen_display
            {% else %}
              media_player.living_room_sonos_speaker
            {% endif %}
          volume_level: >
            {{ states('input_number.tts_volume') | float }}
      - service: tts.google_cloud_say
        data_template:
          entity_id: >
            {% if who == 'back porch' %}
              media_player.back_porch_speaker
            {% elif who == 'front porch' %}
              media_player.front_porch_speaker
            {% elif who == 'dining room' %}
              media_player.dining_room_wifi
            {% elif who == 'office' %}
              media_player.office_wifi
            {% elif who == 'master bedroom' %}
              media_player.master_bedroom_speaker
            {% elif who == 'master bathroom' %}
              media_player.master_bathroom_speaker
            {% elif who == 'gym' %}
              media_player.gym_speaker
            {% elif who == 'guest bedroom' %}
              media_player.guest_bedroom_speaker
            {% elif who == 'garage' %}
              media_player.garage_speaker
            {% elif who == 'guest bathroom' %}
              media_player.guest_bathroom_speaker
            {% elif who == 'everywhere inside' %}
              media_player.everywhere_inside
            {% elif who == 'kitchen' %}
              media_player.kitchen_display
            {% else %}
              media_player.sonos_group
            {% endif %}
          message: >-
            {{ message }}
      - delay: 00:00:45
      # - wait_template: >-
      #     {{ states('media_player.living_room_sonos_speaker') == 'paused' }}
      - service: media_player.volume_set
        data_template:
          entity_id: >
            {% if who == 'back porch' %}
              media_player.back_porch_speaker
            {% elif who == 'front porch' %}
              media_player.front_porch_speaker
            {% elif who == 'dining room' %}
              media_player.dining_room_wifi
            {% elif who == 'office' %}
              media_player.office_wifi
            {% elif who == 'master bedroom' %}
              media_player.master_bedroom_speaker
            {% elif who == 'master bathroom' %}
              media_player.master_bathroom_speaker
            {% elif who == 'gym' %}
              media_player.gym_speaker
            {% elif who == 'guest bedroom' %}
              media_player.guest_bedroom_speaker
            {% elif who == 'garage' %}
              media_player.garage_speaker
            {% elif who == 'guest bathroom' %}
              media_player.guest_bathroom_speaker
            {% elif who == 'everywhere inside' %}
              media_player.everywhere_inside
            {% elif who == 'kitchen' %}
              media_player.kitchen_display
            {% else %}
              media_player.living_room_sonos_speaker
            {% endif %}
          volume_level: >
            {{ states('input_number.current_speaker_volume') | float }}
      - service: sonos.restore
        data_template:
          entity_id: >
            {% if who == 'back porch' %}
              media_player.back_porch_speaker
            {% elif who == 'front porch' %}
              media_player.front_porch_speaker
            {% elif who == 'dining room' %}
              media_player.dining_room_wifi
            {% elif who == 'office' %}
              media_player.office_wifi
            {% elif who == 'master bedroom' %}
              media_player.master_bedroom_speaker
            {% elif who == 'master bathroom' %}
              media_player.master_bathroom_speaker
            {% elif who == 'gym' %}
              media_player.gym_speaker
            {% elif who == 'guest bedroom' %}
              media_player.guest_bedroom_speaker
            {% elif who == 'garage' %}
              media_player.garage_speaker
            {% elif who == 'guest bathroom' %}
              media_player.guest_bathroom_speaker
            {% elif who == 'everywhere inside' %}
              media_player.everywhere_inside
            {% elif who == 'kitchen' %}
              media_player.kitchen_display
            {% else %}
              media_player.sonos_group
            {% endif %}

Maybe this is a stupid question but how is announce much different from snapshot then restore?

I guess one is more generalized since its for the media player service rather than just for the sonos service.

Also, can you help me figure out how to use this idea properly.

Below is what I think I need to do but I don’t really know how to handle media_content_id because my media is contained in a parameter or variable I believe it’s called. i.e. {{message}} that I am providing to the tts.google_cloud_say service

media content type, do I put music? It looks like I only have 6 choices based on the documentation
media content id, no clue what to provide based on my paragraph above

service: media_player.play_media
data:
  media_content_id: 'media-source://tts/google_cloud?message={{message}}'
  media_content_type: music
  announce: false
target:
  entity_id: media_player.sonos_group

you should use variables

  speech_engine:
    mode: queued
    variables:
      players:
        'back porch': media_player.back_porch_speaker
        'front porch': media_player.front_porch_speaker
        'dining room': media_player.dining_room_wifi
        office: media_player.office_wifi
        'master bedroom': media_player.master_bedroom_speaker
        'master bathroom': media_player.master_bathroom_speaker
        gym: media_player.gym_speaker
        'guest bedroom': media_player.guest_bedroom_speaker
        garage: media_player.garage_speaker
        'guest bathroom': media_player.guest_bathroom_speaker
        everywhere inside: media_player.everywhere_inside
        kitchen: media_player.kitchen_display
      player: >
        {{ players.get(who, 'media_player.sonos_group') }}
    sequence:
      # - service: mqtt.publish
      #   data_template:
      #     topic: 'house/polly/lastmsg'
      #     payload: 'This message is from {{ now().strftime("%-I") }}:{{ now().strftime("%M") }} {{ now().strftime("%p") }}. {{ message | striptags | truncate(220)}}'
      #     retain: true
      # - service: mqtt.publish
      #   data_template:
      #     topic: 'house/polly/lastloc'
      #     payload: '{{ who }}'
      #     retain: true
      - condition: state
        entity_id: input_boolean.audible_notifications
        state: "on"
      - condition: state
        entity_id: group.family
        state: "home"
      - condition: state
        entity_id: input_boolean.vacation_mode
        state: "off"
      - service: sonos.snapshot
        data_template:
          entity_id: "{{ player }}"
      # - service: media_player.unjoin
      #   data_template:
      #     entity_id: "{{ player }}"
      - service: media_player.volume_set
        data:
          entity_id: "{{ player }}"
          volume_level: >
            {{ states('input_number.tts_volume') | float }}
      - service: tts.google_cloud_say
        data:
          entity_id: "{{ player }}"
          message: >-
            {{ message }}
      - delay: 00:00:45
      # - wait_template: >-
      #     {{ states('media_player.living_room_sonos_speaker') == 'paused' }}
      - service: media_player.volume_set
        data:
          entity_id: "{{ player }}"
          volume_level: >
            {{ states('input_number.current_speaker_volume') | float }}
      - service: sonos.restore
        data:
          entity_id: "{{ player }}"