Trying to make my doorbell TTS notification function better here. I was doing just a HA group which had all Sonos playing the announcement but totally out of sync. I read some posts here and conjured up a new concoction.
The Sonos app shows the new group being made, audio adjustments being made (added these to try to confirm my deafness wasn’t missing other speakers playing audio; they weren’t playing anything though), and the restore occurs. The restore doesn’t return any prior groups to each other, though. So if I was rocking out to Guns-n-Roses in the kitchen and dining room before, the group does not exist after the TTS announcement automation ends, nor does the prior audio playlist continue.
I’m at a loss as to why the entire group does not play the TTS announcement -and- why the restore isn’t restoring everything to the prior state (old groups, play where it left off, etc).
- id: da21735e-351c-11ee-be56-0242ac120002
alias: Sonos Doorbell Announcement
trigger:
- platform: state
entity_id: binary_sensor.doorbell_button_pressed
to: 'on'
action:
- service: sonos.snapshot
data:
entity_id:
- media_player.family_room
- media_player.tv_room
- media_player.kitchen
- media_player.dining_room
- media_player.move_2
- media_player.sonos_roam
- delay: '00:00:01' # Ensures face recognition has time to process
- service: media_player.join
data:
group_members:
- media_player.tv_room
- media_player.family_room
- media_player.dining_room
- media_player.move_2
- media_player.sonos_roam
target:
entity_id: media_player.kitchen
- delay: '00:00:01' # Brief delay to ensure the group is formed
- service: media_player.volume_set
data:
entity_id: media_player.kitchen
volume_level: 0.20 # Kitchen speaker volume
- service: media_player.volume_set
data:
entity_id: media_player.family_room
volume_level: 0.30 # Family room speaker volume
- service: media_player.volume_set
data:
entity_id: media_player.tv_room
volume_level: 0.20 # TV room speaker volume
- service: media_player.volume_set
data:
entity_id: media_player.dining_room
volume_level: 0.40 # Dining room speaker volume
- service: media_player.volume_set
data:
entity_id: media_player.move_2
volume_level: 0.30 # Move 2 speaker volume
- service: media_player.volume_set
data:
entity_id: media_player.sonos_roam
volume_level: 0.40 # Sonos Roam speaker volume
- delay: '00:00:01' # Brief delay to ensure volume set
- choose:
- conditions:
- condition: template
value_template: > # Check for face recognition matches
{{ state_attr('sensor.double_take_doorbell', 'matches') | length > 0 }}
sequence:
- service: tts.cloud_say
data_template:
entity_id: media_player.kitchen # The main speaker to start the group
message: >
{% set matches = state_attr('sensor.double_take_doorbell', 'matches') %}
{% set faces = matches | map(attribute='name') | list %}
{% set corrected_faces = faces | map('trim') | list %}
{% if 'viviana' in corrected_faces %}
{% set corrected_faces = corrected_faces | map('capitalize') | list %}
{% set corrected_faces = corrected_faces | map('replace', 'viviana', 'Viv-ee-ah-nah') | list %}
{% endif %}
{% if corrected_faces | length == 1 %}
{{ corrected_faces[0] }} is at the front door.
{% else %}
{{ corrected_faces | join(', ') }} are at the front door.
{% endif %}
default:
- service: tts.cloud_say
data:
entity_id: media_player.kitchen
message: Someone is at the front door.
- wait_template: "{{ not is_state('media_player.family_room', 'playing') }}"
timeout: '00:00:06' # Timeout to avoid indefinite waiting
continue_on_timeout: true
- service: sonos.restore
data:
entity_id:
- media_player.family_room
- media_player.tv_room
- media_player.kitchen
- media_player.dining_room
- media_player.move_2
- media_player.sonos_roam
mode: single
I converted my script to use it. All Sonos speakers are playing the announcement concurrently and the group returns to playing.
I’m only failing to configure the new integration’s ability to play TTS over the audio stream I think. Or, maybe that doesn’t work as I’m thinking it would vs. the couple of seconds muted time on either side of the TTS output.
- id: da21735e-351c-11ee-be56-0242ac120002
alias: Sonos Doorbell Announcement
trigger:
- platform: state
entity_id: binary_sensor.doorbell_button_pressed
to: 'on'
action:
- service: sonos.snapshot
data:
with_group: true
entity_id:
- media_player.family_room
- media_player.tv_room
- media_player.kitchen
- media_player.dining_room
- media_player.move_2
- media_player.sonos_roam
- delay: '00:00:02' # Ensures face recognition has time to process
- service: media_player.join
data:
group_members:
- media_player.tv_room
- media_player.family_room
- media_player.dining_room
- media_player.move_2
- media_player.sonos_roam
target:
entity_id: media_player.kitchen
- delay: '00:00:01' # Brief delay to ensure the group is formed
- choose:
- conditions:
- condition: template
value_template: > # Check for face recognition matches
{{ state_attr('sensor.double_take_doorbell', 'matches') | length > 0 }}
sequence:
- service: chime_tts.say
data_template:
entity_id: media_player.kitchen # The main speaker to start the group
message: >
{% set matches = state_attr('sensor.double_take_doorbell', 'matches') %}
{% set faces = matches | map(attribute='name') | list %}
{% set corrected_faces = faces | map('trim') | list %}
{% if 'viviana' in corrected_faces %}
{% set corrected_faces = corrected_faces | map('capitalize') | list %}
{% set corrected_faces = corrected_faces | map('replace', 'viviana', 'Viv-ee-ah-nah') | list %}
{% endif %}
{% if corrected_faces | length == 1 %}
{{ corrected_faces[0] }} is at the front door.
{% else %}
{{ corrected_faces | join(', ') }} are at the front door.
{% endif %}
tts_service: tts.cloud_say # Use Nabu Casa TTS service
default:
- service: chime_tts.say
data:
entity_id: media_player.kitchen
message: Someone is at the front door.
tts_service: tts.cloud_say
- wait_template: "{{ not is_state('media_player.kitchen', 'playing') }}"
timeout: '00:00:06' # Timeout to avoid indefinite waiting
continue_on_timeout: true
- service: sonos.restore
data:
with_group: true
entity_id:
- media_player.family_room
- media_player.tv_room
- media_player.kitchen
- media_player.dining_room
- media_player.move_2
- media_player.sonos_roam
mode: single
Well, aside a few seconds extra delay (not added in by my delays) to get the TTS announcement and then to resume the audio, the only issue I have is that sonos.restore function starts with the next song in the queue and not where we stopped.
- id: da21735e-351c-11ee-be56-0242ac120002
alias: Sonos Doorbell Announcement
trigger:
- platform: state
entity_id: binary_sensor.doorbell_button_pressed
to: 'on'
action:
- delay: '00:00:01'
- service: sonos.snapshot
data:
with_group: true
entity_id: all
# - media_player.family_room
# - media_player.tv_room
# - media_player.kitchen
# - media_player.dining_room
# - media_player.move_2
# - media_player.sonos_roam
- delay: '00:00:01' # Ensures face recognition has time to process
# - service: media_player.join
# data:
# group_members:
# - media_player.tv_room
# - media_player.family_room
# - media_player.dining_room
# - media_player.move_2
# - media_player.sonos_roam
# target:
# entity_id: media_player.kitchen
# - delay: '00:00:01' # Brief delay to ensure the group is formed
- choose:
- conditions:
- condition: template
value_template: > # Check for face recognition matches
{{ state_attr('sensor.double_take_doorbell', 'matches') | length > 0 }}
sequence:
- service: chime_tts.say
data_template:
entity_id:
- media_player.kitchen
- media_player.dining_room
- media_player.tv_room
# - media_player.family_room
# - media_player.sonos_roam
# - media_player.move_2
message: >
{% set matches = state_attr('sensor.double_take_doorbell', 'matches') %}
{% set faces = matches | map(attribute='name') | list %}
{% set corrected_faces = faces | map('trim') | list %}
{% if 'viviana' in corrected_faces %}
{% set corrected_faces = corrected_faces | map('capitalize') | list %}
{% set corrected_faces = corrected_faces | map('replace', 'viviana', 'Viv-ee-ah-nah') | list %}
{% endif %}
{% if corrected_faces | length == 1 %}
{{ corrected_faces[0] }} is at the front door.
{% else %}
{{ corrected_faces | join(', ') }} are at the front door.
{% endif %}
tts_service: tts.cloud_say # Use Nabu Casa TTS service
join_players: true
unjoin_players: true
# announce: true
default:
- service: chime_tts.say
data:
entity_id: group.sonos_speakers
- media_player.kitchen
- media_player.dining_room
- media_player.tv_room
# - media_player.family_room
# - media_player.sonos_roam
# - media_player.move_2
message: Someone is at the front door.
tts_service: tts.cloud_say
join_players: true
unjoin_players: true
# announce: true
- wait_template: "{{ not is_state('media_player.kitchen', 'playing') }}"
timeout: '00:00:03' # Timeout to avoid indefinite waiting
continue_on_timeout: true
# - delay: '00:00:02' # Brief delay to prevent timeout from Sonos API
- service: sonos.restore
data:
with_group: true
entity_id: all
# - media_player.family_room
# - media_player.tv_room
# - media_player.kitchen
# - media_player.dining_room
# - media_player.move_2
# - media_player.sonos_roam
mode: single
Chime TTS offer the same join/unjoin services as the standard Home Assistant media_player entity. I don’t own any Sonos speakers, but I know from Chime TTS users who do, that the join/unjoin is problematic and they recommended not to use it.
Have you tried removing the snapshot/restore service calls and uncommenting announce: true ?
Removing the sonos.snapshot and sonos.restore; adding announce; and keeping join/unjoin with no music playing on devices results in an announcement.
With the Sonos speakers that grouped playing music at TTS event, the ones that receive the TTS input do not rejoin the group after playing music.
Removing join/unjoin with announce = true results in everything staying grouped in Sonos app and music playing. But, the speakers are not in sync with the TTS.
Removing join/unjoin/announce results in the TTS being synced across devices, the Sonos group remains intact after TTS, but the Sonos queue and music is cleared.
Removing join/unjoin with fade_audio = true results in the TTS being synced across devices, the Sonos group remains intact after TTS, but the Sonos queue and music is cleared.
Removing join/unjoin with announce = true results && setting 0ms for the integration’s fade transition in everything staying grouped in Sonos app and music playing. And, the speakers ARE in sync with the TTS.
EDIT Apologies, I meant to reply to derekcentrico.
I’m intrigued by the ability to have the announcement played in sync because my understanding is the announce option is incapable of doing this on unjoined speakers.
In your tests, you say you removed “join/unjoin” but does that mean you did not use an explicit media_player.join service call and used the integration’s own ability to do it?
Man, I was torn about pasting my changes per each test and flooding the place with useless text. Should’ve done it to help you visualize.
I removed the join/unjoin and used the announce variable. Whether it works as designed or is an anomaly I don’t know. However, 2 ARCs, 1 One SL, 1 Move2, 1 Roam, and 1 Era 100 are all playing the announcement at the same time -and- I am not losing playing music and not losing Sonos app groups.
The only caveat is that I’m a bit deaf in my left ear (thanks to a lovely IED explosion). But, my right ear is good and the echo I heard across speakers is not occurring at the moment.
Here’s my current code (cleaned up and less Sonos devices being used but still working as described):
- id: da21735e-351c-11ee-be56-0242ac120002
alias: Sonos Doorbell Announcement
trigger:
- platform: state
entity_id: binary_sensor.doorbell_button_pressed
to: 'on'
action:
- delay: '00:00:03' # compreface can be sluggish right now for some reason
- choose:
- conditions:
- condition: template
value_template: > # Check for face recognition matches
{{ state_attr('sensor.double_take_doorbell', 'matches') | length > 0 }}
sequence:
- service: chime_tts.say
data_template:
entity_id:
- media_player.kitchen
- media_player.dining_room
- media_player.tv_room
# - media_player.family_room
- media_player.sonos_roam
- media_player.move_2
message: >
{% set matches = state_attr('sensor.double_take_doorbell', 'matches') %}
{% set faces = matches | map(attribute='name') | list %}
{% set corrected_faces = faces | map('trim') | list %}
{% if 'viviana' in corrected_faces %}
{% set corrected_faces = corrected_faces | map('capitalize') | list %}
{% set corrected_faces = corrected_faces | map('replace', 'viviana', 'Viv-ee-ah-nah') | list %}
{% endif %}
{% if corrected_faces | length == 1 %}
{{ corrected_faces[0] }} is at the front door.
{% else %}
{{ corrected_faces | join(', ') }} are at the front door.
{% endif %}
tts_service: tts.cloud_say # Use Nabu Casa TTS service
announce: true
default:
- service: chime_tts.say
data:
entity_id:
- media_player.kitchen
- media_player.dining_room
- media_player.tv_room
# - media_player.family_room
- media_player.sonos_roam
- media_player.move_2
message: Someone is at the front door.
tts_service: tts.cloud_say
announce: true
- wait_template: "{{ not is_state('media_player.kitchen', 'playing') }}"
timeout: '00:00:04' # Timeout to avoid indefinite waiting
continue_on_timeout: true
mode: single
You haven’t configured chime_tts.say to use join_players: true so the list of speakers are not joined yet they play the announcement in sync. You have inspired me to test it on my system.
The WAV file played in sync but only on two of the three speakers. The third was silent.
I tried it again and the file played, in sync, on only two of the three speakers but not the same two as in the first trial.
A third trial produced the same results as the second one.
I added a fourth speaker and the results were the same as in the second trial (only two out four played the file).
I added a fifth speaker and, once again, only two speakers played the file in sync and all others were silent. For this trial, the two that played were different from previous trials.
I joined all five speakers first then played the file (to all five). Only two speakers played the file and it was not in sync. For this trial, the two that played were the same as in the fifth trial.
Based on these results, I can’t use the service call’s announce feature to reliably play on more than two speakers. Why it behaves this way is unclear to me because the speakers work properly when used to play any file without announce (i.e. using Home Assistant or the Sonos app).
FWIW, I have been using a script of my own invention to play announcements. It creates a snapshot, pauses the desired speakers (if playing), unjoins them from any existing group(s), joins them into a new group, sets their volume, plays an optional preamble (i.e. prerecorded sound effect), plays the supplied file, then restores the snapshot. The script has been used at least once a day for over two years with reliable performance.
I experimented with announce when it was first introduced and it played out of sync but, I now realize, I had always tested it with joined speakers. Anyways, my latest test results, with unjoined speakers, aren’t ideal (at least not for me). Perhaps the next step is to test Nimrod_Dolev’s Chime integration with my speakers.
I’ve been having the same issues, but I want to throw this out there cause I didn’t see it mentioned. I know the announce feature is only supported by S2/Gen 2 Sonos HW. You may need to upgrade to resolve some of the out-of-sync issues with announce. I however am still running into issues as I have created a group for all my speakers and get the announcement played via media_player.play_media but the music if playing does not return after the announcement.
I’ve been following this thread with some interest, as I’m also in a similar boat. I have six Sonos speakers scattered around the house, and they pretty much only get used for various announcements (front door motion, somebody arriving home, etc.) All the speakers are in a helper ‘Media Group’, so are referenced as a single entity.
Originally, I was using the media_player.play_media call (first taking a Sonos snapshot of one speaker), playing a local mp3 file that had a combined chime and text, then restoring the snapshot. This worked well for about a year, but occasionally one (or more) of the speakers would refuse to play the announcement, but those speakers that did play were in sync.
To get around the issues, I tried using Dov’s TTS_Chime integration. I couldn’t get it to play a custom chime, but using his default chimes and a message (using Google Translate as the TTS platform), it seems to work…but the speakers are, for the most part, slightly out of sync. I don’t use the join/unjoin, as the speakers are a single ‘entity’. I can live with a little out-of-sync, as the speakers are in different rooms. (One nice feature of Dov’s integration is the ability to higher the volume for announcements, then it automatically resets to its original level afterwards.)
I haven’t experimented with it any further since the last time I did (June 2024). I continue to take a snapshot and join speakers prior to playing a preamble (i.e. chime) followed by a message (then restore the snapshot). This technique ensures the selected speakers play in unison (i.e. in sync). It’s all done with a script (that I have been using long before the “announce” feature was introduced to the media_player.play_media action). The script also pauses any content that might already be playing prior to playing the preamble/message (and then restores it).
tl;dr
I don’t use the “announce” feature and continue to use old-school snapshot/join/restore.
Joining them ensures synchronization and, to my knowledge, a Media Group entity doesn’t join its members. That would explain why a Media Group’s members sound “slightly out of sync”.
Hmmm. Interesting. Maybe this is the cause of my angst.
Maybe I’ll experiment with your idea of:
Snapshot (although the Sonos snapshot only allows for one speaker, but there is a “with group” option)
Join - this would be new for me, and maybe the act of joining would force the audio to all speakers, rather than some simply not playing, and of course, synch them
Play (using Media_player.Play_media)
Un-join? Would this be appropriate? The reason that I ask is that generally, I want to treat ALL the speakers in the house as one entity - they get the same announcements and same music (when it’s being played), so there’s probably no mileage in un-joining them