Saltar al contenido
Native Audio Builder

Native Audio Builder

Turn WAV, MP3 or OGG files into a FiveM native audio resource and play them from Lua on the UI, on an entity or at a position, synced if you want.

Esta documentación está en inglés por ahora.

Open the tool Last updated

The Native Audio Builder turns your sound files into a complete FiveM resource that plays them as real game audio: the .awc wave bank, the .dat54.rel sound data, fxmanifest.lua with the right data_file lines, and Lua to load the bank and play sounds. No CodeWalker step is needed. It is for script devs who want custom sounds without a NUI page.

What it is for

Most servers play custom sounds through NUI, a hidden browser page with an audio tag. That works, but the game does not know the sound exists: no 3D position, no distance falloff, no game volume slider, and every client runs a browser page for it. Native audio puts your files into the game’s own audio system, so PlaySoundFrontend, PlaySoundFromEntity and PlaySoundFromCoord play them like any Rockstar sound.

Typical uses: phone ringtones and notification sounds, a siren or horn attached to a vehicle, an alarm at a bank that everyone nearby hears, UI clicks for a custom menu, door buzzers and radio chatter.

Looking for a base game sound instead? Use the Sound Browser.

Quick start

  1. Open the tool and use Choose audio files or Choose folder, or drag files or a folder onto the page.
  2. Check each sound’s Name and Sound set. These are the two strings you pass to the play functions.
  3. Set Resource name in the Bank panel (for example my_sounds). The wave pack, data file and default sound set follow it.
  4. Press play on a row to hear what the game will get.
  5. Tick Loop for sounds that should repeat until you stop them.
  6. Fix anything shown in red, then press Download resource.
  7. Unzip, put the my_sounds folder in your resources, add ensure my_sounds and run /my_sounds_test in game.

Input

  • Formats: WAV, MP3 and OGG work everywhere. FLAC, M4A, AAC, Opus and WebM work when your browser can decode them. Other files are skipped with a count.
  • Up to 200 sounds per bank.
  • Stereo and multichannel files are mixed down to mono, and every file is converted to the bank’s sample rate. The row shows the length, the channel change and the rate change (for WAVs), for example 2.40 s, 2 ch to mono, 44100 to 32000 Hz.
  • Each file becomes one sound named after the file: lowercase, anything other than letters and digits becomes _, cut at 48 characters. Door Buzzer (2).wav becomes door_buzzer_2. A second file with the same name in the same set gets _2, _3 and so on.
  • The sound set comes from the folder the file is in. Drop in/phone/ring.mp3 and in/alerts/beep.wav and you get the sets phone and alerts. Files dropped without a folder go into the Default sound set.
  • Sounds whose name contains loop or alarm, or that sit in a set called ringtone or ringtones, start with Loop on.

Drop more files anywhere on the page at any time to add them. Clear removes every sound.

Note

Everything runs in your browser. Your audio is decoded and converted locally and the zip is built on your PC. Nothing is uploaded.

The sound list

Each row has:

Control What it does
Play / Pause Preview after conversion: sample rate, mono downmix, trimming, normalizing, the codec, the row’s volume and loop. What you hear is close to what the game plays.
Name The sound name, first argument of the play natives. Lowercase letters, digits, _ and -.
Sound set The sound set name. Lowercase letters, digits and _. Existing sets are suggested as you type.
Volume dB Volume stored in the sound, from -60 to +6. Default 0.
Loop The sound repeats until you call StopNative (or StopSound).
Remove Removes the sound from the bank.

Under each row you see a small waveform, the source file name, length and conversion info, and Copy call, which copies a ready line like exports['my_sounds']:PlayNative('beep', 'my_sounds_set'). Problems for that sound are listed right under it.

Bank settings

Setting What it does Default
Resource name Folder name of the resource and the name you ensure. Lowercase letters, digits, _ or -. Changing it also updates the three names below while you have not edited them yourself. my_sounds
Wave pack Folder that holds the bank inside audio/, and the first half of the bank path in Lua. dlc_my_sounds
Bank File name of the .awc, second half of the bank path. sounds
Data file File name of the .dat54.rel. my_sounds_sounds
Default sound set Set for files dropped without a folder. Apply to all puts every sound in this set. my_sounds_set
Codec ADPCM is 4x smaller and lossy. PCM is lossless and 4x bigger. ADPCM
Sample rate 48000, 44100, 32000, 24000 or 22050 Hz. Every sound in the bank uses the same rate. 32000 Hz
Category The mix group the game puts the sounds in: scripted_louder or scripted. scripted_louder
Trim silence Cuts silence at the start and end, so sounds fire on time. on
Normalize Raises or lowers each sound so its peak sits at -1 dBFS. off
Synced playback Adds server.lua to play a sound for every player nearby. on
CodeWalker source Adds the .awc.xml, .rel.xml and WAVs next to the resource, for editing later. on

Wave pack, Bank and Data file allow lowercase letters, digits and _ only.

The summary card shows the number of sounds, the total length and an estimated .awc size. Changing the sample rate, trim or normalize reconverts every sound; the download button waits until that is done (“Converting audio…”).

Choosing codec and rate

  • ADPCM is fine for effects, voice and most music. Very hard edged synth sounds (square waves) lose detail, use PCM for those.
  • 32 kHz keeps banks small and is plenty for effects and UI sounds. Use 44.1 or 48 kHz for music.
  • The whole bank is loaded into memory when a script requests it. Keep long music or big packs in a bank of their own (a second resource) and load it only when you need it.

Checks

Errors block the download, warnings do not.

Level Check
Error Resource name, Wave pack, Bank or Data file with characters that are not allowed; sound name with characters other than lowercase a-z, 0-9, _, -; name over 64 characters; sound set with characters other than lowercase a-z, 0-9, _; the same name twice in one sound set; two names that clash inside the bank or with each other (rename one); a sound that is empty after conversion (for example pure silence with Trim on); volume outside -60 to +6 dB; a sound set that already exists in the base game; a file the browser could not decode.
Warning A sound longer than 30 seconds (the whole bank sits in memory once loaded).

Output

What is in the zip

Download resource saves <resource>.zip:

Text
my_sounds/
  fxmanifest.lua
  client.lua                              load the bank, play, stop, free
  server.lua                              only with Synced playback
  audio/dlc_my_sounds/sounds.awc          the wave bank
  audio/data/my_sounds_sounds.dat54.rel   the sound data
codewalker_source/                        only with CodeWalker source
  sounds.awc.xml
  sounds/*.wav
  my_sounds_sounds.dat54.rel.xml

Put only the my_sounds folder in your server’s resources. codewalker_source is for you, not for the server. The message under the button shows the exact size of the .awc and .dat54.rel after the download.

The code tabs under the list show client.lua, server.lua (with Synced playback), fxmanifest.lua, the .rel.xml and the .awc.xml before you download.

fxmanifest.lua

fxmanifest.lua
fx_version 'cerulean'
game 'gta5'
lua54 'yes'

description 'Native audio bank built with fivemad.com/tools/native-audio-builder'

client_script 'client.lua'
server_script 'server.lua'

files {
    'audio/data/my_sounds_sounds.dat54.rel',
    'audio/dlc_my_sounds/sounds.awc',
}

-- sound data: the path of the .dat54.rel without "54.rel"
data_file 'AUDIO_SOUNDDATA' 'audio/data/my_sounds_sounds.dat'
-- wave pack: the folder that holds the .awc bank
data_file 'AUDIO_WAVEPACK' 'audio/dlc_my_sounds'
server.cfg
ensure my_sounds

Important

The AUDIO_SOUNDDATA path ends in .dat, not .dat54.rel, and AUDIO_WAVEPACK points at the folder, not the .awc. Both files must also be in files { }, or clients never download them. The generated manifest already does this, keep it that way if you merge it into another resource.

client.lua

The generated client.lua loads the bank when the resource starts (it waits up to 10 seconds and prints an error if the bank does not load) and releases it when the resource stops. It defines these functions, all also available as exports:

Function What it does Returns
PlayNative(name, soundSet, loop) 2D sound (UI, phone, notifications) via PlaySoundFrontend. sound id
PlayNativeOnEntity(name, soundSet, entity, loop) 3D sound that follows a ped, vehicle or prop via PlaySoundFromEntity. sound id
PlayNativeAtCoords(name, soundSet, coords, range, loop) 3D sound at a position via PlaySoundFromCoord. range defaults to 20.0. sound id
SetNativeVolume(id, volume) Changes the volume of a playing sound, 0.0 to 1.0.
StopNative(id) Stops the sound and frees its id.

One shot sounds free their sound id by themselves when they finish. Looped sounds keep their id until you call StopNative, so store it. The loop argument only controls that cleanup; whether a sound actually repeats is set by the Loop toggle when you build the bank.

It also registers a test command named after the resource: /my_sounds_test plays every sound one after the other (looped ones for 5 seconds), /my_sounds_test beep plays just one.

Examples

Inside the same resource (add your code to client.lua or another client script of the resource):

client.lua
-- UI sound
PlayNative('beep', 'my_sounds_set')

-- follows the vehicle
local veh = GetVehiclePedIsIn(PlayerPedId(), false)
PlayNativeOnEntity('horn', 'my_sounds_set', veh)

-- heard up to 30 m from the bank door
PlayNativeAtCoords('alarm', 'my_sounds_set', vector3(150.2, -1040.5, 29.4), 30.0)

-- looped ringtone at half volume, stopped later
local id = PlayNative('ringtone', 'my_sounds_set', true)
SetNativeVolume(id, 0.5)
Wait(8000)
StopNative(id)

From another resource, use the exports:

phone/client.lua
local ring = exports['my_sounds']:PlayNative('ringtone', 'phone', true)

RegisterNetEvent('phone:answered', function()
    exports['my_sounds']:StopNative(ring)
end)

Synced playback

For everyone nearby to hear a sound, the server has to tell them. With Synced playback on, server.lua exports two functions that check each player’s distance (needs OneSync) and send the sound only to players in range:

bank_robbery/server.lua
-- everyone within 30 m of the vault hears the alarm
exports['my_sounds']:PlayAtCoords('alarm', 'my_sounds_set', vector3(255.0, 225.0, 101.9), 30.0)

-- everyone within 30 m (the default) hears the horn on that networked vehicle
exports['my_sounds']:PlayOnEntity('horn', 'my_sounds_set', vehicle)

PlayAtCoords defaults to a 20 m range, PlayOnEntity to 30 m. The play natives also have an isNetwork argument, but it does not load your bank on the other clients, so the server event approach is the reliable one.

Editing the bank later

With CodeWalker source on, the zip has everything to rebuild the bank in CodeWalker: open RPF Explorer, turn on edit mode, and drag sounds.awc.xml (with the sounds folder of WAVs next to it) and the .dat54.rel.xml into a folder. CodeWalker builds the binary files, drag them back into the resource. Or drop the WAVs into this tool again and download a new bank.

Common mistakes

  • No sound at all. The bank did not load: check the F8 console for “could not load audio bank”, then check the data_file lines and that both files are in files { }. Restart the resource after changing the manifest and reconnect.
  • Wrong sound set or name. Both strings are case sensitive in your scripts. Copy them with Copy call.
  • Sound plays only for you. PlayNative is local. Use the server exports with Synced playback for sounds others must hear.
  • Looping sound never stops. Keep the id returned by the play function and call StopNative(id).
  • Name clash with the game. Sound sets share one namespace with every game sound, so give them your own prefix. The tool refuses sets that already exist in the base game.
  • Huge bank. A bank with ten minutes of music at 48 kHz is loaded into memory as a whole. Split music into its own resource.

Limitations

  • The page cannot play the finished .awc and .rel in the game itself, so test the resource on your own server before you ship it.
  • Output is mono. Multichannel banks (the stereo format radio stations use) are not built here.
  • One sample rate, codec and category per bank.
  • Up to 200 sounds per bank.
  • Files you drop are kept only for this page visit. After a reload, drop them again.

Based on lb-nativeaudio by LB Scripts.