> For the complete documentation index, see [llms.txt](https://acestudios.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://acestudios.gitbook.io/docs/roleplay/live-radio/configuration.md).

# Configuration

Every customer setting in config.lua, plus secrets and hosting permissions.

Live Radio splits its settings across four files:

| File                  | Purpose                                                                                             | Escrow                                                                                      |
| --------------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `config.lua`          | Everyday settings (this page)                                                                       | Editable                                                                                    |
| `config_advanced.lua` | Fine-tuning — most servers never need it                                                            | Editable. See [Advanced Configuration](/docs/roleplay/live-radio/advanced-configuration.md) |
| `server_config.lua`   | Secrets: YouTube API key, Discord webhook                                                           | Editable, **server-only**                                                                   |
| `client/editable.lua` | Your own notification/text UI functions, used when `Config.Notify` or `Config.TextUI` is `'custom'` | Editable                                                                                    |

{% hint style="info" %}
If a value is missing or invalid, the resource falls back to the default and lists a warning in the startup summary. A misspelled setting (`Enabeld = true`) or a secret put in `config.lua` (`Config.YouTubeApiKey`) is named there too, instead of being silently ignored.
{% endhint %}

## Integrations

`'auto'` picks the first one running.

| Option             | Default  | Values                                                                            |
| ------------------ | -------- | --------------------------------------------------------------------------------- |
| `Config.Framework` | `'auto'` | `qbcore`, `qbox`, `esx`, `standalone`                                             |
| `Config.Inventory` | `'auto'` | `ox_inventory`, `qs-inventory`, `qb-inventory`, `framework` (the framework's own) |
| `Config.Notify`    | `'auto'` | `ox_lib`, `qbcore`, `qbox`, `esx`, `okokNotify`, `gta`, `custom`                  |
| `Config.TextUI`    | `'auto'` | `ox_lib`, `qbcore`, `qbox`, `esx`, `gta`, `custom`                                |
| `Config.Target`    | `'auto'` | `ox_target`, `qb-target`, `none` (key prompt)                                     |

The framework is used for job/gang hosting permissions and usable items, the inventory for `HostItem` and the headphones/boombox/DJ deck items, the text UI and target for the boombox and DJ deck prompts. If a chosen notification or text UI fails, the GTA one is used instead. `pma-voice` and `xsound` are required and need no setting.

## General

| Option                  | Default            | Description                                     |
| ----------------------- | ------------------ | ----------------------------------------------- |
| `Config.RadioName`      | `'Ace Live Radio'` | Display name used throughout the script.        |
| `Config.Locale`         | `'en'`             | `en`, `de`, `fr`, `es`, `pt`, `nl`, `tr`, `ar`. |
| `Config.StationListKey` | `'Q'`              | Opens the station list. `false` = command only. |
| `Config.HostConsoleKey` | `'F6'`             | Opens the host console.                         |

## Permissions

```lua
Config.EveryoneCanHost = true
Config.AuthorizedHosts = {
    -- ['license:xxxx'] = true,
    -- ['discord:1234'] = { '93.7', '94.7' },
}
Config.HostJobs = { -- ['weazel'] = 0, -- lowest grade
}
Config.HostGangs = { -- ['ballas'] = 2,
}
Config.HostItem = false       -- e.g. 'microphone'
Config.AdminAcePermission = 'command'
```

With `Config.EveryoneCanHost = false`, a player can host when any of these match:

* their identifier is in `Config.AuthorizedHosts` (a table value further limits them to those frequencies only);
* their job is in `Config.HostJobs`, or their gang in `Config.HostGangs`, at the listed grade or higher (needs QBCore, Qbox or ESX);
* they own a **reserved frequency** (only for that frequency).

`Config.HostItem = 'microphone'` additionally requires carrying that item, checked with the inventory from `Config.Inventory`.

`Config.AdminAcePermission` is the ACE permission that unlocks `/liveradioadmin`. Your existing admin group likely already has the default `command` permission:

```
add_ace group.admin command allow
add_principal identifier.license:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx group.admin
```

## Stations

| Option                                    | Default                              | Description                                                                                               |
| ----------------------------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------- |
| `Config.DefaultRange`                     | `'Local'`                            | `Local`, `Regional` or `Global`.                                                                          |
| `Config.RangeDistance`                    | `{ Local = 50.0, Regional = 300.0 }` | Meters for each range. Global skips range checks.                                                         |
| `Config.MaxStationsPerPlayer`             | `1`                                  | `0` = no limit.                                                                                           |
| `Config.MaxTracksPerStation`              | `50`                                 | `0` = no limit.                                                                                           |
| `Config.RemoveAbandonedStationsAfterDays` | `14`                                 | `0` = never remove.                                                                                       |
| `Config.AllowedTrackDomains`              | `{}`                                 | Empty = any site. Example: `{ 'youtube.com', 'youtu.be' }`.                                               |
| `Config.StationGenres`                    | 14 genres                            | Pop, Hip-Hop, R\&B, Rock, Electronic, Latin, Country, Jazz, Classical, Oldies, Talk, News, Sports, Other. |

{% hint style="info" %}
`MaxStationsPerPlayer` and `MaxTracksPerStation` apply only to ad-hoc stations, never to a player's reserved frequency.
{% endhint %}

## Reserved frequencies

```lua
Config.ReservedFrequencies = {
    -- ['93.7'] = { Host = 'discord:1234', Range = 'Global' },
}
Config.ReservedFrequenciesOnly = false
```

A reserved frequency's `Host` can always host on it, regardless of `Config.EveryoneCanHost`. Set `ReservedFrequenciesOnly = true` to stop players hosting anywhere except a frequency reserved for them.

## Server stations

Permanent stations defined in `config.lua`, running from server start with no owner. `Mode` is `'Music'` (needs a `Playlist`) or `'Podcast'` (open-mic, no playlist).

```lua
Config.ServerStations = {
    {
        Frequency = '87.5',
        Mode = 'Music',
        Name = 'Los Santos Hits',
        Genre = 'Pop',
        Description = 'The biggest pop hits, all day long.',
        Playlist = {
            'https://www.youtube.com/watch?v=...',
        },
    },
    {
        Frequency = '101.1',
        Mode = 'Podcast',
        Name = 'Open Mic',
        Genre = 'Talk',
        Description = 'Anyone can join and talk. Be nice.',
    },
}
```

Four example stations ship by default: two music stations (`87.5`, `97.5`) and two podcasts (`101.1`, `105.3`).

{% hint style="warning" %}
The default music stations queue **official artist videos** on YouTube. Make sure your server is allowed to play commercial music, or replace the playlists with your own tracks.
{% endhint %}

## Features

```lua
Config.CarRadio        = { Enabled = true }
Config.SignalFade      = { Enabled = true }
Config.MusicDucking    = { Enabled = true }
Config.OneWayBroadcast = { Enabled = true }
Config.Headphones      = { Enabled = true, Item = false, KeyPutsOn = false }
Config.Boombox         = { Enabled = true, Item = false, MaxPerPlayer = 2, AnyoneCanTune = false }
Config.DJDeck          = { Enabled = true, Item = false, MaxPerPlayer = 1, AnyoneCanTune = false, CertifiedOnly = false }
Config.Community       = { Enabled = true }
```

Turning a feature off here disables it entirely. See [Listening Modes](/docs/roleplay/live-radio/listening-modes.md) and [Boombox & DJ Deck](/docs/roleplay/live-radio/boombox-and-dj-deck.md) for what each option does, and [Station Community](/docs/roleplay/live-radio/station-community.md) for `Config.Community`.

## Certified DJs

Used only when `Config.DJDeck.CertifiedOnly = true`:

```lua
Config.CertifiedDJs = {
    -- ['license:xxxx'] = true,
}
Config.DJJobs = {
    -- ['vanilla'] = 0, -- lowest grade
}
```

See [Boombox & DJ Deck](/docs/roleplay/live-radio/boombox-and-dj-deck.md#dj-deck) for the full picture.

## Discord logging

```lua
Config.DiscordLog = {
    StationCreated   = true,
    StationRemoved   = true,
    AdminActions     = true,
    Bans             = true,
    SecurityWarnings = false,
}
```

`SecurityWarnings` logs blocked actions from modified clients, and is off by default. Set the webhook URL in `server_config.lua`, not here — see [Server-only secrets](#server-only-secrets).

## YouTube playlist import

Hosts can paste a YouTube playlist link to add all of its videos, up to `Config.MaxTracksPerStation`. It needs a free **YouTube Data API v3** key from [Google Cloud Console](https://console.cloud.google.com). Put it in `server_config.lua` (`ServerConfig.YouTubeApiKey`), **never** in `config.lua`, since that file is downloaded by every player. Without a key, pasting a playlist link tells the host that import isn't set up.

## Languages

Set `Config.Locale` to `en`, `de`, `fr`, `es`, `pt`, `nl`, `tr` or `ar`. Text lives in `locales/<code>.json`.

{% hint style="warning" %}
**Only English is written by hand.** The other seven languages are machine-assisted. Have a native speaker check them before relying on them, and fix any line directly in its file. Any line missing from a language file falls back to English.
{% endhint %}

To add a language, copy `locales/en.json` to `locales/<code>.json`, translate the text on the right (keep words in `{braces}` as they are) and set `Config.Locale` to that code. Arabic switches the panels to right-to-left. To preview a language in a browser build of the UI, open it with `?locale=de` (or any other code).

## Server-only secrets

`server_config.lua` is loaded only by the server and never sent to players:

```lua
ServerConfig.YouTubeApiKey = ''
ServerConfig.DiscordWebhook = ''
```

Instead of editing the file, you can set the same values with convars in `server.cfg` — use `set`, never `setr`:

```properties
set ace_liveradio_youtube_api_key "your-youtube-api-key"
set ace_liveradio_discord_webhook "https://discord.com/api/webhooks/..."
```

## Debug mode

```properties
setr ace_liveradio_client_debug true
set  ace_liveradio_server_debug true
```

{% hint style="info" %}
The **client** setting must use `setr` so players' games can read it. The server setting uses `set`.
{% endhint %}
