Radio Station Framework
Installation
Section titled โInstallationโ1) Add The Resource
Section titled โ1) Add The ResourceโPlace rs_radio in your resources and ensure it in server.cfg:
ensure rs_radio2) Required Dependencies
Section titled โ2) Required DependenciesโThe resource requires ox_lib. For legacy FiveM voice, also start the RS-modified pma-voice build. FiveM Enhanced servers using the supported built-in voice API do not require pma-voice.
On legacy servers, use this order in server.cfg:
ensure ox_libensure pma-voiceensure rs_radioOn supported FiveM Enhanced servers, use:
ensure ox_libensure rs_radioFor legacy voice support, download the RS-modified pma-voice build:
Replace your existing pma-voice folder with it (same resource name) before
starting rs_radio. It is stock pma-voice 7.0.1 plus two extra files and a
few hooks for the station audience; everything else in pma-voice is unchanged.
If you see this in the server console, you are still on stock pma-voice:
[rs-radio][WARN] ... No such export setStationAudienceSpeakers in resource pma-voiceThat is not an error in pma-voice or rs_radio - install the build above and restart. FiveM Enhanced servers using the built-in voice API do not need it.
The modified pma-voice build provides the legacy voice backend for:
- DJ mic routing
- cohost monitor/voice routing
- call-in screening
- patched live callers
- station mic participant handling
- listener ducking behavior
For voice backend selection and Enhanced support, refer to docs/voice-backends.md in the resource archive.
3) Audio Dependency Model
Section titled โ3) Audio Dependency ModelโThe world playback path is bundled/internalized inside rs_radio.
You do not need to install a separate external xSound resource for the current build in this repository.
4) Framework / Inventory / Target Compatibility
Section titled โ4) Framework / Inventory / Target CompatibilityโThe boombox system auto-detects the supported runtime stack.
Supported frameworks:
- QBCore
- Qbox
- ESX
Supported inventories:
qb-inventoryox_inventory
Supported target resources:
qb-targetox_target
If no supported target resource is running, boombox interaction should be treated as unavailable.
5) DJ Job Setup
Section titled โ5) DJ Job Setupโrs_radio uses the configured DJ job for tablet access and boss hiring.
Default job name:
dj
Default grades:
0= Trainee1= DJ2= Senior DJ3= Boss
The boss menu requires grade 3 by default. These values must match:
Config.DJJobNameConfig.DJGradesConfig.DJBossGrades
Qbox / qbx_core
Section titled โQbox / qbx_coreโAdd the dj job to:
resources/[qbx]/qbx_core/shared/jobs.lua
Example:
['dj'] = { label = 'Radio DJ', type = 'radio', defaultDuty = true, offDutyPay = false, grades = { [0] = { name = 'Trainee', payment = 25 }, [1] = { name = 'DJ', payment = 50 }, [2] = { name = 'Senior DJ', payment = 75 }, [3] = { name = 'Boss', isboss = true, bankAuth = true, payment = 100 }, },},After editing jobs, restart qbx_core and rs_radio, or restart the server.
Add the same dj job shape to your QBCore jobs file, commonly:
qb-core/shared/jobs.lua
The job key must be lowercase dj, and grade 3 should be marked with isboss = true.
Create the dj job and grades in your ESX jobs database/table or job-management resource.
Minimum requirements:
- job name:
dj - grades:
0,1,2,3 - boss grade:
3
6) Portable Radio Item Setup
Section titled โ6) Portable Radio Item SetupโDefault item names:
radio_boomboxradio_walkboy
Expected image assets:
radio_boombox.pngradio_walkboy.png
This resource auto-detects the runtime stack, but each enabled item still has to exist in your inventory item definitions.
QBCore + qb-inventory
Section titled โQBCore + qb-inventoryโExample:
radio_boombox = { name = 'radio_boombox', label = 'Portable Radio', weight = 2500, type = 'item', image = 'radio_boombox.png', unique = true, useable = true, shouldClose = true, description = 'A portable boombox that can broadcast the station around you.'},radio_walkboy = { name = 'radio_walkboy', label = 'Walkboy', weight = 750, type = 'item', image = 'radio_walkboy.png', unique = true, useable = true, shouldClose = true, description = 'A wearable personal radio with headphones.'},Qbox + ox_inventory
Section titled โQbox + ox_inventoryโQbox servers commonly pair with ox_inventory.
Add an item definition in your ox_inventory item file, commonly:
ox_inventory/data/items.lua
Example:
['radio_boombox'] = { label = 'Portable Radio', weight = 2500, stack = false, close = true, description = 'A portable boombox that can broadcast the station around you.'},['radio_walkboy'] = { label = 'Walkboy', weight = 750, stack = false, close = true, consume = 0, client = { event = 'rs-radio:client:useWalkboyItem' }, description = 'A wearable personal radio with headphones.'},ESX + ox_inventory
Section titled โESX + ox_inventoryโIf your ESX server uses ox_inventory, define the same item there:
ox_inventory/data/items.lua
Example:
['radio_boombox'] = { label = 'Portable Radio', weight = 2500, stack = false, close = true, description = 'A portable boombox that can broadcast the station around you.'},['radio_walkboy'] = { label = 'Walkboy', weight = 750, stack = false, close = true, consume = 0, client = { event = 'rs-radio:client:useWalkboyItem' }, description = 'A wearable personal radio with headphones.'},ESX + another inventory
Section titled โESX + another inventoryโIf your ESX server uses a different inventory, the exact file depends on that inventory resource.
Minimum expectation for each enabled item:
- item names must match
radio_boomboxandradio_walkboy - item should be usable
- images should be
radio_boombox.pngandradio_walkboy.png - item should not stack if your inventory supports unique/non-stackable items
Important Notes
Section titled โImportant Notesโ- The item name in your inventory must match
Config.BoomboxItemNameunless you change the config. - The Walkboy item name must match
Config.WalkboyItemName. - Inventory examples are install references; edit the item file supplied by your inventory resource.
- If you change the item name, keep the same value aligned across
config.luaand your inventory item definitions.
7) Optional Static Radio Props
Section titled โ7) Optional Static Radio PropsโStatic radio props are map/world props, not inventory items. Enable them only on servers that want players to open the listener UI from configured prop models.
In config.lua:
Config.RadioPropTargetsEnabled = trueConfig.RadioPropTargets = { "ex_prop_ex_tv_flat_01", "xm_prop_x17_tv_flat_01", "vw_prop_vw_cinema_tv_01", "prop_tv_flat_01"}The player must be near the prop to control it. Config.RadioPropAutoCloseDistance controls when the UI closes, and the server validates the same range with a small buffer.
This feature requires a running target resource:
ox_targetqb-target
8) Station Media And Data
Section titled โ8) Station Media And DataโStations are defined in:
config.lua- the in-game Station Creator/Admin UI
Fresh installs intentionally start without predefined stations, so every server publishes its own lineup. Existing stations already stored in SQL continue to load and are never deleted by configuration changes.
Most station setup should be done through the Station Creator/Admin UI. That flow handles station identity, branding colors, music, ads, SFX, placement, and review/publish state without requiring server owners to edit JSON by hand.
Open Station Creator:
/radiostationadminThe command requires the configured radio admin group or ACE permission.
The standard package uses server-provided local .ogg and .mp3 files under songs/. Add audio to the station folders described in songs/README.md and select or publish stations through Station Creator.
Only upload files you own or are properly licensed to use. The package does not include a third-party music catalogue or an external-media add-on.
Shared product ads stay global:
data/product_ads.json
9) Admin Tools And Commands
Section titled โ9) Admin Tools And CommandsโCommon public commands:
/radiostationadmin/radioemitterfx/radiolistenerui/radiolisten/radiolisten on/radiolisten off/radiocohost add [serverId]/radiocohost remove [serverId]/radioacceptcohost/radiodeclinecohostOptional command:
/radiotablet/radiotablet only exists when Config.EnableDJTabletCommand = true.
Notes:
/radiostationadminopens the Station Creator/Admin UI./radioemitterfxopens the Emitter FX panel for authorized admins./radiolisteneruiand/radiolistenare listener UI shortcuts.- Cohost commands are mainly backup/manual workflow; the DJ UI provides the normal invite/accept flow.
10) Optional Weather Integration
Section titled โ10) Optional Weather IntegrationโIf using an external weather authority such as rs_weather or av_weather:
- keep
Config.WeatherAuthorityProvider = "auto"or set it to your provider - set
Config.WeatherAuthorityResource = "rs_weather"when usingrs_weather - set
Config.WeatherAuthorityResource = "av_weather"when using AV Weather - for AV Weather, adjust
Config.WeatherAuthorityAvZoneMapif your AV zone names differ from the defaults - let the configured weather resource apply world weather
- let
rs_radioonly read weather state for radio UI/broadcast purposes
Important:
- avoid duplicate world weather application
- when
rs_weatheris active,rs_radioshould behave as a consumer, not a competing weather controller
11) Optional Rebel Radio Door Locks
Section titled โ11) Optional Rebel Radio Door Locksโox_doorlock
Section titled โox_doorlockโIf you use ox_doorlock, rs_radio can automatically install or update the captured Rebel Radio doors when both ox_doorlock and oxmysql are running.
Config toggle:
Config.AutoInstallRebelRadioDoors = true
The auto-installer only inserts missing Rebel Radio rows by name. Existing rows are not deleted or updated.
The repository also includes a manual SQL import:
docs/rebel_radio_doors_ox_doorlock.sql
The included doors are locked by default and restricted to:
djgrade0+
Restart ox_doorlock after the auto-install or manual SQL import if any rows were inserted. This is required for double-door entries to rebuild correctly in ox_doorlock.
qb-doorlock
Section titled โqb-doorlockโqb-doorlock does not use the ox_doorlock SQL table, so rs_radio cannot auto-populate it from the database.
If your server uses qb-doorlock, copy the provided entries into your qb-doorlock door config:
docs/rebel_radio_doors_qb_doorlock.lua
The entries use:
authorizedJobs = { ['dj'] = 0 }locked = true- the same north/south front double doors, garage doors, and booth doors captured for Rebel Radio
After adding the entries, restart qb-doorlock.
12) Restart And Verify
Section titled โ12) Restart And VerifyโAfter installing or updating:
- restart the server or
ensure rs_radio - confirm the
djjob exists in your framework - confirm a grade
3DJ can open the boss menu at the configured station locations - confirm a hired DJ can open the DJ tablet
- confirm listener UI works in a vehicle
- confirm Station Creator opens for an admin group user
- confirm the server-provided local station audio plays correctly
- confirm boombox item flow works if enabled
13) Production Notes
Section titled โ13) Production NotesโBefore production use, verify:
- DJ permissions are configured correctly
- Station Creator/admin tools are restricted to trusted groups or ACE permissions
Config.EnableDJTabletCommandisfalseso DJs use configured station locations- DJ job and boss grades exist in your framework
- boombox item exists for your inventory stack
- only one weather authority is applying world weather
- your target/inventory/framework stack matches one of the supported combinations