# How Player Configuration Profiles Control Playback Behavior in Music Assistant

> Understand how player configuration profiles in Music Assistant control playback behavior. Learn how they influence buffering, seeking, and now-playing info by adjusting transport headers, audio normalization, and metadata.

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

---

**Player configuration profiles determine HTTP transport headers, audio normalization, and metadata injection, directly controlling how players buffer, seek, and display now-playing information.**

Music Assistant's server architecture allows granular control over audio delivery through player-specific configuration profiles. These profiles, stored per-player in the configuration database, dictate everything from HTTP response formatting to PCM normalization. Understanding how these settings interact with the streaming pipeline is essential for resolving buffering issues, early playback stops, or missing metadata displays on specific hardware.

## HTTP Transport Profiles and Stream Delivery

The most critical profile is the **HTTP profile** (`CONF_HTTP_PROFILE`), defined in [`music_assistant/constants.py`](https://github.com/music-assistant/server/blob/main/music_assistant/constants.py). This setting determines how the streaming controller in [`music_assistant/controllers/streams/controller.py`](https://github.com/music-assistant/server/blob/main/music_assistant/controllers/streams/controller.py) constructs HTTP responses when delivering audio to players.

### Chunked Encoding (`"chunked"`)

When set to `"chunked"`, the server calls `resp.enable_chunked_encoding()` on the HTTP response. This omits the `Content-Length` header and streams data using HTTP/1.1 chunked transfer encoding.

This profile works best with players that support continuous streaming and ignore content size. The player begins playback immediately without waiting for complete track metadata, as data arrives in discrete chunks until the connection closes.

### No Content Length (`"no_content_length"`) — Default

The default profile sends audio as a raw stream without chunked encoding and without a `Content-Length` header. The response body flows continuously until the connection terminates.

This approach suits most modern players that handle steady data streams efficiently. It eliminates the overhead of chunk markers while maintaining compatibility with players that don't require explicit size declarations.

### Forced Content Length (`"forced_content_length"`)

This profile calculates and injects an explicit `Content-Length` header. In [`music_assistant/controllers/streams/controller.py`](https://github.com/music-assistant/server/blob/main/music_assistant/controllers/streams/controller.py), the logic distinguishes between known and unknown track durations:

```python
if http_profile == "forced_content_length" and not queue_item.duration:
    resp.content_length = calculate_content_length(output_format, 12 * 3600)
elif http_profile == "forced_content_length" and queue_item.duration:
    resp.content_length = await get_content_length(...)

```

When the duration is unknown, the server uses a 12-hour placeholder (43,200 seconds). When known, it estimates byte count via `calculate_content_length` or `get_content_length`. This forces strict players to maintain connections for the entire track duration, though it may introduce extra buffering if estimates are inaccurate.

## Audio Processing and Metadata Profiles

Beyond transport layer configuration, additional player configuration profiles affect audio processing and metadata delivery.

### PCM Normalization Profiles

Provider-specific modules implement PCM normalization profiles that control gain adjustment. For example, in [`music_assistant/providers/yandex_ynison/streaming.py`](https://github.com/music-assistant/server/blob/main/music_assistant/providers/yandex_ynison/streaming.py), these profiles select presets that equalize volume across tracks. This ensures consistent loudness levels regardless of the source material's original dynamic range.

### ICY Metadata Profiles

The `CONF_ENABLE_ICY_METADATA` setting (defined in [`music_assistant/constants.py`](https://github.com/music-assistant/server/blob/main/music_assistant/constants.py)) controls whether the server injects ICY tags containing artist, title, and cover art into the stream. When enabled, compatible players display real-time now-playing information extracted from these metadata frames.

## Configuring Profiles via the API

Player profiles are stored per-player in the configuration database and can be manipulated programmatically. Changes typically trigger player reinitialization due to `requires_reload=True` on the configuration entries.

### Reading Current Profile Settings

Retrieve the current HTTP profile for a specific player:

```python
player_id = "my_sonos_player"
http_profile = await mass.config.get_player_config_value(
    player_id, CONF_HTTP_PROFILE, default="no_content_length", return_type=str
)
print(f"The HTTP profile for {player_id} is: {http_profile}")

```

### Modifying HTTP Profiles

Change a player to use forced content length:

```python
await mass.config.set_player_config_value(
    player_id, CONF_HTTP_PROFILE, "forced_content_length"
)

```

### Enabling Metadata and Normalization

Enable ICY metadata injection:

```python
await mass.config.set_player_config_value(
    player_id, CONF_ENABLE_ICY_METADATA, "full"
)

```

Set PCM normalization for supported providers:

```python
await mass.config.set_player_config_value(
    player_id, "pcm_normalization_profile", "high_dynamic_range"
)

```

## Implementation Details in the Streaming Controller

The profile selection logic resides in [`music_assistant/controllers/streams/controller.py`](https://github.com/music-assistant/server/blob/main/music_assistant/controllers/streams/controller.py). When handling audio requests, the controller queries the configuration and applies the appropriate HTTP formatting:

```python
http_profile = await self.mass.config.get_player_config_value(
    player_id, CONF_HTTP_PROFILE, default="default", return_type=str
)
if http_profile == "forced_content_length" and not queue_item.duration:
    resp.content_length = calculate_content_length(output_format, 12 * 3600)
elif http_profile == "forced_content_length" and queue_item.duration:
    resp.content_length = await get_content_length(...)
elif http_profile == "chunked":
    resp.enable_chunked_encoding()

```

This implementation shows how the selected profile directly modifies the HTTP response object before transmission, altering the headers that the player receives and consequently how it manages buffering and playback continuity.

## Summary

- **Player configuration profiles** determine HTTP transport behavior, audio normalization, and metadata injection in Music Assistant.
- The **HTTP profile** (`CONF_HTTP_PROFILE`) offers three modes: chunked encoding, no content length (default), and forced content length, each affecting how players buffer and maintain connections.
- **Forced content length** calculates explicit byte counts using `calculate_content_length` or `get_content_length`, essential for legacy players that require `Content-Length` headers.
- **PCM normalization profiles** and **ICY metadata settings** provide additional control over audio processing and now-playing information display.
- Configuration changes are stored per-player and trigger reloads when `requires_reload=True` is set on the configuration entry.
- Profile application occurs in [`music_assistant/controllers/streams/controller.py`](https://github.com/music-assistant/server/blob/main/music_assistant/controllers/streams/controller.py), directly modifying HTTP response headers before streaming begins.

## Frequently Asked Questions

### What is the default HTTP profile in Music Assistant and when should I change it?

The default profile is `"no_content_length"`, defined in [`music_assistant/constants.py`](https://github.com/music-assistant/server/blob/main/music_assistant/constants.py). This setting streams audio without explicit size declarations or chunked encoding, working well for most modern players. Change to `"forced_content_length"` if your player stops playback early or buffers excessively, as some legacy hardware requires explicit `Content-Length` headers to maintain connections.

### How does chunked encoding affect playback latency?

Chunked encoding (`"chunked"`) typically reduces initial playback latency because the player starts receiving and processing data immediately without waiting for a complete track download. However, some players may exhibit instability if they expect traditional content-length headers or if their HTTP client libraries don't handle chunked transfers efficiently.

### Can I use different profiles for different players in the same group?

Yes. Music Assistant stores profiles per-player in the configuration database. When using universal groups ([`music_assistant/providers/universal_group/player.py`](https://github.com/music-assistant/server/blob/main/music_assistant/providers/universal_group/player.py)), the system handles individual player profiles separately, though the group itself may have its own configuration that affects how child players are managed.

### Why does changing a player profile require a reload?

Configuration entries for player profiles specify `requires_reload=True`, meaning changes trigger player reinitialization. This ensures the new HTTP header strategies, normalization settings, or metadata injection parameters take effect immediately, as the streaming controller must rebuild the audio pipeline with the new parameters.