Hi, want to share my script how you make a good tts announcement on sonos.

How it works:

  • triggered by an automation like this
          - service: script.turn_on
            entity_id: script.jarvis_speak
            data:
              variables:
                mymessage: |
                  {{ state_attr('sensor.notification_message', 'msg') }}
                myplayer: media_player.sonos_bedroom

  • the script is using an input_boolean to flip so that one announcement is done at a time, that’s why I have the “jarvis_announcement_wait” boolean
  • it uses "input_number.jarvis_<<room>>_volume to be able to adjust the volume per room for the announcements
  • it uses a little “ding” sound prior to the announcement
  • it uses piper and with trial end error I figured out how many word per minute “ryan” is speaking so that the script ends exactly at the time when the tts announcement has finished in case there are multiple announcements to be made per room
alias: jarvis_speak
sequence:
	  - repeat:
		  while:
			- condition: state
			  entity_id: input_boolean.jarvis_announcement_wait
			  state: "on"
		  sequence:
			- delay:
				hours: 0
				minutes: 0
				seconds: 1
				milliseconds: 0
	  - service: input_boolean.turn_on
		target:
		  entity_id:
			- input_boolean.jarvis_announcement_wait
		data: {}
      - service: media_player.play_media
        data:
          media_content_id: /local/jarvis-chime.wav
          media_content_type: music
          announce: true
          extra:
            volume: >-
              {{ states('input_number.jarvis_' + myplayer |
              replace('media_player.','') + '_volume')  }}
        target:
          entity_id: "{{ myplayer }}"
      - delay:
          seconds: 1
      - service: media_player.play_media
        data:
          media_content_type: music
          announce: true
          media_content_id: >-
            media-source://tts/tts.piper?message={{ mymessage  | replace('&',
            'and') }}
          extra:
            volume: >-
              {{ states('input_number.jarvis_' + myplayer |
              replace('media_player.','') + '_volume')  }}
        target:
          entity_id: "{{ myplayer }}"
      - delay:
          seconds: >
            {% set text = mymessage | replace('&', 'and') %} {{ (text.split(' ')
            | length * 60 / 150) | round(0, 'ceil') }}
	  - service: input_boolean.turn_off
		target:
		  entity_id:
			- input_boolean.jarvis_announcement_wait
		data: {}
mode: queued
max: 10

  • @camr_on
    link
    English
    51 year ago

    This is really cool, nice work. I’ll have to take a look at using this method, right now I’ve got a hacky Sonos API with Google translate tts giving me announcements… this looks way more straightforward and useable

    • @bazingabotOP
      link
      English
      41 year ago

      thanks. the piper voices are really awesome from quality perspective. it is even cached locally, thus repeating messages are instantly available, plus: this announcement method is setting your music volume to lower and talking over it - a very nice feature

      • deejay4am
        link
        English
        11 year ago

        I was going to ask about that - is that a Sonos-only feature or can you do that with other devices like ChromeCast/Google TV?

        I’ve only ever tried sending messages from the Media Player card to a ChromeCast and it stops whatever is playing so I never bothered to explore further…

        • @bazingabotOP
          link
          English
          11 year ago

          I have a chromecast audio at home as well - there I need to stop playing, let the tts announce and make it start playing again, which makes the scripting more complex

    • @SugaryBurro
      link
      English
      21 year ago

      I have the same Google TTS solution, though I’ve noticed sometimes it has a multi second delay.

      • @bazingabotOP
        link
        English
        21 year ago

        the proposed solution above has only a delay after the chime if the tts to generate is very long and hasn’t been generated in the past. Then, you hear “ding” … pause pause pause pause … announcement. but this comes all down to the processing power where you host your piper docker/engine/addon