SONOS Synchronisation Issues, Using tts_chime

Is there a problem with joining SONOS speakers? I’m trying to play announcements (via TTS_CHIME add on) when an event occurs at home. e.g motion detected. I created a helper media group (aptly named ‘Sonos Speakers’).

When the monitored event happens, it does play on all the speakers, but they are not synchronized, so it sounds like the announcement is rippling through the house.

Don’t have this issue when using iTunes to play music or the native SONOS app on either my phone or Mac, so it seems like an AirSonos issue.

Workflow:

On Detection of event:

  1. Join speakers (media_join); Basically, I join each Sonos entity to a master entity, in my case the Ktichen speaker pair.
  2. Play announcement on entity ‘Sonos Speakers’

If there is workaround, I’m willing to try that too.

Thanks.

It would be helpful to see your code. Hard to make educated suggestions otherwise.

One general thought: many Sonos speakers rely on the 2.4GHz band, which is very crowded. It’s possible that your media_player.join calls aren’t happening in time. Have you tried, perhaps, a delay of 2-5 seconds between the join call and the call to play the media?

Not sure if that will prove helpful, but it’s a general consideration for many Sonos configurations.

Hmmm. Never thought about the delay option, although it would have to be a short delay, or the person would have run the doorbell before the announcement was made :grinning:.

I do have a Google mesh in the house, so the 2.4 Ghz signal should be fairly strong.

Code below:

- id: '1733684159123'
  alias: Motion Detected
  description: Make announcement if motion is detected, then set flag (which will
    be cleared in 10 minutes)
  triggers:
  - trigger: state
    entity_id:
    - input_boolean.front_door_motion_detected
    from: 'off'
    to: 'on'
    id: FD Motion Sensor
  conditions:
  - condition: state
    entity_id: input_boolean.sonos_announcements
    state: 'on'
  actions:
  - choose:
    - conditions:
      - condition: trigger
        id:
        - FD Motion Sensor
      sequence:
      - action: media_player.join
        metadata: {}
        data:
          group_members:
          - media_player.darrells_office_sonos
          - media_player.barbaras_office_sonos
          - media_player.laundry_room_sonos
          - media_player.guest_bedroom_sonos
          - media_player.master_bathroom_sonos
        target:
          entity_id: media_player.kitchen_sonos_1
      - action: chime_tts.say
        metadata: {}
        data:
          chime_path: bells
          message: Front door motion
          tts_platform: google_translate
          cache: false
          announce: false
          tld: co.uk
          volume_level: 0.6
        target:
          entity_id: media_player.sonos_speaker_group
    - conditions: []
      sequence: []
  mode: single

In all honesty, I’ve had trouble getting media_player.join to be reliable with my Sonos speakers. I abandoned it in favor of staggering announcements throughout the home, most recently in connection with a fake “doorbell” based on an Aqara mini-switch.

The issue with 2.4GHz is not the signal strength. It’s almost the opposite: the issue is that a lot of other devices use the same band, so you get a lot of interference. One way to deal with it is to adjust the WiFi Channel (but you have to be very strategic about it, lest you actually lower your quality of performance).

One thing that has made a huge difference for me: if you own a Sonos sub, connect the sub to your router with an Ethernet cable. The sub will then coordinate the speakers to use the best WiFi channel using its own fake “hotspot.” I am not sure what the magic is that goes into that implementation, but this setup always works better for me than if I let all the speakers run wild, no matter which channel I set them up on.

So, all of my Sonos One speakers do have an ethernet port. However, I was under the impression (maybe incorrectly) that if you connect any one Sonos to the LAN via this method, that Sonos then sets up its own ‘network’. What the implications of that are for, say Apple AirPlay, I’m not sure; if it does break AirPlay, then it’s a non-starter.

In my experience, AirPlay is pretty cruddy.

Either way, though, AirPlay seems to perform the same whether or not you let Sonos create its own WiFi cloud.

Perhaps your results will be different, if AirPlay works for your purposes as is; but why not try?

Well, it’s not the ideal solution, that’s for sure. But, it does seem to work for both my iTunes (where even the Sonos and Homepods in the same room are in sync) and the (lame) Sonos app. It’s just HA-based announcements that are the issue.

While I can probably hardwire 50% of my Sonos directly to the LAN, some are in places where there’s no Ethernet, so have to rely on Wifi.

I’ll try connecting one to the LAN (and forcing Sonos to create it’s own network) to see if that improves things. I’m assuming if I wish to roll back, all I have to do is remove the wired connection and it will automatically revert to Wifi.

That’s been my experience.

I had a similar problem with Sonos and ChimeTTS being out of synch. Here is my solution. This has been working perfectly for quite some time now. You’ll see that I pass all my values to the script, but you can change that to meet your needs.

#################################################################
# Chime TTS Announce
# rocket launch, trash, recycle, laundry, etc
#################################################################
chime_tts_announce:
  alias: "Chime TTS Announce"
  mode: queued
  sequence:
    # ---------------------------------------------
    - action: switch.turn_on
      data: {}
      target:
        entity_id:
          - switch.outside_amp_patio_zw049
          - switch.outside_amp_garage_zw049
    # ---------------------------------------------
    - action: sonos.snapshot
      metadata: {}
      data:
        with_group: true
        entity_id: all
    # ---------------------------------------------
    - action: media_player.join
      target:
        entity_id: media_player.kitchen_white
      data:
        group_members:
          - media_player.kitchen_white
          - media_player.office
          - media_player.living_room
          - media_player.sunroom_black
          - media_player.mbr
    # ---------------------------------------------
    - action: media_player.volume_set
      data:
        volume_level: >-
          {% set current_hour = strptime(states('sensor.time'), "%H:%M").hour | int %}
          {% if current_hour >= 5 and current_hour < 8 %}
            0.30
          {% elif current_hour >= 8 and current_hour <= 17 %}
            0.50
          {% elif current_hour >= 17 and current_hour <= 18 %}
            0.65
          {% elif current_hour >= 19 and current_hour <= 24 %}
            0.40
          {% else %}
            0.45
          {% endif %}
        entity_id:
          - media_player.kitchen_white
          - media_player.office
          - media_player.living_room
          - media_player.sunroom_black
          - media_player.mbr
    # ---------------------------------------------
    # Chime TTS Announce
    - action: chime_tts.say
      data:
        # tts_platform: google_cloud
        language: "{{ language }}"
        voice: "{{ voice }}"
        volume_level: "{{ volume_level }}"
        chime_path: "{{ pre_chime_path }}"
        end_chime_path: "{{ end_chime_path }}"
        message: "{{ message }}"
        offset: "{{ offset }}"
        join_players: true
        announce: false
      target:
        entity_id:
          - media_player.kitchen_white
          - media_player.office
          - media_player.living_room
          - media_player.sunroom_black
          - media_player.mbr
          - media_player.garage_speakers
    # ---------------------------------------------
    - action: sonos.restore
      metadata: {}
      data:
        with_group: true
        entity_id: all
#

Note: The JOIN and ANNOUNCE values in the Chime TTS section are critical to making this work correctly, as is the sonos.snapshot and Sonos.restore. I took me a lot of trial and error to get this to work, but now it’s perfect and works very reliable.

kartcon

1 Like

OK, I see what you’re doing.

  • Sonos snapshot
  • Set volume (depending on time of day. Clever idea.)
  • Chime_tts call, with Announce=false, and Join=True, but you address speakers individually, whereas I use a speaker group
  • Restore Sonos

Wonder why the Announce=false was important? (I have it set as true, currently). I do a manual join before calling chime_tts, because my tts_chime call addresses a single entity (Sonos Speaker Group), so the tts_chime join would fail.

I’ll play with this and see if your approach works. Thanks for the suggestions.

Some background might be helpful here. This script was developed about a year ago, and some improvements to Chime TTS may now negate the need for this solution as it’s written. The primary issues I had at that time were three-fold; synchronization of the spoken text, pausing and resuming the currently playing music, and getting the volume correct for both the announcement and music.

That’s the reason for the Sonos snapshot and restore outside of the Chime TTS commands as well as the volume. I also struggled with the synchronization during the announcement and this combination of JOIN and ANNOUNCE just worked. I’d be interested in hearing what your experience is with this as well as how it affects any music playing at the time of the announcement.

I do keep all my integrations current, but I will admit that I may not read up on all changes that might allow me to do this more efficiently. It’s more a “If it ain’t broke, don’t fix it” approach. In any case, good luck getting your system working and do let me know if there is an easier or better way.

Art - aka kartcon

When using the “announce” option each speaker reads and plays the media independently (and only the left channel on a stereo pair).

So yes, announcing across multiple speakers may result in synchronization issues. The more speakers and the slower your computer the more noticeable this is. On mine it just sounds like reverb.

If you want it synced then the speakers need to be joined into a Sonos group (not a HA group) and play_media called without the announce attribute set to true.

@PeteRage
Thanks for the explanation, and this then validates my original posting.

Thanks, Pete

OK, I just checked my iPhone app and find that I do have a group called (‘Sonos Speaker Group’), which encmpases all the speakers in the house.

So, how is (Sonos group) this reflected in HA, or is it? (I think I asked this question back in 2024, but never got a response.) I guess I’m trying to find out how to leverage the Sonos group with HA.

Use the media player join action. This is the same as going into the Sonos app and playing music across more than one speaker. It is not a permanent grouping.

Oh, OK…

So, the proposed workflow would be:

  1. Media Player join of all speakers
  2. Take Sonos snapshot
  3. Play audio clip (using tts_chime, with NO announcement, and NO native join) on just one of the joined speakers
  4. Restore Sonos snapshot

Not worried about un-joining the speakers, as I only play music and have announcements made house-wide.

Not sure if steps 1 & 2 are in the correct order, ot should be reversed.