# Music Assistant Player Groups and Sync Groups Management: Architecture and Implementation

> Explore Music Assistant player groups sync groups management architecture. Learn about SyncGroupPlayer and UniversalGroupPlayer synchronized playback and multicast streaming solutions.

- Repository: [Music Assistant/server](https://github.com/music-assistant/server)
- Tags: architecture
- Published: 2026-06-21

---

**Music Assistant server implements two distinct group player architectures—`SyncGroupPlayer` for synchronized multi-room playback and `UniversalGroupPlayer` for virtual multicast streaming—both inheriting from the core `Player` model and managed through a centralized controller with support for dynamic or static membership, idle-grace lifecycle handling, and configurable power controls.**

The Music Assistant server repository provides sophisticated group player capabilities that allow multiple physical audio devices to function as unified logical targets. Understanding the architecture behind Music Assistant player groups and sync groups management is essential for developers integrating with the API or configuring complex multi-room audio setups. The implementation distinguishes between perfectly synchronized playback groups that maintain sample-accurate alignment and universal groups that stream a single encoded audio flow to heterogeneous devices.

## Understanding Group Player Types

Music Assistant defines two primary group implementations, each serving different synchronization and protocol requirements.

### SyncGroupPlayer for Multi-Room Synchronization

The **SyncGroupPlayer** class, defined in [`music_assistant/providers/sync_group/player.py`](https://github.com/music-assistant/server/blob/main/music_assistant/providers/sync_group/player.py), enables perfectly synchronized playback across multiple physical devices. This implementation ensures that audio output remains sample-accurate across all group members, making it ideal for multi-room scenarios where timing alignment is critical.

Key properties include:

- **`sync_leader`** – Designates the current leader player that drives playback for the entire group
- **`supported_features`** – Dynamically aggregates capabilities from the leader, ensuring volume, mute, and DSP controls appear in the UI
- **`requires_flow_mode`** – Mirrors the leader's flow-mode setting, forcing the group to use identical streaming parameters

### UniversalGroupPlayer for Virtual Streaming

The **UniversalGroupPlayer** class, located in [`music_assistant/providers/universal_group/player.py`](https://github.com/music-assistant/server/blob/main/music_assistant/providers/universal_group/player.py), creates a virtual streaming endpoint that serves a single encoded audio flow (FLAC or MP3) to any number of members. This approach benefits protocols that only accept a single source connection but need to distribute audio to multiple physical endpoints.

Key characteristics include:

- **Virtual streaming endpoint** – Exposes URLs at `/ugp/<player_id>.flac` or `/ugp/<player_id>.mp3` for client connections
- **`UGPStream` instance** – Tracks multicast stream state through the `stream` attribute, with `stream.done` indicating active status
- **`supported_sample_rates`** – Derived from `CONF_UGP_OUTPUT_FORMAT` configuration, limiting the group to a single encoded bitrate

## Group Lifecycle and Session Management

Both group types share a common lifecycle implemented in the base `Player` model ([`music_assistant/models/player.py`](https://github.com/music-assistant/server/blob/main/music_assistant/models/player.py)).

### Formation and Activation

Groups follow a three-phase lifecycle:

1. **Formation** – The group automatically forms when playback begins via `cmd_play_media`, establishing the initial member set and selecting a sync leader (for sync groups) or initializing the virtual stream (for universal groups)
2. **Active session** – The `is_active_session` property returns `True` while the leader remains active or the virtual multicast stream is alive
3. **Idle-grace handling** – When playback stops, a timer (`IDLE_GRACE_SECONDS`) maintains the group state to absorb rapid resume actions

### Dissolution

If the idle-grace timer expires, the group **dissolves** and members revert to their prior independent states. For sync groups, dissolution also clears the `sync_leader` attribute.

## Configuring Sync Group Players

### Dynamic vs Static Members

Sync groups support two membership modes controlled by the `CONF_DYNAMIC_GROUP_MEMBERS` configuration entry:

- **Dynamic groups** – When enabled, configured members act as a preset list; the actual member set is built only when the group powers on via `on_config_updated`
- **Static groups** – Member lists from `CONF_GROUP_MEMBERS` are stored in `_attr_static_group_members` and used directly without runtime modification

### Power Control Features

By default, groups lack power control capabilities. Users can enable a virtual power toggle by setting `CONF_POWER_CONTROL` to `PLAYER_CONTROL_FAKE`. When enabled, `supported_features` adds `PlayerFeature.POWER`, allowing UI-based power management even when underlying hardware lacks explicit power commands.

## Configuring Universal Group Players

### Output Format and Sample Rates

Universal groups derive their audio capabilities from the `CONF_UGP_OUTPUT_FORMAT` configuration entry. Unlike sync groups that pass through raw audio, universal groups transcode to a specific format, limiting `supported_sample_rates` to the configured output parameters.

### Dynamic Member Handling

The `is_dynamic` property controls runtime membership changes. When `CONF_DYNAMIC_GROUP_MEMBERS` is enabled, the group advertises `PlayerFeature.SET_MEMBERS`, allowing clients to add or remove members via `cmd_set_group_members` while the stream is active.

## Centralized Group Control Architecture

All group operations are orchestrated by the **players controller** in [`music_assistant/controllers/players/controller.py`](https://github.com/music-assistant/server/blob/main/music_assistant/controllers/players/controller.py). This controller handles configuration updates, persists changes to member lists, and triggers formation or dissolution events.

Key controller responsibilities include:

- Watching for configuration changes via `on_config_updated` callbacks
- Processing group volume commands through `cmd_group_volume`
- Managing member notifications via `iter_group_members`

## Practical API Usage Examples

The following examples demonstrate how to interact with Music Assistant player groups programmatically:

```python

# Retrieve a group player by its ID

group = mass.players.get_player("syncgroup_myroom")
assert group is not None

# Inspect aggregated supported features

print("Features:", group.supported_features)

# Dynamically modify group members (requires dynamic configuration)

await mass.players.cmd_set_group_members(
    group.player_id, 
    ["player1", "player2"]
)

# Initiate playback - triggers automatic group formation

await mass.players.cmd_play_media(
    player_id=group.player_id,
    media=PlayerMedia(url="https://example.com/song.mp3"),
)

# Stop playback - group remains alive for IDLE_GRACE_SECONDS

await mass.players.cmd_stop(group.player_id)

```

## Summary

- **Two distinct architectures** – `SyncGroupPlayer` provides sample-accurate synchronization via a leader-follower model, while `UniversalGroupPlayer` creates virtual multicast streams for protocol-constrained devices
- **Shared lifecycle** – Both types use formation on playback start, active session tracking via `is_active_session`, and idle-grace dissolution controlled by `IDLE_GRACE_SECONDS`
- **Flexible membership** – Support for both static member lists (`CONF_GROUP_MEMBERS`) and dynamic runtime configuration (`CONF_DYNAMIC_GROUP_MEMBERS`)
- **Centralized control** – The players controller in [`music_assistant/controllers/players/controller.py`](https://github.com/music-assistant/server/blob/main/music_assistant/controllers/players/controller.py) manages all group state transitions and configuration persistence
- **Optional power control** – Virtual power toggles can be exposed via `CONF_POWER_CONTROL` when hardware lacks native power management

## Frequently Asked Questions

### What is the difference between SyncGroupPlayer and UniversalGroupPlayer?

**SyncGroupPlayer** maintains perfect synchronization across members by designating a `sync_leader` that drives playback timing, making it ideal for multi-room audio where alignment matters. **UniversalGroupPlayer** creates a virtual streaming endpoint that serves a single encoded audio stream (FLAC/MP3) to multiple clients, which is necessary when target devices only accept individual connections or require specific encoded formats.

### How does dynamic member configuration work in Music Assistant groups?

When `CONF_DYNAMIC_GROUP_MEMBERS` is enabled in the player configuration, the group exposes `PlayerFeature.SET_MEMBERS` and allows runtime modification of the member list via `cmd_set_group_members`. For static configurations, members are defined in `CONF_GROUP_MEMBERS` and stored in `_attr_static_group_members`, remaining fixed during the group lifecycle.

### What triggers the dissolution of a group player?

A group dissolves when the `IDLE_GRACE_SECONDS` timer expires after playback stops, or when the sync leader disappears (for sync groups). During the idle-grace period, the group remains active to accommodate rapid resume actions without requiring re-formation overhead.

### How does the idle-grace period affect group playback?

The idle-grace period maintains the group structure temporarily after `cmd_stop` is called, preventing unnecessary formation overhead during brief pauses. If playback resumes within this window, the group continues with existing members; if the timer expires, the group dissolves and members revert to independent states, requiring full re-formation on the next play command.