How continue play the previous music after a tts voice announcement?

Hi,

I’ll take a look at it and get back.

I am not sure you do need the custom component to play spotify.
but have you tried with other sources like TuneIn for example?

Hi @Jokerigno,

Just wanted to give you an update.

I confirm that it works fine with Spotify when running on Sonos devices but, unfortunately not on Chrome cast or other google devices like the google mini or nest.
other streaming apps like TuneIn work fine on both Sonos and Google devices.

The reason basically is that calling the service media_player.play_media that is used in the script works on Sonos devices but not on google. Maybe we need the custom component you mentioned.

I’ll give it a try and look further for a solution

I’ll get back with an update

Kind regards, Ghassan

2 Likes

Hi @Jokerigno ,

Good news, I found a solution :slight_smile:

If you first install and configure:

Then the updated version of the script will work with SpotifyConnect on Chrome cast devices like yours.
On Sonos it still works with Sonos if you start Spotify from the Sonos App but not if you choose the Sonos SpotifyConnect device from the the Spotify app.

On the other hand, other streaming services like TuneIn still works with both Chrome cast and Sonos devices.

Her is the updates version of the script:

alias: TTS and resume
variables:
  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.75
  - service: tts.google_translate_say
    data:
      entity_id: '{{ tts_entity }}'
      language: da
      message: '{{ msg }}'
  - delay:
      hours: 0
      minutes: 0
      seconds: 7
      milliseconds: 0
  - service: media_player.volume_set
    data:
      entity_id: '{{ tts_entity }}'
      volume_level: '{{ mediaplayer_volume_level }}'
  - choose:
      - conditions:
          - condition: template
            value_template: '{{ mediaplayer_app_name == ''Spotify'' }}'
        sequence:
          - service: spotcast.start
            data:
              entity_id: '{{ tts_entity }}'
          - service: media_player.media_play
            data:
              entity_id: '{{ tts_entity }}'
    default:
      - 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: 8
          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 }}'
  - service: media_player.media_pause
    data:
      entity_id: '{{ tts_entity }}'
  - delay:
      hours: 0
      minutes: 0
      seconds: 4
      milliseconds: 0
  - choose:
      - conditions:
          - condition: template
            value_template: '{{ mediaplayer_State == ''playing'' }}'
        sequence:
          - service: media_player.media_play
            data:
              entity_id: '{{ tts_entity }}'

mode: single

As you ca see i introduced delays several places to make sure previous commands are finished executing before new ones are called. Maybe some of these delays can be made shorter. You can experiment finetuning these.

Please let med know if this works for you :slight_smile:

4 Likes

Tomorrow in the morning I will test it and let you know asap the results! Can’t wait!

TY! :slight_smile:

So I tested out and in my case I don’t know why is not working.

First I already have spotcast and I tested it in dev tools with this simple command and it works:

service: spotcast.start
  entity_id: media_player.corridoio

What I’ve found is a simply copy paste of the script. What I’v e noticed and that my google mini make the blink after tts message but the music does not start. Moreover looking ath te spotcast docs maybe the second command of the script is not required?


      - choose:
          - conditions:
              - condition: template
                value_template: "{{ mediaplayer_app_name == 'Spotify' }}"
            sequence:
              - service: spotcast.start
                data:
                  entity_id: "{{ tts_entity }}"
##########THIS IS REQUIRED ? ###########
              - service: media_player.media_play
                data:
                  entity_id: "{{ tts_entity }}"
#######################################

Of course it is just a question. I just pasted the script as is.

I’ve checked also the logs but no error in there.

Hi @Jokerigno ,

Yes I also noticed some inconsistency too.
I don’t have a google mini but other Chinese products a Mi AI speaker and Mi TV Box box. with built in Chrome cast and these behave differently. So maybe the real Chrome cast behave in yet another way.

Try this a bit modifiede version:

alias: TTS and resume
variables:
  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: da
      message: '{{ msg }}'
  - delay:
      hours: 0
      minutes: 0
      seconds: 7
      milliseconds: 0
  - service: media_player.volume_set
    data:
      entity_id: '{{ tts_entity }}'
      volume_level: '{{ mediaplayer_volume_level }}'
  - choose:
      - conditions:
          - condition: template
            value_template: '{{ mediaplayer_app_name == ''Spotify'' }}'
        sequence:
          - service: spotcast.start
            data:
              entity_id: '{{ tts_entity }}'
    default:
      - 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: 8
      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 }}'
          - delay:
              hours: 0
              minutes: 0
              seconds: 4
              milliseconds: 0

  - service: media_player.media_pause
    data:
      entity_id: '{{ tts_entity }}'
  - choose:
      - conditions:
          - condition: template
            value_template: '{{ mediaplayer_State == ''playing'' }}'
        sequence:
          - delay:
              hours: 0
              minutes: 0
              seconds: 4
              milliseconds: 0
          - service: media_player.media_play
            data:
              entity_id: '{{ tts_entity }}'
mode: single

If it still don’t work, please send me the state and attributes values for your media player from the developer tools “states tab”, before and after you call the script?

This will help us figure out what is missing :slight_smile:

4 Likes

it works!!! I need to make some other test but first impression is that it works on every condition!

1 Like

Great :slight_smile:
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.

2 Likes

Hi @wburgers ,

Glad to hear my script was useful and inspired you for your solution: :slight_smile:

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 }}'
2 Likes

Thanks for the suggestion! :+1:
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

1 Like

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 :slight_smile: .

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.

2 Likes

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 :slight_smile:

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. :slight_smile:

Looks good. :slight_smile:
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 :slight_smile: ), it will be nice