Parent : [[INDEX-FIVEM-GAMEPLAY]]
FiveM - Media Streaming NUI + Routing Buckets : TVs instanciées, playback local/externe
Problème
Les TVs dans FiveM doivent synchroniser la vidéo entre joueurs proches, mais pas avec tout le monde sur le serveur. De plus, des appartements ou intérieurs nécessitent des instances séparées.
Solution
Système TV instancié par routing buckets, NUI media player avec sources locales (.mp3/.mp4) et externes (optionnel avec avertissement), target system, vehicle TV offsets.
-- Config
Config.EnableRoutingBucketTv = true -- Instanced TVs (apartments/interiors)
Config.EnableExternalSources = false -- Optional external media (use responsibly)
Config.EnableMediaFromFolder = true -- Local media from html/media folder
Config.VehicleTelevision = true -- TVs inside vehicles
Config.Target = true
Config.Targettype = "oxtarget" -- qtarget, qbtarget, oxtarget
-- Routing bucket TV logic (server-side)
local tvStates = {} -- [routingBucket] = { url, currentTime, playing }
RegisterNetEvent('rtx_tv:sync')
AddEventHandler('rtx_tv:sync', function(tvId, state)
local src = source
local bucket = GetPlayerRoutingBucket(src)
tvStates[bucket] = tvStates[bucket] or {}
tvStates[bucket][tvId] = {
url = state.url,
currentTime = state.currentTime,
playing = state.playing,
timestamp = os.time()
}
-- Broadcast uniquement aux joueurs du même bucket
for _, playerId in ipairs(GetPlayers()) do
if GetPlayerRoutingBucket(playerId) == bucket then
TriggerClientEvent('rtx_tv:update', playerId, tvId, state)
end
end
end)
-- Client sync on bucket change
AddEventHandler('playerRoutingBucket', function(src, oldBucket, newBucket)
if tvStates[newBucket] then
for tvId, state in pairs(tvStates[newBucket]) do
TriggerClientEvent('rtx_tv:update', src, tvId, state)
end
end
end)
Pourquoi
- Routing buckets isolent les instances (appartements, intérieurs) sans conflit
- Sources locales évitent les problèmes de copyright et de latence
- Target system pour l'interaction (ox_target, qtarget)
Quand l'utiliser
- Systèmes de TV dans les appartements, bars, cinémas
- Playback synchronisé de musique/vidéo
Quand NE PAS l'utiliser
- Streaming public de contenu copyrighté (risque légal)
- Si les joueurs n'ont pas besoin d'instance séparée
Exemples
Correct
-- Local media avec fallback
local mediaUrl = 'nui://' .. GetCurrentResourceName() .. '/html/media/' .. filename
if Config.EnableExternalSources and isTrustedUrl(url) then
mediaUrl = url
end
SendNUIMessage({
action = 'play',
url = mediaUrl,
volume = 0.5
})
Incorrect
-- Broadcast global sans bucket → tout le monde voit la même TV
RegisterNetEvent('tv:play')
AddEventHandler('tv:play', function(url)
TriggerClientEvent('tv:show', -1, url) -- Tous les joueurs, tous les buckets
end)
Références
- rtx_tv/config.lua L69-79
- CFX Docs : Routing Buckets