Google home - set volume up and back again

Hello, is there some way how to set volume to predefined together with TTS command (tts.google_translate_say) and after is done turn it to previous level?

1 Like

Sorry already talking about here: Setting Volume level for Google Home in Automation announcement

The data_template instead of data advice does not apply if you are on the current version.

1 Like

what are you talking about?

The answer in the link you pasted:

Try it like this, with data_template: instead of data:…

This only applies to home assistant versions prior to 0.115.

1 Like

So there is no chance to get the volume_set working actually?

Sure there is. I use a script for that. I will post it later. Here you go:
scripts.yaml:

announce_downstairs:
  alias: 'Announce downstairs'
  sequence:
    - service: media_player.volume_mute  # The first part gets rid of the default Google Home bloop-bloop sound. First mutes the speaker...
      data:
        entity_id: media_player.googlehome_downstairs
        is_volume_muted: true
    - service: media_player.play_media  # then plays a random 1 second silent track ...
      data:
        entity_id: media_player.googlehome_downstairs
        media_content_type: music
        media_content_id: "{{ states('input_text.base_url') + '/local/audio/1sec.mp3' }}"
    - delay:
        seconds: 1
    - service: media_player.volume_set  # then sets the desired volume ...
      data:
        entity_id: media_player.googlehome_downstairs
        volume_level: >-
          {% if now().hour > 18 or now().hour < 7 %} 0.35
          {% else %} 0.65
          {% endif %}
    - service: media_player.volume_mute  # only then unmutes, so you don't hear the volume changing sounds
      data:
        entity_id: media_player.googlehome_downstairs
        is_volume_muted: false
    - service: media_player.play_media  # then it plays a nice ding-dong sound
      data:
        entity_id: media_player.googlehome_downstairs
        media_content_type: music
        media_content_id: "{{ states('input_text.base_url') + '/local/audio/announcement.mp3' }}"
        # My base_url is contained in an input_text, so that I could put it in secrets.yaml. You can just put the external url to your HA frontend here. NB an internal url won't work in my experience.
    - delay:
        seconds: 2
        # milliseconds: 800
    - service: tts.google_say  # then finally here's your TTS message :-)
      data:
        entity_id: media_player.googlehome_downstairs
        message: "{{my_message}}"

Calling the script from an automation:

    - service: script.announce_downstairs
      data:
        my_message: "Have a great day"
8 Likes

@Emphyrio wow must try today. May I ask you for your nice ding dang? I have only Scarry dong dang kong. Thank you :blush:

I see you have volume-setting capabilities in your script, but I don’t see anything that saves the previous volume setting and restores it after the announcement. Have you figured out a way to acquire the current volume setting before you make changes? Restoring should be pretty simple after that.

3 Likes

I will try to figure that out for you.

Here are the sounds (1 second of silence + announcement sound).

3 Likes

Here’s an adaptation that also restores the volume to its original volume, after the announcement.

announce_downstairs:
  alias: 'Announce downstairs'
  sequence:
    - service: media_player.volume_mute  # The first part gets rid of the default Google Home bloop-bloop sound. First mutes the speaker...
      data:
        entity_id: media_player.googlehome_downstairs
        is_volume_muted: true
    - service: media_player.play_media  # then plays a random 1 second silent track ...
      data:
        entity_id: media_player.googlehome_downstairs
        media_content_type: music
        media_content_id: "{{ states('input_text.base_url') + '/local/audio/1sec.mp3' }}"
    - delay:
        seconds: 1
    - service: input_number.set_value  # store the current volume level (should be after playing 1sec because only then the volume_level attribute is available)
      data:
        entity_id: input_number.current_volume
        value: "{{ state_attr('media_player.googlehome_downstairs','volume_level') }}"
    - service: media_player.volume_set  # then sets the desired volume for the announcement ...
      data:
        entity_id: media_player.googlehome_downstairs
        volume_level: >-
          {% if now().hour > 18 or now().hour < 7 %} 0.35
          {% else %} 0.65
          {% endif %}
    - service: media_player.volume_mute  # only then unmutes, so you don't hear the volume changing sounds
      data:
        entity_id: media_player.googlehome_downstairs
        is_volume_muted: false
    - service: media_player.play_media  # then it plays a nice ding-dong sound
      data:
        entity_id: media_player.googlehome_downstairs
        media_content_type: music
        media_content_id: "{{ states('input_text.base_url') + '/local/audio/announcement.mp3' }}"
        # My base_url is contained in an input_text, so that I could put it in secrets.yaml. You can just put the external url to your HA frontend here. NB an internal url won't work in my experience.
    - delay:
        seconds: 2
        # milliseconds: 800
    - service: tts.google_say  # then finally here's your TTS message :-)
      data:
        entity_id: media_player.googlehome_downstairs
        message: "{{my_message}}"
    - delay:   # Set this delay for the maximum length of your announcement messages
        seconds: 4
    - service: media_player.volume_mute  # Again, muting to prevent volume changing sounds
      data:
        entity_id: media_player.googlehome_downstairs
        is_volume_muted: true
    - service: media_player.volume_set
      data:
        entity_id: media_player.googlehome_downstairs
        volume_level: "{{ states('input_number.current_volume') }}"
    - delay:
        seconds: 1
    - service: media_player.volume_mute
      data:
        entity_id: media_player.googlehome_downstairs
        is_volume_muted: false

This requires an input_number to be defined in configuration.yaml:

input_number:
  current_volume:
    name: 'Current volume'
    min: 0
    max: 1

Although in the latest HA versions you might be able to use an on-the-fly variable, but I haven’t used that before so there’s that.

7 Likes

Thank you very much @Emphyrio

I took @Emphyrio’s example above and parameterized it to make it easier to use generically - i.e. use any media_player entity (or several!), use a specificed volume, etc.

First, a setup script:

# Turns on Google smart speaker(s), bypassing the Google chime by muting
#
# Args:
#   announcement_volume (float): speaker volume_level for announcement (0 <= x <= 1)
#   player_id (entity or list of entities): media_player(s) on which to play announcement
#
# Usage Example:
#     - service: script.google_speaker_announcement_startup
#       data:
#         announcement_volume: "{{ states('input_number.volume_announcement') }}"
#         player_id: media_player.office_display, media_player.family_room_speaker
google_speaker_announcement_startup:
  alias: 'GoogleSpeakerAnnouncementStartup'
  sequence:
    - service: media_player.volume_mute
      data:
        entity_id: "{{ player_id }}"
        is_volume_muted: true
    - delay:
        milliseconds: 200
    - service: media_player.play_media
      data:
        entity_id: "{{ player_id }}"
        media_content_type: music
        media_content_id: "{{ states('input_text.home_assistant_url_internal') + '/local/sounds/silence-1sec.mp3' }}"
    - delay:
        seconds: 1
    - service: media_player.volume_set
      data_template:
        entity_id: "{{ player_id }}"
        volume_level: "{{ announcement_volume }}"
    - delay:
        seconds: 2
    - service: media_player.volume_mute
      data:
        entity_id: "{{ player_id }}"
        is_volume_muted: false
    - service: media_player.play_media
      data:
        entity_id: "{{ player_id }}"
        media_content_type: music
        media_content_id: "{{ states('input_text.home_assistant_url_internal') + '/local/sounds/announcement_chime.mp3' }}"
    - delay:
        seconds: 3

Note that I’ve found this eliminates the Google chime most of the time, but not all of the time. I played with lots of variations of this sequence in terms of order, timing, etc., and haven’t gotten it to be silent 100% of the time. But this one is close…

Then there’s a shutdown script:

# Turns off Google smart speaker(s), restoring volume to default
#
# Args:
#   player_id (entity or list of entities): media_player(s) to shut down
#
# Usage Example:
#     - service: script.google_speaker_announcement_shutdown
#       data:
#         player_id: media_player.office_display, media_player.family_room_speaker
google_speaker_announcement_shutdown:
  alias: 'GoogleSpeakerAnnouncementShutdown'
  sequence:
    - service: media_player.volume_set
      data_template:
        entity_id: "{{ player_id }}"
        volume_level: "{{ states('input_number.volume_smart_speaker_default') }}"
    - delay:
        seconds: 1
    - service: media_player.turn_off
      data:
        entity_id: "{{ player_id }}"

And finally, there’s the announcement itself:

# Plays an TTS announcement on Google smart speaker(s) with specificed volume
#
# Args:
#   announcement_length (int): number of seconds to delay after starting announcement
#                              before assuming it has completed
#   announcement_message (string): message used as input to text-to-speech
#   announcement_volume (float): speaker volume_level for announcement (0 <= x <= 1)
#   player_id (entity or list of entities): media_player(s) on which to play announcement
#
# Usage Example:
#     - service: script.announce
#       data:
#         announcement_length: 10
#         announcement_message: "This is a test.  This is only a test of the Home Asssistant alert system."
#         announcement_volume: "{{ states('input_number.volume_announcement') }}"
#         player_id: media_player.office_display, media_player.family_room_speaker
announcement:
  alias: 'Announcement'
  sequence:
    - service: script.google_speaker_announcement_startup
      data:
          player_id: "{{ player_id }}"
          announcement_volume: "{{ announcement_volume}}"
    - service: tts.cloud_say
      data:
        entity_id: "{{ player_id }}"
        message: "{{ announcement_message  }}"
    - delay:
        seconds: "{{ announcement_length }}"
    - service: script.google_speaker_announcement_shutdown
      data:
          player_id: "{{ player_id }}"

So to use this, you just call the script.announce from an automation or other script, as shown in the example above.

2 Likes

Also, to address @Jiran’s original question (how to restore the volume to its previous level after the announcement), I tried this:

announcement_with_volume_restore:
  alias: 'AnnouncementWithVolumeRestore'
  variables:
    previous_volume: >
      "{% if is_state('media_player.office_display', 'playing') 
          or is_state('media_player.office_display', 'on') 
          or is_state('media_player.office_display', 'paused')
      %} 
        {{ state_attr('media_player.office_display', 'volume_level') | float | round(2) }} 
      {% else %}
        {{ states('input_number.volume_smart_speaker_default') | float | round(2) }}
      {% endif %}"       
  sequence:
    - service: script.google_speaker_announcement_startup
      data:
          player_id: "{{ player_id }}"
          announcement_volume: "{{ announcement_volume}}"
    - service: tts.cloud_say
      data:
        entity_id: "{{ player_id }}"
        message: "{{ announcement_message  }}"
    - delay:
        seconds: 10
    - service: media_player.volume_set
      data_template:
        entity_id: "{{ player_id }}"
        volume_level: "{{ previous_volume }}"  # doesn't seem to be a float, and casting as float makes it 0
    - service: media_player.turn_off
      data:
        entity_id: "{{ player_id }}"

That example has the entity for the previous volume hardcoded to a specific media player since I was experimenting. If the device is off (not playing), the above works by restoring the value of volume_smart_speaker_default to the device after the announcement.

In the case of the device being originally in the playing state, the value of previous_volume is saved and able to be read back with a second TTS call. However, when trying to restore the volume (line with comment above), it complains about it not being a float. If I cast it as a float (add | float), then the volume is restored as a value of zero.

I’ve tried a bunch of stuff to get this part to work, but haven’t been successful. Other ideas welcome!

1 Like

My adapted script works for me to restore the volume. It doesn’t for you?

Apparently I can’t read. :slight_smile:

I read your post above as setting up a static input_number to have as the restored value and missed that you were calling the service to set it within the script. My bad.

That works as long as you don’t have multiple announcements going at the same time… which I’m guessing for most people would be rare.

Any thoughts on how to do it without adding an extra input_number to keep things simpler?

Oh how to decide which one is better? :slight_smile:

Yes, use a variable :upside_down_face:

Hi all!

Fantastic post and love the solution by you, @Emphyrio. I also tried to implement a minimal setup as a script, however, when running it, I do script/automation that calls it does not turn back the volume. Here is what I implemented:

broadcast_msg_single_device:
  alias: 'Broadcast a message on a single device'
  sequence:
    - service: tts.google_say
      data_template:
        entity_id: "{{ device_name }}"
        message: "{{ msg }}"
        language: "{{ lang }}"
    - delay:
        seconds: 2
    - service: input_number.set_value
      data_template:
        entity_id: input_number.current_volume
        value: "{{ state_attr( device_name ,'volume_level') }}"
    - service: media_player.volume_set
      data_template:
        entity_id: "{{ device_name }}"
        volume_level: 0.7
    - service: tts.google_say
      data_template:
        entity_id: "{{ device_name }}"
        message: "{{ msg }}"
        language: "{{ lang }}"
    - delay:
        seconds: 2
    - service: media_player.volume_set
      data_template:
        entity_id: "{{ device_name }}"
        volume_level: "{{ states(input_number.current_volume) }}"
    - service: tts.google_say
      data_template:
        entity_id: "{{ device_name }}"
        message: "{{ msg }}"
        language: "{{ lang }}"

It still plays the second message but not the third anymore. When commenting out the following command, then also the 3rd message is played:

    - service: media_player.volume_set
      data_template:
        entity_id: "{{ device_name }}"
        volume_level: "{{ states(input_number.current_volume) }}"

Would appreciate if you had any idea how to solve this. Probably some beginner’s issue :wink:. Thank you!