A mobile web application for synchronizing multiple Sendspin players in multi-room audio setups.
GroupSync solves the challenge of achieving sample-accurate audio synchronization across multiple Sendspin speakers. Users walk around their listening space holding their phone near each speaker, and the app uses the device microphone to detect audio offset. The calculated offset is then pushed to each player to achieve perfect synchronization.
- Music Assistant Integration - Connects via WebSocket to discover and control Sendspin players
- Automatic Offset Detection - Uses microphone to measure audio delay at each speaker
- Cross-Correlation Algorithm - Sub-millisecond accuracy offset calculation
- Protocol Extension - Pushes offset to players via new
client/sync_offsetmessage - Mobile-First Design - Optimized for walking around with phone in hand
- Connect - Enter your Music Assistant server URL
- Select Players - Choose which Sendspin players to synchronize
- Calibrate - Walk to each speaker, hold phone nearby while calibration track plays
- Apply - Push calculated offsets to all players
GroupSync plays a specially designed click track through all selected speakers simultaneously:
- 20 seconds duration
- Clicks at 1-second intervals
- Rotating frequencies (1kHz, 2kHz, 4kHz, 8kHz) for reliable detection
- Cross-correlation algorithm calculates precise offset
| Component | Technology |
|---|---|
| Framework | React 18 + TypeScript 5 |
| Build | Vite |
| Audio | Web Audio API |
| State | Zustand |
| UI | Tailwind CSS |
- Music Assistant server (v2.7+) with Sendspin player provider
- One or more Sendspin-compatible players
- Mobile device with microphone (iOS Safari or Android Chrome)
- HTTPS connection (required for microphone access)
- windowsSpin - Windows desktop player
- SpinDroid - Android player
- sendspin-js - Web/Cast player
- sendspin-cli - Python CLI player
# Clone the repository
git clone https://github.com/yourusername/groupsync.git
cd groupsync
# Install dependencies
npm install
# Start development server (HTTPS required for microphone)
npm run dev
# Build for production
npm run buildnpm run devOpens at https://localhost:5173 (HTTPS required for microphone access).
npm run build
npm run previewDeploy the dist/ folder to any static hosting service (GitHub Pages, Vercel, Netlify).
None required. Server URL is entered at runtime.
HTTPS is enabled by default for development to allow microphone access:
// vite.config.ts
export default defineConfig({
server: {
https: true,
host: true, // Allow mobile access
},
});GroupSync extends the Sendspin protocol with a new message type:
interface SyncOffsetMessage {
type: 'client/sync_offset';
payload: {
player_id: string;
offset_ms: number; // Positive = delay, negative = advance
source: 'groupsync';
};
}Players receive this message and adjust their internal sync delay accordingly.
groupsync/
├── src/
│ ├── main.tsx # Entry point
│ ├── App.tsx # Main component
│ ├── calibration/ # Audio detection & offset calculation
│ ├── ma-client/ # Music Assistant WebSocket client
│ ├── sync-push/ # Offset push mechanism
│ ├── store/ # Zustand state management
│ ├── components/ # React UI components
│ └── types/ # TypeScript type definitions
├── public/
│ └── calibration-track.wav # Pre-generated click track
└── docs/
├── ARCHITECTURE.md # Technical architecture
└── PROTOCOL.md # Protocol extension details
- Music Assistant - Home music server
- Sendspin Protocol - Synchronized audio streaming
- windowsSpin - Windows Sendspin player
- SpinDroid - Android Sendspin player
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
MIT License - see LICENSE file for details.
- Music Assistant team for the excellent home audio server
- Sendspin protocol designers for the synchronized audio specification