How to improve tts script with variable

I want to make a script which I can call from automations, to call the tts service. The reason I need this, I’ll have conditions etc to change which speakers to use. Eg now I have a test toggle, it only beeps 1 speaker instead of all.
Also I want to do other things - eg set volume to play text, then restore old volume. Because tts is too soft somehow.

alias: Announce
sequence:
  - if:
      - condition: state
        entity_id: input_boolean.test_mode
        state: "on"
    then:
      - service: tts.google_cloud_say
        data:
          entity_id: media_player.bedroom_speaker
          message: "{{ message }}"
      - stop: ""
    else:
      - service: tts.google_cloud_say
        data:
          entity_id: media_player.all_speakers
          message: "{{ message }}"
mode: queued

It works. I call it with

service: script.announce
data:
  message: hello.

But it doesn’t really support the gui. Is there a way to change this so I can call service, and it pops up a place to type in the message, and I don’t have to remember to start with "message: " each time?

Use script fields.

    alias: Announce
    description: "Play specified message as TTS"
    fields:
      message:
        name: Message 
        description: "The message you want to play"
        selector:
          text:
    mode: queued
    sequence:
      ... the rest of your script...

Here’s the documentation for the Text Selector.

Thanks that works a treat.

I tried to add variables, but I’m not sure what’s wrong:

Defined up top

...
fields:
  ...
variables:
  entities: null
sequence:
...

then I set them

sequence:
  - if:
      - condition: state
        entity_id: input_boolean.test_mode
        state: "on"
    then:
      - entities: media_player.office_speaker
    else:
      - entities: >-
            media_player.office_speaker, media_player.living_room_group

etc a few more times

then call at end

  - service: tts.google_cloud_say
    data:
      entity_id: "{{ entities }}"
    message: <speak><prosody volume="+60dB">"{{ message }}"</prosody></speak>

I got “Message malformed: Unable to determine action @ data[‘sequence’][0][‘then’][0]”

I’m really finding this yaml difficult to read.

Which part is wrong?

You’re welcome!

Please consider marking my post above with the Solution tag. It will automatically place a check-mark next to the topic’s title which signals to other users that this topic has been resolved. This makes it easier to find for users with similar questions.

For more information refer to guideline 21 in the FAQ.


I don’t know what you read in the variables documentation that led you to believe you can define a variable like that but you can’t.

This is the correct format. However it still won’t work the way you want because of the scope of variables.

      - variables:
           entities: media_player.office_speaker

What are all the conditions that will determine which media_players to use? It may be possible to use a template instead of if-then-else.

Well I couldn’t see anything in Script Syntax - Home Assistant about how to set the variable.

I thought I could scope it up top before sequence and it would be visible to all below it?

I don’t have all the rules yet but basically

if (toggle1 == on)
  entities = speaker1
elif (toggle2 == on)
  entities = speaker3, speaker5
...<x many>

set tts params
call tts(entities)

I don’t see how to set a variable at all. Otherwise I have the dumb way

if (toggle1 == on)
  set tts params
  call tts(speaker1)
elif (toggle2 == on)
  set tts params
  call tts(speaker3, speaker5)

set tts params
call tts(entities)

which is ugly because I may have a few lines to setup tts.

You can implement that directly within the service call using a template.

sequence:
  - service: tts.google_cloud_say
    target:
      entity_id: >
        {% if is_state('input_boolean.toggle1', 'on') %}
          media_player.speaker1
        {% elif is_state('input_boolean.toggle2', 'on') %}
          media_player.speaker3, media_player.speaker5
        {% endif %}
    data:
      message: '<speak><prosody volume="+60dB">"{{ message }}"</prosody></speak>'

Having said that, the template’s logic should be improved (at least a final else) because if both input_booleans are off it will report nothing and that’s not a valid value for entity_id (resulting in a runtime error).