> For the complete documentation index, see [llms.txt](https://audalaxy.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://audalaxy.gitbook.io/docs/playerservices/playerservices.md).

# Playerservices

The Audalaxy Playerservices are a collection of scalable and highly available system services for player clients. This system service delivers all types of metadata to player clients, e.g. web player, apps, skills, etc. With stream start using a unique meta id, the client connects to Audalaxy-Player services and receives synchronized metadata in real time for general or a unique listener session. Inside the metadata content several types of information can be delivered, e.g. title, artist or cover, but also control commands and opportunities to show commercials. By now only artist and track title together with a timestamp are garanteed to be delivered. The available data fields depened on what the playout system sends to the metaport.

**Protocols:**

* SSE (server sent events)
* Websockets (real-time)
* HTTPs, HTTP (polling with server-side cache)

## SSE

Our Playerservices for metadata now also support **SSE (Server-Sent Events)**.\
SSE is a modern standard for server-to-client delivery of data and provides an alternative to WebSockets.

Because communication is one-way — server to client only — this model fits perfectly the Audalaxy metadata use case. SSE runs natively over HTTP/2 and requires no protocol upgrade (such as `wss://` with WebSockets), which significantly improves compatibility with proxies.

| Type     | Endpoint                                                     |
| -------- | ------------------------------------------------------------ |
| Channel  | `https://api.streamabc.net/metadata/sse/channel/:channelkey` |
| Listener | `https://api.streamabc.net/metadata/sse/listener/:metaid`    |
| Station  | `https://api.streamabc.net/metadata/sse/station/:stationid`  |

**We emit two types of events:**

* `metadata` - this event type contains metadata in our JSON format. Channel, station and listener SSE endpoints emit this event type.
* `companionad` - this event is only available for SSE listener endpoints and emits companion ad events as JSON if enabled for a channel.

Make sure to subscribe to add event listeners to either one or both.

**Example:**

```html
<script type="text/javascript">
   const eventSrc = new EventSource("https://api.streamabc.net/metadata/sse/listener/123456test1");

   const renderMetadata = (event) => {}
   const renderEvent = (event) => {}

    eventSrc.addEventListener("metadata", renderMetadata);
    eventSrc.addEventListener("companionad", renderCompanionAd);
</script>
```

## Websockets

`wss://api.streamabc.net/metadata/listener/{metaid}` \
(Websockets Listener Metadata)

`wss://api.streamabc.net/metadata/channel/{channelkey}` \
(Websockets Channel Metadata)

`wss://api.streamabc.net/metadata/station/{stationkey}` \
(Websockets Station Metadata)

To use the websockets endpoints you need to subscribe and listen for incoming JSON messages. There are PING messages that are sent to keep the connection alive and that have to be answered with PONG messages. The browser implementation of the websockets API usually does this automatically.

A simple Javascript browser example can be found here:

```javascript
<pre id="now"></pre>
<pre id="next"></pre>
<pre id="status"></pre>
<script>
    const now = document.getElementById("now");
    const next = document.getElementById("next");
    const status = document.getElementById("status");
    const socket = new WebSocket("wss://api.streamabc.net/metadata/channel/qc_fkvwoo65bsvz_tuzx");

    socket.onopen = function () {
        status.innerHTML += "Status: Connected\n";
    };

    socket.onclose = function () {
        status.innerHTML += "Status: Disconnected\n";
    };

    socket.onmessage = function (e) {
        const metadata = JSON.parse(e.data);
        console.log(metadata);
        if (metadata.type === "next") {
            next.innerHTML = "Es folgt: " + metadata.song + " von " + metadata.artist;
        } else {
            now.innerHTML = "Es läuft: " + metadata.song + " von " + metadata.artist;
        }
    };
</script>
```

## Polling

`https://api.streamabc.net/metadata/channel/{channelkey}.json` \
(Channel JSON Polling)

`https://api.streamabc.net/metadata/channel/{channelkey}.txt` \
(Channel TXT Polling)

`https://api.streamabc.net/metadata/station/{stationkey}.json` \
(Station JSON Polling, metadata for all channels of this station)&#x20;

`https://api.streamabc.net/metadata/listener/{metaid}.json` \
(Listener JSON Polling, metadata a specific listener, please consider using Websockets here)

**Example request**:

```bash
curl https://api.streamabc.net/metadata/channel/qc_fkvwoo65bsvz_tuzx.json
```

**Example response**:

```json
{
    "rawdata": "",
    "userplayout": false,
    "channel": "Audalaxy ShowCase Sequenz",
    "session": "",
    "position": "c9eb8216c09ccf4541edadee70178aa1",
    "marker": "",
    "id": "",
    "mount": "",
    "channelkey": "qc_fkvwoo65bsvz_tuzx",
    "timestamp": "2021-12-01T17:58:32Z",
    "artist": "Adele",
    "song": "Someone Like You",
    "station": "audalaxy",
    "start": "01.12.2021 17:58:32",
    "duration": 294,
    "start_timestamp": 1638381512,
    "type": "now",
    "etype": 1008
}
```

Response JSON Object:

* **time** (*time.Time*) – ISO 8601 combined date-time format
* **start** (*string*) – local date-time
* **start\_timestamp** (*int64*) – unix timestamp
* **duration** (*int*) – Length of the audio item
* **song** (*string*) – song name
* **artist** (*string*) – artist name
* **code** (*string*) – code
* **channelkey** (*string*) – channelkey - unique key / ID of the stream
* **timezone** (*string*) – time zone of the time specification
* **channel** (*string*) – channelkey - unique key / ID of the stream
* **id** (*string*) – reference ID
* **userplayout** (*bool*) – default: `false` | `true` in case of personalized audio stream
* **separator** (*string*) – separator between artist and song, default is ” - “
* **etype** (*int*) – Content-type ID of the audio item as an integer
* **type** (*string*) – type of record
* **isrc** (*string*) – ISRC of the audio item

## Listener specific Metadata

In order to activate listener specific metadata you need to start a stream by providing a unique meta id for each listener as query parameter `metaid` as part of the stream url.

You than use the same meta id to either subscribe to the websocket or access the polling endpoint.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://audalaxy.gitbook.io/docs/playerservices/playerservices.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
