> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rktscripts.com/llms.txt
> Use this file to discover all available pages before exploring further.

# RKT Musicfy

> Immersive spatial music and DJ system for FiveM.

# Introduction

**RKT Musicfy** is an immersive sound system for FiveM. It combines a Spotify-style music player, a portable Bluetooth boombox, per-vehicle radio with realistic acoustics, and a full two-deck DJ booth with crossfader — all built on true 3D spatial audio.

<CardGroup cols={2}>
  <Card title="3D Spatial Audio" icon="volume-high">
    Distance-based volume rolloff, per-vehicle-class range, and dynamic door/roof muffling.
  </Card>

  <Card title="Bluetooth Handoff" icon="bluetooth">
    Seamlessly move your session between a portable boombox and any vehicle's radio.
  </Card>

  <Card title="DJ Booth" icon="record-vinyl">
    Two independent decks with crossfader, monitor mode, pitch control and seek.
  </Card>

  <Card title="Playlists & Search" icon="magnifying-glass">
    Search YouTube directly in-game, save playlists to the database, and share public ones.
  </Card>
</CardGroup>

## Quick Start

1. **Download**: place the `rkt_musicfy` folder in your server's `resources` directory.
2. **Dependencies**: requires `ox_lib` and `oxmysql`. The `xsound` resource is only needed if you set `Config.AudioEngine = "xsound"` — by default Musicfy uses its own native audio engine.
3. **Install the search engine**: run `npm install` inside the `rkt_musicfy` folder. This installs `youtube-search-api`, used by `server/search.js` to power in-game search.
4. **Start the resource**: add `ensure rkt_musicfy` to your server configuration, after `ox_lib` and `oxmysql`.

<Info>
  If `npm install` wasn't run, search by name will fail — direct YouTube links still work since they don't depend on the JS search engine.
</Info>

## Configuration

Every setting lives in `config.lua`.

```lua theme={null}
Config.Debug = true

-- Audio engine: "xsound" (external dependency) or "native" (built into the script)
Config.AudioEngine = "native"

Config.MaxDistance = 20.0      -- Default range for the boombox
Config.DefaultVolume = 0.5

-- Per vehicle-class listening range
Config.VehicleDistances = {
    ["default"] = 20.0,
    ["super"]   = 25.0,
    ["utility"] = 40.0,        -- e.g. sound cars/vans
}

Config.BoomboxProp = `prop_boombox_01`

-- DJ Booth
Config.DJBooth = {
    coords   = vector3(0.0, 0.0, 0.0),
    distance = 25.0,
}

-- Commands
Config.Commands = {
    open = "spotify",
    dj   = "dj",
}
```

| Field                         | Description                                                                                                        |
| :---------------------------- | :----------------------------------------------------------------------------------------------------------------- |
| `AudioEngine`                 | `"native"` uses the built-in engine (no extra dependency). `"xsound"` delegates playback to the `xsound` resource. |
| `MaxDistance`                 | Default hearing range, in meters, for the boombox prop.                                                            |
| `VehicleDistances`            | Hearing range per vehicle class — falls back to `default` when a class isn't listed.                               |
| `BoomboxProp`                 | Prop model spawned when music plays outside a vehicle.                                                             |
| `DJBooth.coords` / `distance` | Position and broadcast range of the DJ booth. Set `coords` to the real location on your map.                       |
| `Commands.open` / `dj`        | Chat command names for the player UI and the DJ booth.                                                             |

## Commands & Keybinds

| Command                        | Description                                          |
| :----------------------------- | :--------------------------------------------------- |
| `/spotify`                     | Opens the music player UI.                           |
| `/dj`                          | Opens the DJ Booth UI.                               |
| `/musica_vol [0-100]`          | Sets your personal master volume.                    |
| `G` (keybind `musicfy_toggle`) | Drops the boombox on the ground or picks it back up. |

## How It Works

Each player's music session is bound to a single "sound owner" entity — either their portable boombox or the vehicle they're in.

<Steps>
  <Step title="Play">
    Hitting play with no active entity spawns a boombox (on foot) or plays straight through the vehicle radio you're sitting in.
  </Step>

  <Step title="Bluetooth Connect">
    Entering a vehicle while a boombox is active swaps the session to the vehicle's radio, and vice-versa when you exit.
  </Step>

  <Step title="Acoustics">
    Vehicle sound is muffled (reduced volume and range) whenever all doors, windows and the roof are closed — and restored instantly once one opens.
  </Step>

  <Step title="Auto-stop">
    If the sound-owner entity is deleted or despawns, the session stops for every listener automatically.
  </Step>
</Steps>

Sessions are synced server-side, so anyone who joins mid-session — or is near the entity when the resource restarts — hears the music already in progress.

## DJ Booth

The DJ Booth is an independent two-deck system (`A` and `B`) that broadcasts from a fixed position (`Config.DJBooth`), separate from any player's personal boombox/radio session.

* **Crossfader & per-deck volume** — mix between decks live.
* **Monitor mode** — the DJ can preview a deck privately at full volume without it affecting the public mix.
* **Pitch control** — adjustable playback rate between `0.5x` and `2.0x`.
* **Seek & progress sync** — scrub tracks with live position updates every 250ms.

## Playlists & Search

Search accepts a song/artist name (resolved through the bundled YouTube search engine) or a direct YouTube/audio link. Results can be played immediately, saved to a favorites list, or added to a playlist.

Playlists are stored in the `musicfy_playlists` table:

| Column                 | Description                                                           |
| :--------------------- | :-------------------------------------------------------------------- |
| `owner`                | Player identifier (Steam, or license as fallback).                    |
| `name` / `description` | Playlist metadata.                                                    |
| `songs`                | JSON array of tracks.                                                 |
| `is_public`            | When enabled, the playlist is visible and importable by every player. |

<Info>
  Public playlists can be imported (cloned) by other players into their own library via the in-game UI.
</Info>
