Great
Glad to hear
I was looking for something like this! Thanks for this great script!
I have edited the script to fit my use case a little better:
In the Google Home app, I have bundled my two Google Home mini speakers together to a “Home Group” (the group has the name home_group
. This home group is the default playback device.
This shows up as an extra media player in Home Assistant.
Whenever I say: “Hey Google, play my favourites” it will start playing my liked songs in Spotify on both speakers.
I want to play my tts on only a single device. This automatically stops playback on the entire group for some reason.
Whenever a tts comes along, I want playback to continue on both speakers.
Here are my edits:
tts_and_resume:
alias: TTS and resume
variables:
group_State: '{{ states(''media_player.home_group'') }}'
mediaplayer_State: '{{ states(tts_entity) }}'
mediaplayer_volume_level: '{{ state_attr(tts_entity,''volume_level'') }}'
mediaplayer_media_content_id: '{{ state_attr(tts_entity,''media_content_id'') }}'
mediaplayer_app_name: '{{ state_attr(tts_entity,''app_name'') }}'
mediaplayer_Source: '{{ state_attr(tts_entity,''media_channel'') }}'
sequence:
- service: media_player.volume_set
data:
entity_id: '{{ tts_entity }}'
volume_level: 0.15
- service: tts.google_translate_say
data:
entity_id: '{{ tts_entity }}'
language: '{{ language }}'
message: '{{ msg }}'
- delay:
seconds: 7
- service: media_player.volume_set
data:
entity_id: '{{ tts_entity }}'
volume_level: '{{ mediaplayer_volume_level }}'
- choose:
- conditions:
- condition: template
value_template: '{{ group_State == ''playing'' }}'
sequence:
- service: script.turn_on
target:
entity_id: script.resume_after_tts
data:
variables:
resume_entity: media_player.home_group
mediaplayer_State: '{{ mediaplayer_State }}'
mediaplayer_volume_level: '{{ mediaplayer_volume_level }}'
mediaplayer_media_content_id: '{{ mediaplayer_media_content_id }}'
mediaplayer_app_name: '{{ mediaplayer_app_name }}'
mediaplayer_Source: '{{ mediaplayer_Source }}'
default:
- service: script.turn_on
target:
entity_id: script.resume_after_tts
data:
variables:
resume_entity: '{{ tts_entity }}'
mediaplayer_State: '{{ mediaplayer_State }}'
mediaplayer_volume_level: '{{ mediaplayer_volume_level }}'
mediaplayer_media_content_id: '{{ mediaplayer_media_content_id }}'
mediaplayer_app_name: '{{ mediaplayer_app_name }}'
mediaplayer_Source: '{{ mediaplayer_Source }}'
mode: single
And the resume is done in another service:
resume_after_tts:
alias: Resume after TTS
sequence:
- choose:
- conditions:
- condition: template
value_template: '{{ mediaplayer_app_name == ''Spotify'' }}'
sequence:
- service: spotcast.start
data:
entity_id: '{{ resume_entity }}'
default:
- service: media_player.play_media
data:
entity_id: '{{ resume_entity }}'
media_content_id: '{{ mediaplayer_media_content_id }}'
media_content_type: music
- delay:
seconds: 8
- choose:
- conditions:
- condition: template
value_template: '{{ mediaplayer_Source != None }}'
sequence:
- service: media_player.select_source
data:
entity_id: '{{ resume_entity }}'
source: '{{ mediaplayer_Source }}'
- delay:
seconds: 4
- service: media_player.media_pause
data:
entity_id: '{{ resume_entity }}'
- choose:
- conditions:
- condition: template
value_template: '{{ mediaplayer_State == ''playing'' }}'
sequence:
- delay:
seconds: 4
- service: media_player.media_play
data:
entity_id: '{{ resume_entity }}'
mode: single
So it detects the state of the group and will continue playing on either the tts_entity or on the group depending on the state.
It is not the most elegant solution, but this is working fine for now.
If you have multiple groups however, you’ll have to come up with an even more clever way of knowing which group is playing.
Hi @wburgers ,
Glad to hear my script was useful and inspired you for your solution:
Maybe you can optimize the code by conditional value of the resume_entity instead of a choose construction and two different calls with the only difference by the entity. if this works, you can reconsider containing the resume scipt, in the main script saving further calls.
Try something like this (Not sure the indention is correct)
- service: script.turn_on
target:
entity_id: script.resume_after_tts
data:
variables:
resume_entity: |-
{% if is_state('group_State', 'playing') %}
'{{ media_player.home_group }}'
{% else %}
'{{ tts_entity }}'
{% endif %}
mediaplayer_State: '{{ mediaplayer_State }}'
mediaplayer_volume_level: '{{ mediaplayer_volume_level }}'
mediaplayer_media_content_id: '{{ mediaplayer_media_content_id }}'
mediaplayer_app_name: '{{ mediaplayer_app_name }}'
mediaplayer_Source: '{{ mediaplayer_Source }}'
Thanks for the suggestion!
I’ll give it a go next week when I have more time.
hello , my script work fine! thanks @ghvader and all
this is my code:
alias: TTS and resume
variables:
media_content_id_mini: '{{ state_attr(''media_player.home_mini'',''media_content_id'') }}'
media_content_id_nest: '{{ state_attr(''media_player.nest_mini'',''media_content_id'') }}'
mediaplayer_volume_level_mini: '{{ state_attr(''media_player.home_mini'',''volume_level'') }}'
mediaplayer_volume_level_nest: '{{ state_attr(''media_player.nest_mini'',''volume_level'') }}'
mediaplayer_State_mini: '{{ states(''media_player.home_mini'') }}'
mediaplayer_State_nest: '{{ states(''media_player.nest_mini'') }}'
sequence:
- service: media_player.media_pause
data:
entity_id: '{{ ''media_player.home_mini'' }}'
- service: media_player.media_pause
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
- delay: 1
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.home_mini'' }}'
volume_level: '{{ volumen }}'
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
volume_level: '{{ volumen }}'
- delay: 1
- service: tts.google_say
entity_id: media_player.minis
data:
message: '{{ message }}'
- delay: '{{ espera }}'
- choose:
- conditions:
- condition: template
value_template: '{{ media_content_id_mini == media_content_id_nest }}'
sequence:
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.home_mini'' }}'
volume_level: '{{ mediaplayer_volume_level_mini }}'
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
volume_level: '{{ mediaplayer_volume_level_nest }}'
- delay: 2
- service: media_player.play_media
data:
entity_id: '{{ ''media_player.minis'' }}'
media_content_id: '{{ media_content_id_nest }}'
media_content_type: music
default:
- choose:
- conditions:
- condition: template
value_template: '{{ mediaplayer_State_nest == ''playing'' }}'
sequence:
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
volume_level: '{{ mediaplayer_volume_level_nest }}'
- delay: 2
- service: media_player.play_media
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
media_content_id: '{{ media_content_id_nest }}'
media_content_type: music
- choose:
- conditions:
- condition: template
value_template: '{{ mediaplayer_State_mini == ''playing'' }}'
sequence:
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
volume_level: '{{ mediaplayer_volume_level_mini }}'
- delay: 2
- service: media_player.play_media
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
media_content_id: '{{ mediaplayer_volume_level_mini }}'
media_content_type: music
- choose:
- conditions:
- condition: template
value_template: '{{ mediaplayer_State_mini != ''playing'' }}'
sequence:
- service: media_player.turn_off
data:
entity_id: '{{ ''media_player.home_mini'' }}'
- choose:
- conditions:
- condition: template
value_template: '{{ mediaplayer_State_nest != ''playing'' }}'
sequence:
- service: media_player.turn_off
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
mode: single
now , a further optimization …
how I can add a “choose:” or “IF” to reduce a 50% or limit to 0.3 the volume in the night ? when the sun is above_horizon by example.
regards
I add the option to reduce the volume in the night
alias: TTS and resume
variables:
media_content_id_mini: '{{ state_attr(''media_player.home_mini'',''media_content_id'') }}'
media_content_id_nest: '{{ state_attr(''media_player.nest_mini'',''media_content_id'') }}'
mediaplayer_volume_level_mini: '{{ state_attr(''media_player.home_mini'',''volume_level'') }}'
mediaplayer_volume_level_nest: '{{ state_attr(''media_player.nest_mini'',''volume_level'') }}'
mediaplayer_State_mini: '{{ states(''media_player.home_mini'') }}'
mediaplayer_State_nest: '{{ states(''media_player.nest_mini'') }}'
volumen_noche: '{{ volumen - 0.3 }}'
sequence:
- service: media_player.media_pause
data:
entity_id: '{{ ''media_player.home_mini'' }}'
- service: media_player.media_pause
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
- delay: 1
- choose:
- conditions:
- condition: template
value_template: '{{ now().hour < 9 }}'
sequence:
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.home_mini'' }}'
volume_level: '{{ volumen_noche }}'
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
volume_level: '{{ volumen_noche }}'
- conditions:
- condition: template
value_template: '{{ now().hour < 23 }}'
sequence:
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.home_mini'' }}'
volume_level: '{{ volumen }}'
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
volume_level: '{{ volumen }}'
default:
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.home_mini'' }}'
volume_level: '{{ volumen_noche }}'
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
volume_level: '{{ volumen_noche }}'
- delay: 1
- service: tts.google_say
entity_id: media_player.minis
data:
message: '{{ message }}'
- delay: '{{ espera }}'
- choose:
- conditions:
- condition: template
value_template: '{{ media_content_id_mini == media_content_id_nest }}'
sequence:
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.home_mini'' }}'
volume_level: '{{ mediaplayer_volume_level_mini }}'
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
volume_level: '{{ mediaplayer_volume_level_nest }}'
- delay: 2
- service: media_player.play_media
data:
entity_id: '{{ ''media_player.minis'' }}'
media_content_id: '{{ media_content_id_nest }}'
media_content_type: music
default:
- choose:
- conditions:
- condition: template
value_template: '{{ mediaplayer_State_nest == ''playing'' }}'
sequence:
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
volume_level: '{{ mediaplayer_volume_level_nest }}'
- delay: 2
- service: media_player.play_media
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
media_content_id: '{{ media_content_id_nest }}'
media_content_type: music
- choose:
- conditions:
- condition: template
value_template: '{{ mediaplayer_State_mini == ''playing'' }}'
sequence:
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
volume_level: '{{ mediaplayer_volume_level_mini }}'
- delay: 2
- service: media_player.play_media
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
media_content_id: '{{ mediaplayer_volume_level_mini }}'
media_content_type: music
- choose:
- conditions:
- condition: template
value_template: '{{ mediaplayer_State_mini != ''playing'' }}'
sequence:
- service: media_player.turn_off
data:
entity_id: '{{ ''media_player.home_mini'' }}'
- choose:
- conditions:
- condition: template
value_template: '{{ mediaplayer_State_nest != ''playing'' }}'
sequence:
- service: media_player.turn_off
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
mode: single
Hi @ArielBaravalle ,
I tried to make a more compact version optimizing the conditional structure and thereby removing unnecessary duplicate code.
The script size is reduced from 125 to 78 lines .
alias: TTS and resume
variables:
media_content_id_mini: '{{ state_attr(''media_player.home_mini'',''media_content_id'') }}'
media_content_id_nest: '{{ state_attr(''media_player.nest_mini'',''media_content_id'') }}'
mediaplayer_volume_level_mini: '{{ state_attr(''media_player.home_mini'',''volume_level'') }}'
mediaplayer_volume_level_nest: '{{ state_attr(''media_player.nest_mini'',''volume_level'') }}'
mediaplayer_State_mini: '{{ states(''media_player.home_mini'') }}'
mediaplayer_State_nest: '{{ states(''media_player.nest_mini'') }}'
volumen_output: |-
{% if now().hour < 9 %}
'{{ volumen - 0.3 }}'
{% elif now().hour < 23 %}
'{{ volumen }}'
{% else %}
'{{ volumen }}'
{% endif %}
sequence:
- service: media_player.media_pause
data:
entity_id: '{{ ''media_player.home_mini'' }}'
- service: media_player.media_pause
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
- delay: 1
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.home_mini'' }}'
volume_level: '{{ volumen_output }}'
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
volume_level: '{{ volumen_output }}'
- delay: 1
- service: tts.google_say
entity_id: media_player.minis
data:
message: '{{ message }}'
- delay: '{{ espera }}'
- delay: 2
- choose:
- conditions:
- condition: template
value_template: '{{ mediaplayer_State_nest == ''playing'' }}'
sequence:
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
volume_level: '{{ mediaplayer_volume_level_nest }}'
- delay: 2
- service: media_player.play_media
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
media_content_id: '{{ media_content_id_nest }}'
media_content_type: music
default:
- service: media_player.turn_off
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
- choose:
- conditions:
- condition: template
value_template: '{{ mediaplayer_State_mini == ''playing'' }}'
sequence:
- service: media_player.volume_set
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
volume_level: '{{ mediaplayer_volume_level_mini }}'
- delay: 2
- service: media_player.play_media
data:
entity_id: '{{ ''media_player.nest_mini'' }}'
media_content_id: '{{ mediaplayer_volume_level_mini }}'
media_content_type: music
default:
- service: media_player.turn_off
data:
entity_id: '{{ ''media_player.home_mini'' }}'
mode: single
Take a look at this and let me know of you have comments/questions.
great ! thanks
now , how we can eliminate the “espera” variable ?
waiting the change of state of player to “not playing” , maybe in a WHILE loop ?
or calculating the length of the string “message” ?
If you dont mind broadcasting to all the Google Home/Nest devices then just use Assistant Relay.
A work-around to prevent it playing to all devices is to first send a command to particular devices to put them in ‘do not disturb’ mode first, then set back to normal. That setting can be done using the Google Home custom component.
Hi Ariel,
so, does it work for you?
Please remove the delay: 2 line after delay: ‘{{ espera }}’. I did not notice it earlier
Maybe worth trying calculate the length og the message and multiply by a constant to get number og seconds to wait.
That constant is very likely language dependent and must be calibrated to the actual language doing some trial and error until you hit a reasonable level.
I can probably give it a try tomorrow.
Kind regards,
Ghassan
i try this changes in variables , to detect if is defined or not, and calculate the time to wait the tts.
variables:
espera: '{{ ( ( message | length ) / 10 + 4 ) | int }}'
media_content_id_mini: '{{ state_attr(''media_player.home_mini'',''media_content_id'') }}'
media_content_id_nest: '{{ state_attr(''media_player.nest_mini'',''media_content_id'') }}'
mediaplayer_volume_level_mini: '{{ state_attr(''media_player.home_mini'',''volume_level'') }}'
mediaplayer_volume_level_nest: '{{ state_attr(''media_player.nest_mini'',''volume_level'') }}'
mediaplayer_State_mini: '{{ states(''media_player.home_mini'') }}'
mediaplayer_State_nest: '{{ states(''media_player.nest_mini'') }}'
volumen_output: |
{% if volumen_level is undefined %}
0.7
{% else %}
{% if now().hour < 9 %}
{{ (volumen_level * 0.7 ) | round(1) }}
{% elif now().hour < 22 %}
{{ volumen_level }}
{% else %}
{{ (volumen_level * 0.7 ) | round(1) }}
{% endif %}
{% endif %}
now the volume is a optional variable.
Looks good.
Does it seem to work?
is it really enough with 1 sec per 10 characters?
I think maybe if the volume is not given, then you should keep current volume as is.
You can consider simplifying your if structure like this:
volumen_output: |
{% if volumen_level is undefined %}
0.7
{% elif now().hour > 9 or now().hour < 22 %}
{{ volumen_level }}
{% else %}
{{ (volumen_level * 0.7 ) | round(1) }}
{% endif %}
Finally I suggest that you define variables (constants) for all your hardcoded values ( magic numbers ), it will be nice
This is amazing! I’ve been looking for something like this for so long. I receive a fair few TTS announcements and it drives the family mad if playing music and need to order google to start it again (normally the playlist starts at the first song too).
I’m trying to get this script working but getting some issues. Please forgive me if this is an extremely dumb question but do I need to amend this script to work for me? I’ve added the script in my scripts.yaml, added the Spotify integration and added Spotcast (which works if I manually call service) but it doesn’t resume the music after TTS announcements automatically.
Hi Jake,
No, you need not do any modifications to the script.
What is the issue you are facing: Do you succeed to do the announcement but not resuming the playing?
And what kind of media player device and technology: Airplay., google cast or other
- is it Spotify you have tested?
- Have you tested other playing sources like internet radio or other? If not please do so.
Please share the code from where you call the script.
And take screenshots of the media player entity state showing all its attributes from the developer toots before and after calling the script like this:
Looking forward to get your answers and I will try to help through
Kind regards,
Ghassan
hi @ghassan,
Looking for some help here. Any idea if this will work with YouTube Music? It’s clear the script is working (based on the state of the device), but it doesn’t resume playing music.
Here’s the state before and after the script:
Before:
Hi @shanf67,
Looks like the source is restored correctly but the most basic which is the state is not.
We verify that if you manually start playing on the device and check if it plays the correct, media. Please do the test and tell me the result.
The script has been under development and is shared here in different versions.
From which post nr did you copy it?
Even if I attempt to play again manually, it doesn’t work. I’m assuming because the app changes.
I’m using the following for the script:
alias: TTSandresume
variables:
mediaplayer_State: '{{ states(tts_entity) }}'
mediaplayer_media_content_id: '{{ state_attr(tts_entity,''media_content_id'') }}'
mediaplayer_Source: '{{ state_attr(tts_entity,''media_channel'') }}'
mediaplayer_volume_level: '{{ state_attr(tts_entity,''volume_level'') }}'
sequence:
- service: media_player.volume_set
data:
entity_id: '{{ tts_entity }}'
volume_level: 0.25
- service: tts.google_translate_say
data:
entity_id: '{{ tts_entity }}'
language: en
message: '{{ msg }}'
- delay:
hours: 0
minutes: 0
seconds: 5
milliseconds: 0
- service: media_player.volume_set
data:
entity_id: '{{ tts_entity }}'
volume_level: '{{ mediaplayer_volume_level }}'
- service: media_player.play_media
data:
entity_id: '{{ tts_entity }}'
media_content_id: '{{ mediaplayer_media_content_id }}'
media_content_type: music
- delay:
hours: 0
minutes: 0
seconds: 10
milliseconds: 0
- choose:
- conditions:
- condition: template
value_template: '{{ mediaplayer_Source != None }}'
sequence:
- service: media_player.select_source
data:
entity_id: '{{ tts_entity }}'
source: '{{ mediaplayer_Source }}'
- choose:
- conditions:
- condition: template
value_template: '{{ mediaplayer_State != ''playing'' }}'
sequence:
- service: media_player.media_pause
data:
entity_id: '{{ tts_entity }}'
mode: single
Hi @shanf67 ,
I guess you are right, this is very likely because we miss to backup and then update some important attributes.
I am not sure which of these exactly but probably the app_id / name
But don’t worry this can be done. We can backup and restore all these attributes.
To be able to do that, I have installed and use a python script, and I do it successfully in my version of the script. But i just cant remember which script it is and where to find it.
I’ll search for it and get back to you
In the meanwhile you can work identifying which attribute we still need to adjust.
You can start changing the app_Id
you can do that from the developer tool, in the state attributes window, and then hit “Set state”
Then try to start playing from the lovelace or any other place you can control the media_player and see if it works.
if not, then try another attribute and so on.
Stay tuned .’