Script to resume radio (TuneIn) and Spotify after TTS on Google Home speakers

This script supports

  • Resuming of TuneIn, Spotify and generic streams after TTS message to a Google cast device
  • Resuming an entire speaker group after a TTS has been sent to a single group member
  • Resuming of individual group members after a TTS has been sent to a speaker group

Recent changes

1 February 2022

  • BREAKING: This script is longer maintained by me. I have replaced it in my own configuration by the new Google Home Resume script. You can still report bugs or other issues, and I will do my best to fix them, but I will no longer add functionality to this script.
  • Changed links to new location in my configuration (folder not_maintained so the script will still be available, and there will be no dead links)

25 January 2022

  • Small fix to avoid error caused by undefined fixed_picture variable.

24 January 2022

  • Created a fork which allows other actions than only TTS
  • Simplified some templates
  • Moved the last choose block (to turn on the players with screen) so it will actually be executed when needed.

13 January 2022

  • Bugfix to resolve the error in case players_screen was not defined as variable.

9 January 2022

  • Fixed a bug in the template to determine which entities should be resumed

7 January 2022

  • Fixed a bug which would cause an error if speaker_groups was not defined.
  • Changed post 3 to an updated version of the dashboard card

6 January 2022

  • Found out that sending the silent mp3 is not needed to retrieve the old volume, just turning them on works fine. Advantage is that only a very short delay is required for HA to be able to retrieve the current volumes (0.25 seconds is enough) so I’ve removed the settings to set if volume restore is required, it is now always enabled (but only performed when there were non playing entities).
    The fields silent_mp3, restore_volume_all and volume_non_playing are removed. The script variables default_volume_restore and delay_volume_restore are removed as well. I’ve left default_volume_level for cases where the script was not able to retrieve the old volume.
    This will not break your existing automations or scripts, but it might be that you now send some script variables in your actions which are no longer used.

3 January 2022

  • Fixed an error in the template to determine volume restore is required
  • Changed the order of sending the TTS and the volume change, and added a wait_template. This will make sure the volume is changed after the stream stopped, so the volume of the stream will not increase/decrease just before the TTS starts. This is based on the first tts_target from the list, so it works best if there is only one tts_target.

2 January 2022

  • Small change in condition to check if volume should be changed
  • Small changes to some other conditions making the checks more robust

December 2021

  • Fixed some bugs in template to determine spotcast account
  • Added variable fixed_picture to link to pictures used as thumbnail after resuming. This prevents that the picture of the song which was playing will be used as a thumbnail. You can make sure a more generic picture is used (e.g. the logo of the TuneIn stream).
  • Placed script on Github instead of in this post so I can maintain it in one place
  • Removed need to add frequent_radio streams. The script will resume any stream starting with http
  • added variable service_data to provide additional service data for the tts_script call.
  • Fixed a bug in the template to determine the tts_target_list when the tts_target was part of a group which was not playing.
  • Fixed a bug where both groups and single entities belonging to that group would be resumed
  • Fixed a bug in determining the tts_targets_not_playing (was still using the old approach for speaker groups there)
  • Made some changes to make it work with the updated script to send a TTS to the right Google Home (on which you asked the question)

November 2021

  • BREAKING: removed the need for HA group entities for the speaker groups, the entites have to be defined in the script variables now.
  • Added a variable default_volume_level for a default volume, in case the retreived volume is not a valid value (e.g. entity was not turned on by the script in time)
  • In case a single entity was playing, and this entity was belonging to a group, it would not resume if the TTS was sent to the group, and speaker_group_split was set to false. This is fixed now.
  • added variable to provide tts_service


  1. I’m using Google Cloud TTS, check the TTS variable to make sure this matches your setup. It could be that your TTS service also requires service data like language, in such cases you can add them using the service_data variable
  2. For Spotify you need to have the Spotify integration installed, and Spotcast (available on HACS)
  3. The entity_id’s for media_player entities from the Spotify integration should be formatted like media_player.spotify_{{ spotcast user }}. For the primary Spotcast user you can use whatever you want as {{ spotcast user }}.
  4. The primary Spotcast user needs to be specified under primary_spotcast (see comment above).
  5. To determine the Spotify account, the source in the Spotify media_players is used. This is compared to the friendly name of the Goolge Home media_player. Therefor the Google Home media players in HA need to have the exact same name as they have in the Google Home app (this is also already a requirement for Spotcast to work with entity_id’s)
  6. Google Nest Hub speakers can be entered under the variable players_screen. This will make sure the photo display is turned on again after the TTS in case nothing was already playing.
  7. If you use speaker groups in the Google Home app, you can enter them under the variable speaker_groups. If you use them, you’ll need to complete this variable, and add the group members in there as well (see the script for an example).

Known limitations

  • It is possible to create speaker groups on the fly from the Google Home app, e.g. if you are playing something from Spotify on your Kitchen speaker, you can add your Living Room speaker in the Google Home app, without them belonging to a speaker group. The script won’t recognize these groups created on the fly. The cast integration won’t recognize these devices as playing anymore, so they won’t be resumed.
  • When Spotify switches to a new song or starts playing, the Spotify Media Player will shortly not show as playing. When at that moment the script is started, the stream will not be resumed afterwards.

How to start the script

In case you want your script/automation to resume with the next action immediately

  - alias: "TTS voor Nest Hub Kitchen"
    service: script.turn_on 
      entity_id: script.google_home_say
        tts_message: "Hello, hello! This is a test!"
        tts_target: media_player.google_kitchen
        tts_volume: 35

In case you want to have your script/automation wait for the TTS script to be completed

  - alias: "TTS voor Nest Hub Kitchen"
    service: script.google_home_say
      tts_message: "Hello, hello! This is a test!"
        - media_player.google_kitchen
        - media_player.google_living
        - media_player.upstairs_group
      tts_volume: 35
      speaker_group_split: False

The script can also be started from the GUI, both in YAML mode and full GUI mode. The variables tts_message and tts_target are required. tts_volume is optional, in case it is not set the current volume will be used. In full GUI mode you can only select one enttiy_id as limitation of the the entity selector. In YAML mode, or if called in a service call in an automation or script, you can enter multiple entity_ids.

Explanation of the fields

Field Required Example Description
tts_message Yes "Hello, this is a test" The TTS message to be sent
tts_target Yes media_player.kitchen_hub The media_players entities to which the TTS message should be sent. Multiple entities can be provided as a comma separated string, or as a list (see 2nd example above)
tts_volume No 35 The volume for the TTS message, can be entered as a value between 1 and 100, or as a value between 0 and 1. Both 0.35 and 35 will result in 35% volume.
speaker_group_split No True If set to True it will not send the TTS message to the Google Home speaker group entity, but it will send it to the separate member entities. Requires the speaker_groups to be provided in the script.

And finally the script itself

Link to the script on my Github config, so I don have to maintain it in two places

Explanation of variables in the script

Only tts_service is required, all other are optional, but will affect the workings of the script.

Variable Default Example Description
tts_service tts.google_cloud_say the service used for the tts service call
service_data language: nl Add additional service data for your tts_service call
players_screen See script on Github Enter a list of cast devices with a screen. Do not use a comma seperated string here.
primary_spotcast pepijn The Spotify account which is used as primary account for spotcast, should match the last part of the Spotify media player.
fixed_picture See script on Github A dictionary with the pictures. As key value the artist should be used (check media_artist in developer tools > states)
speaker_groups See script on Github A combination of a dictionary and a list, with speaker groups of which all entities are included in another speaker group.
default_volume_level 0.25 0.5 The default volume level to use to set the entity to if the old volume can not be retreived
default_group_split False True True/False default setting for splitting speaker groups to individual entities when sending TTS

If you’re interested, you can replace this:

        tts_target_list: >
          {# convert tts_target input to list if it is not already #}
            ( tts_target | replace(' ' , '')).split(',') | list 
            if tts_target is string else tts_target 

with this slightly shorter version:

        tts_target_list: >
          {# convert tts_target input to list if it is not already #}
            (tts_target).replace(' ', '').split(',') 
            if tts_target is string else tts_target 
1 Like

BREAKING: The script linked below will now use the Google Home Resume script instead of the Google Home Say script. So you need that script instead of the one this topic is about.

For my Lovelace Dashboard I have made a card to easily send a TTS message.

For this I’ve used some helpers.

  • input_text.tts_message for the text to be sent
  • input_boolean.tts_volume to set if you want to change the volume for the TTS, or use the current volume
  • input_number.tts.volume for the volume setting (value from 0 to 100 using increments of 5)
  • an input_boolean for each Google Cast media player, with the entity_id as the player. So e.g. input_boolean.google_kitchen for media_player.google_kitchen

I created a script which uses this input to call the other script from post 1
It will reset the helpers to some defaults settings after the TTS has been sent (volume to 25%, all device toggles to off etc)

The script allows to set a default selection for de dropdown, a default message text, a default volume and an option to reset the toggles (input_booleans) after the script is sent. If you remove one of these variables, it won’t reset anymore after the script is started.

All required helpers and the script are combined in one package.

I don’t have a very fancy Lovelace dashboard, so I made a simple card to use the above. The volume slider will only be shown in case input_boolean.tts_volume is set to on, and the toggles to select multiple entities will only be shown in case input_select.dropdown_google_say is set to Geavanceerd kiezen (Advanced selection in English).

The code for the card is available here

This will then look like this (I did not provide a default_selection here, so the dropdown does not reset automatically):

1 Like

If you wish, you can reduce that to this:

        tts_target: >
                  | selectattr('state', 'eq', 'on') 
                  | map(attribute='entity_id') 
                  | list
                  | replace('input_boolean', 'media_player')
1 Like

Hi TheFes, I’m trying my best to get this to work with “YouTube Music”. Its like the connection gets knocked from my mobile casting and never comes back. I updated your code to include YouTube Music in the conditions. Would you be able to point my in the right direction?

I’ve been trying to use YouTube Music as well for a short period of time. However, there is no service like Spotcast for YouTube music.

You can use the media_extractor integration (Media Extractor - Home Assistant) to resume the last track which was playing (using the media_content_id). However, it will then only play that track, and will not resume your playlist, or radio station (or whatever that is called in YouTube Music)

There is a YouTube Music integration available on HACS, but it works different as Spotcast does (see GitHub - KoljaWindeler/ytube_music_player: YouTube music player for homeassistant). That service does have a resume function though, but that only works if you started the stream using this integration (as far as I could figure out).
I tried to install it again to test it out again, but could not immediately get the token required to connect it, and my boss expects me to work right now :wink:

This all made me decide to stick with Spotify :slight_smile:

1 Like

Get this when i copy and paste to script:
Message malformed: extra keys not allowed @ data[‘google_home_say’]

Amazing job here !
Congrats and very useful !
Using both scripts (post 1 & 3) !
Love the work.
Appreciated & thanks to @TheFes !

Did you past it directly into configuration.yaml?
If so, you need add a line at the top with script: and intend everything two spaces.

However, new installations normally come with a scripts.yaml where you can paste the script as it is.

I’ve read it again now, and I think you are trying to paste it in the YAML editor of the GUI (from configuration → scripts).
In that case you have to remove the top line (google_home_say:) and remove the first two spaces of all the lines.
Howver, I would recommend to paste it into scripts.yaml instead of in the GUI YAML editor.

1 Like

Yep tried to put in the gui. But as I understand cutting and pasting in script.yaml is okay? No need to delete lines?

Yep, you can paste it directly into scripts.yaml

You will of course have to amend the variables to your own situation

Thanks, the script is in the system. No time yet to make it work and probably have many question to get it to work.

@TheFes, thanks for this script! It works really well. However, I do have some weird behavior with it. If I am playing music on two separate google homes (one mini and one 1st gen hub), the volumes at which they were playing gets switched after the TTS message. Any idea why this is happening?

Another small issue I noticed is that after the TTS message, the app_name changes from TuneIn Free to Default Media Receiver, thereby blacking out the screen on the hub, no longer showing the radio station information. Do you know how to solve this?

Unfortunately I did not find a way to get cast TuneIn. What the script does is just send the URL using the default media player. Maybe it could be done using Assistant Relay, but that is not maintained anymore. I’m from the Netherlands, and Dutch was not supported, so I did not invest a lot of time in it.

The volume issue is a bit strange indeed. I will have a look into that.

Thank you for reply. No worries about TuneIn as this is not a big issue. It works, and that is the most important thing :smile:

I just noticed that it also switches the volumes of the two devices if both are not playing.

Made some updates in the way the attributes before TTS are stored, which should prevent things to be mixed up.

Hey TheFes,

It’s not working. At first, it was crashing on your notify debug so I’ve removed it. Now nothing happens. There are no errors associated.

Setting a TTS volume causes the music I’m listening to to change to that volume but no TTS is produced.

Whoops, the notify shouldn’t be in there. It relies on a text notify service to be set up.
I am working on a changed version with an optional debug info write to the log.
For now it should work without the notifiy part (as I changed it to now)

It doesn’t. Nothing happens and no error is produced.

Nevermind, you’re using Google Cloud.

I’ll try to convert this to google_say.