A Home Assistant custom integration for synchronizing audio playback across different speaker platforms (Sonos, Google Cast, etc.) using microphone-based latency detection.
- Cross-platform speaker sync: Synchronize Sonos speakers with Google Cast devices
- Microphone-based calibration: Automatically detect and compensate for latency differences between speakers
- Works with Sonos Era 100: Uses direct UPnP API (SoCo) - no AirPlay required
- Cross-correlation algorithm: Accurately detects audio delays using chirp signals
- Calibration Phase: The integration plays a test chirp signal on each speaker individually
- Recording: A microphone (e.g., USB microphone connected to Home Assistant host) records the audio
- Analysis: Cross-correlation is used to measure the exact latency for each speaker
- Compensation: When playing audio, speakers are started with compensated timing to achieve sync
- USB microphone connected to the machine running Home Assistant
- Sonos speakers (including Era 100/300)
- Google Cast speakers (Google Home, Nest, Chromecast Audio)
- numpy >= 1.24.0
- scipy >= 1.10.0
- sounddevice >= 0.4.6
- soco (for Sonos control)
- pychromecast (for Google Cast control)
- Open HACS in Home Assistant
- Click the three dots in the top right corner
- Select "Custom repositories"
- Add this repository URL:
https://github.com/hovborg/ha-music-sync - Select "Integration" as the category
- Click "Add"
- Search for "Music Sync" and install it
- Restart Home Assistant
- Download the
custom_components/music_syncfolder - Copy it to your Home Assistant's
custom_componentsdirectory - Restart Home Assistant
- Go to Settings > Devices & Services
- Click + Add Integration
- Search for "Music Sync"
- Follow the configuration flow:
- Select speakers to synchronize
- Configure microphone device (optional, uses default if not specified)
- Set sample rate (default: 44100 Hz)
Calibrate all configured speakers.
service: music_sync.calibrate_allCalibrate a specific speaker.
service: music_sync.calibrate_speaker
data:
entity_id: media_player.living_room_speakerManually set the offset for a speaker (in milliseconds).
service: music_sync.set_offset
data:
entity_id: media_player.living_room_speaker
offset_ms: 50Clear all calibration data.
service: music_sync.clear_offsetsThe integration creates sensors for each configured speaker showing:
- Current offset (ms)
- Calibration confidence score
- Last calibration timestamp
- A chirp signal (1000-4000 Hz sweep, 200ms) is generated
- The signal is saved to
/config/www/music_sync/and served via Home Assistant's built-in web server - Each speaker plays the signal while the microphone records
- Cross-correlation is used to find the peak offset between the original and recorded signal
- The confidence score indicates how reliable the measurement is (>10 is considered good)
The algorithm uses FFT-based cross-correlation for efficient detection:
correlation = signal.correlate(recorded, reference, mode="full", method="fft")
peak_index = np.argmax(np.abs(correlation))
offset_samples = peak_index - len(reference) + 1
offset_ms = (offset_samples / sample_rate) * 1000- Sonos Era 100/300: AirPlay (RAOP) has been removed from firmware, but UPnP control works
- Google Cast: Initial buffering can add 5-20 seconds delay; calibration accounts for this
- Alexa: Very limited API access; not currently supported
- Ensure the microphone is connected and recognized by the OS
- Check
sounddevice.query_devices()output - Try specifying the device ID explicitly in configuration
- Move the microphone closer to the speakers
- Reduce background noise during calibration
- Increase the calibration signal duration
- Re-run calibration
- Check network latency to speakers
- Ensure all speakers are on the same network segment
# Run the test script
python test_sonos_google_sync.py --discover
python test_sonos_google_sync.py --list-audio
python test_sonos_google_sync.py --test-miccustom_components/music_sync/
├── __init__.py # Integration setup
├── manifest.json # Integration manifest
├── config_flow.py # Configuration UI
├── coordinator.py # Main sync coordinator
├── media_player.py # Media player entity
├── services.yaml # Service definitions
├── const.py # Constants
├── calibration/
│ └── audio_analyzer.py # Cross-correlation analysis
└── platforms/
├── sonos_api.py # Sonos (SoCo) wrapper
└── cast_api.py # Google Cast wrapper
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Submit a pull request
MIT License - see LICENSE file for details.
- SoCo - Sonos Controller library
- pychromecast - Google Cast library
- Home Assistant - Home automation platform