Play custom sounds in FiveM: NUI audio, volume by distance, formats
Play custom sounds on FiveM with NUI audio (SendNUIMessage and an HTML audio element), distance-based volume, OGG files, xsound and native audio banks.
You have a sound file, such as a doorbell, a siren or a notification, and you want to play it from a script. FiveM has no simple native for custom audio files, so the usual answer is NUI: a hidden web page in your resource that plays the file when a client script asks it to. This is how resources in the style of interact-sound work. Below you find the code, the distance volume, the formats and the other options.
How it works
- The resource has an HTML page (
ui_page) with a small script. - The client script sends a message to the page with
SendNUIMessage. - The page creates an
Audioobject with the file and plays it.
The page can stay invisible, and it needs no mouse focus.
The resource
resources/[mic]/my_sounds/
fxmanifest.lua
client.lua
html/
index.html
sounds/
doorbell.ogg
alarm.ogg-- fxmanifest.lua
fx_version 'cerulean'
game 'gta5'
ui_page 'html/index.html'
files {
'html/index.html',
'html/sounds/*.ogg',
}
client_script 'client.lua'The sound files must be in files, or the page cannot load them.
The HTML page
<!DOCTYPE html>
<html>
<body>
<script>
window.addEventListener('message', (event) => {
const data = event.data
if (data.action !== 'play') return
const audio = new Audio('./sounds/' + data.file + '.ogg')
audio.volume = Math.min(Math.max(data.volume ?? 1.0, 0), 1)
audio.play().catch((err) => console.log('sound error', err))
})
</script>
</body>
</html>audio.volume goes from 0.0 to 1.0. Values outside that range cause an error, so the code clamps it.
The client script
local function playSound(file, volume)
SendNUIMessage({
action = 'play',
file = file,
volume = volume or 1.0,
})
end
RegisterNetEvent('my_sounds:play', function(file, volume)
playSound(file, volume)
end)
exports('PlaySound', playSound)Now another client script can call exports.my_sounds:PlaySound('doorbell', 0.6), and the server can send TriggerClientEvent('my_sounds:play', source, 'doorbell', 0.6) to one player, or -1 for all of them.
Tip: for a sound a player should hear all the time (a notification, a phone ringtone), this is all you need. For a sound that belongs to a place, use the distance version below.
Distance-based volume
For a sound at a point, such as an alarm on a building, the server sends the coordinates, and each client decides how loud it is:
-- client.lua
RegisterNetEvent('my_sounds:playAt', function(file, coords, maxDistance, baseVolume)
local pos = GetEntityCoords(PlayerPedId())
local dist = #(pos - vec3(coords.x, coords.y, coords.z))
if dist >= maxDistance then return end
local volume = (1.0 - dist / maxDistance) * (baseVolume or 1.0)
playSound(file, volume)
end)-- server.lua: everyone gets it, only players in range hear it
TriggerClientEvent('my_sounds:playAt', -1, 'alarm', vec3(120.0, -1300.0, 29.0), 40.0, 1.0)This checks the distance once, when the sound starts. For a long sound where the player moves, send the position again at intervals, or keep the audio object in the page and update its volume as the client sends new values. A sound that must follow a moving vehicle is where a ready made library helps, as in the next section.
Keep the server in control of who triggers what. If you let clients send a play for everyone event, any cheater can spam sounds to the whole server. See server events and security.
File formats and size
- OGG: the best default, small and good quality.
- MP3: also fine, and easy to find.
- WAV: works, but it is large. Use it only for very short effects.
Every file in files is downloaded by every player, so keep it short, mono for effects, and compressed. Trim silence at the start of the file: a delay that you hear in game often comes from that. If the total is big, the same warning applies as for other assets: see oversized assets.
xsound and other libraries
Instead of writing the page yourself, you can use a sound library such as xsound. It plays audio from a file or an URL at a position or on an entity, and can change the volume and the position later, which suits music in a bar or a boombox that follows a player. Read its README for its exact exports, since they differ between versions. The idea is the same: a hidden NUI page plays the audio, and a client script controls it.
Native sounds and audio banks
The game's own sounds are another option. They are played with natives such as PlaySoundFrontend or PlaySoundFromCoord, with the sound's name and set, and need no files from you. Adding your own sounds to the game's audio system is also possible, with audio bank files and data_file lines for audio, but it is a specialist job with its own tools and it is easy to break. For most servers, NUI audio is simpler and enough.
Common problems
- No sound at all. Check the file name and that the file is in
files. Open the NUI in the game's developer tools if you have them, and read the console for a 404. - Sound plays only once. Create a new
Audioobject each time, as in the code above, or resetcurrentTimeon a kept one. - Too loud or too quiet. Keep volume from 0.0 to 1.0, and set it low by default.
- The sound is cut when the resource restarts. The page is reloaded with the resource. That is expected.
- A script that uses
interact-soundfails. Resources that expect that name need a resource with the same name and exports. Check what the script wants before you rename yours.
Checklist
| Symptom | Fix |
|---|---|
| Nothing plays | Put the files in files and check the ui_page line |
| Wrong path | Use ./sounds/<name>.ogg relative to the HTML page |
| Too loud | Clamp audio.volume between 0 and 1, and lower the default |
| Sound should fade with distance | Send coordinates and compute the volume on the client |
| Download is slow | Use short OGG files and compress them |
| Moving source (vehicle) | Use a library such as xsound, or update the volume as the player moves |
Quick answers
What audio format should I use?
OGG is a good default: small files and well supported by the game's browser. MP3 also works. Avoid WAV for anything long, since the files are large and every player downloads them.
Do I need SetNuiFocus to play a sound?
No. Playing audio from NUI needs no focus and no visible interface, only a page loaded with ui_page that contains the audio code.
How do I make a sound quieter when the player is far away?
Send the coordinates of the sound to the client, measure the distance to the player and set the audio volume from it, for example linearly from 1 close to 0 at the maximum distance.
Scripts that skip this problem
Arcade MachinesSeven playable arcade games in real cabinets, with leaderboards and bets.View script →
Mic PhoneA foldable phone that unfolds into a tablet and carries onto a player's real phone.View script →
Crypto MiningBuy a warehouse, build rigs part by part and mine coins on a market that moves.View script →