Obsi Lib plays sounds through its own NUI player, with volume that follows the distance live, or through xsound when it is running.

## Playing sounds

```lua
ObsiLib.sound.play('click', { volume = 0.4 })

local id = ObsiLib.sound.playAt(GetEntityCoords(PlayerPedId()), 'engine_loop', { range = 15.0, loop = true })
ObsiLib.sound.setPosition(id, newCoords)   -- volume follows the distance every 100 ms
ObsiLib.sound.stop(id)
ObsiLib.sound.stopAll()
```

Short names play `web/build/sounds/<name>.mp3`.
Add your own files to `web/public/sounds` before [building the UI](/lib/reference/building-the-ui).

## Broadcasting to nearby players

```lua
ObsiLib.sound.broadcast('horn', { range = 30.0, id = 'horn' })  -- everyone near you
ObsiLib.sound.unbroadcast('horn')
```

The server checks the range (up to `ObsiConfig.Sound.MaxBroadcastRange`) and rate (`BroadcastCooldown`).

:::hint{type="warning" title="URLs from clients"}
Clients can only broadcast short sound names.
Set `ObsiConfig.Sound.AllowRemoteUrls = true` to let them broadcast http(s) URLs to other players.
:::

## Streams and URLs

```lua
-- xsound when it runs, the built-in player otherwise
ObsiLib.sound.url('radio_1', 'https://example.com/stream.mp3', { coords = coords, range = 25.0, volume = 0.3 })
ObsiLib.sound.seek('radio_1', 30)   -- xsound only
ObsiLib.sound.provider()            -- 'xsound' | 'nui' | 'none'
```

Server-side sounds are on [Notifications and logs](/lib/server-api/notifications-and-logs#sounds).
