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

# Server API

Server-side exports for synced sounds that every player hears.

Server exports create **synced** sounds. Every targeted player hears the same track at the same position. Players who join later, or drive into range later, hear it from the current point in the song.

## Play

```lua
local id = exports.kaze_sound:Play(options)
```

Accepts every [client option](/kazescripts/kaze_sound/client-api.md#options), plus:

| Option              | Type                  | Default | Description                                                     |
| ------------------- | --------------------- | ------- | --------------------------------------------------------------- |
| `targets`           | `-1`, number or table | `-1`    | Who hears it: everyone, one player id, or a list of player ids. |
| `entity`            | server entity         | —       | Server-side entity handle, converted to a network id.           |
| `netId`             | number                | —       | Network id of the entity to follow.                             |
| `destroyWithEntity` | boolean               | `true`  | Remove the sound when the entity is deleted.                    |

{% tabs %}
{% tab title="Club music" %}

```lua
exports.kaze_sound:Play({
    id = 'club_music',
    url = 'https://cdn.example.com/set.mp3',
    coords = vec3(-1388.0, -618.0, 30.8),
    volume = 0.7,
    loop = true,
    maxDistance = 60.0,
    refDistance = 8.0,
    reverbPreset = 'club',
})
```

{% endtab %}

{% tab title="Car radio" %}

```lua
RegisterNetEvent('myradio:play', function(url)
    local src = source
    local vehicle = GetVehiclePedIsIn(GetPlayerPed(src), false)
    if vehicle == 0 then return end

    exports.kaze_sound:Play({
        id = 'radio_' .. NetworkGetNetworkIdFromEntity(vehicle),
        url = url,
        entity = vehicle,
        volume = 0.5,
        maxDistance = 25.0,
        refDistance = 1.5,
        fadeIn = 400,
    })
end)
```

{% endtab %}

{% tab title="Private sound" %}

```lua
-- Only these two players hear it
exports.kaze_sound:Play({
    url = 'nui://kaze_sound/sounds/alarm.ogg',
    coords = vec3(441.0, -981.0, 30.7),
    targets = { 3, 7 },
})
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
Validate URLs before playing anything a player typed in. kaze\_sound plays whatever link it's given.
{% endhint %}

## Control

| Export                           | Description                                                                                                      |
| -------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `Destroy(id, fadeMs?)`           | Remove the sound for everyone.                                                                                   |
| `Pause(id)` / `Resume(id)`       | Pause and resume for everyone.                                                                                   |
| `SetVolume(id, volume, fadeMs?)` | Change volume for everyone.                                                                                      |
| `SetTime(id, seconds)`           | Seek for everyone.                                                                                               |
| `SetUrl(id, url)`                | Switch track, from the start.                                                                                    |
| `SetCoords(id, coords)`          | Move the sound.                                                                                                  |
| `Attach(id, entity)`             | Follow a server entity. Use `Attach(id, netId, true)` to pass a network id.                                      |
| `SetOption(id, key, value)`      | Change an option for everyone, including players who join later.                                                 |
| `SetTargets(id, targets)`        | Change who hears it. Removed players stop hearing it at once, and added players join in at the current position. |

## Read state

| Export            | Returns                                                                   |
| ----------------- | ------------------------------------------------------------------------- |
| `Exists(id)`      | `true` if the sound exists.                                               |
| `IsPaused(id)`    | Paused state.                                                             |
| `GetTime(id)`     | Current position in seconds.                                              |
| `GetDuration(id)` | Track length, known once the first player has loaded it. `0` before that. |
| `GetAll()`        | List of every synced sound id.                                            |

## Automatic cleanup

The server removes a synced sound on its own when:

* a non-looped track finishes,
* its entity is deleted (unless `destroyWithEntity = false`),
* every target player has left the server,
* the resource that created it stops.

## Server events

Use these to build playlists and queues:

| Event                       | Arguments      | Fired when                                                                                                  |
| --------------------------- | -------------- | ----------------------------------------------------------------------------------------------------------- |
| `kaze_sound:server:ended`   | `id`           | A track finished. The sound is already removed, so you can play the next track with the same id right away. |
| `kaze_sound:server:removed` | `id`, `reason` | A sound was removed for another reason: `'entity'` or `'targets'`.                                          |

```lua
local playlist, index = { 'https://cdn.example.com/1.mp3', 'https://cdn.example.com/2.mp3' }, 1

local function playCurrent()
    exports.kaze_sound:Play({ id = 'lobby', url = playlist[index], coords = vec3(0.0, 0.0, 70.0) })
end

AddEventHandler('kaze_sound:server:ended', function(id)
    if id ~= 'lobby' then return end
    index = index % #playlist + 1
    playCurrent()
end)

playCurrent()
```
