FAQ
General
Is the script compatible with my framework?
HZ-Television supports QBCore, QBox, ESX and Standalone. Detection is handled by hz_lib — configure once there and HZ-Television (+ every other Hz-Script) inherits automatically.
Can I have multiple TVs with different content at the same time?
Yes — this is one of the main selling points. Every nearby TV renders its own independent content (no 5-screen cap since v2.3, no 12-TV cap since the DrawSpritePoly rewrite). Even the DashScreen feature — every vehicle with a hz_dashscreen item gets its own texture-isolated variant so driving past 12 cars in traffic = 12 different Smart TVs.
How many players can watch the same TV?
Unlimited. Real-time sync is handled via plate-based and coords-based events (5 s heartbeat, 1.5 s drift tolerance, 0.1 s precision, instant seek/play/pause). Late joiners get the exact playback position on connect.
What about routing buckets / instances?
Fully bucket-aware since v3.1.2. TVs, billboards, operator locks, and playlist loops are all isolated per instance. Two TVs at the same coords in different instances never collide.
Does it use a lot of resources?
Client idle: ~0.01 ms. Six active on-screen TVs: ~0.03 ms (cached DrawSpritePoly vertex data). Server: ~0.00 ms. See Performance.
Installation
Error: "Resource HZ-TelevisionProps not found"
hz_televisionprops ships bundled with your HZ-Television download (v3.4+) but must be ensured separately in server.cfg. Add ensure hz_televisionprops before ensure hz_television. Without it, the 12 DashScreen prop variants don't stream and DashScreen placement silently hangs at lib.requestModel.
Error: "Menu system not detected"
The script requires ox_lib (recommended) or qb-menu + qb-input. Install one and ensure it before hz_lib (which itself starts before HZ-Television).
TV items don't appear in my inventory
You must manually add the items to your inventory's items file. Pre-configured snippets are in hz_television/items/:
ox_inventory.txt→ox_inventory/data/items.luaqb-inventory.txt→qb-core/shared/items.lua(orqbx_core/shared/items.lua)qs-inventory.txt→qs-inventory/shared/items.lua
Complete server restart required after adding items (not just
restart hz_television).
I'm using ak47_inventory — items show but don't trigger when used
ak47_inventory isn't in hz_lib's auto-detected list (ox_inventory, qb-inventory, qs-inventory, ps-inventory, codem-inventory, origen_inventory, core_inventory, tgiann-inventory). The bridge falls back to ESX native, but ak47 intercepts use-item events before ESX sees them, so RegisterUsableItem never fires.
Fix per the ak47_inventory docs: wire the callback directly inside the item definition with server.onUse. Open your ak47 items config (typically ak47_inventory/shared/items.lua or ak47_inventory/configs/items.lua) and add:
["hz_dashscreen"] = {
name = "hz_dashscreen",
label = "DashScreen Screen",
weight = 3000,
type = "item",
close = true,
server = {
onUse = function(source, item)
TriggerClientEvent('hz_television:useItem', source, { name = 'hz_dashscreen' })
end,
},
},
Repeat for hz_television_screen if you also use the wall / cinema TVs. Drop the matching .png into your ak47 UI images folder. Then ensure ak47_inventory and ensure hz_television.
SQL Error 1067 or 1075 when importing install.sql
Both are strict-mode MariaDB rejections fixed in v3.4.6:
- Error 1067 on
last_login—timestamp DEFAULT NULLrequires an explicitNULLdeclaration in strict mode. Nowtimestamp NULL DEFAULT NULL - Error 1075 on
hz_dashscreen_placed— theid AUTO_INCREMENTcolumn needed aPRIMARY KEY. Now declared
install.sql. CREATE TABLE IF NOT EXISTS skips already-created tables, so only the two previously-failing ones get created. No data migration.
Generic_texture_renderer_gfx — do I need it?
No. Since v2.3 the rendering engine usesDrawSpritePoly directly. The old scaleform dependency is gone.
How do I update?
- Download latest from keymaster.fivem.net
- Back up your
config.luaandtv_config.json - Replace every file except those two
- Check the Changelog for new config keys
- Restart the server
ensure hz_televisionprops to server.cfg, and review the new Config.Placer.BlockOnRoad / MaxPerPlayer / AutoCleanupDays fields.
DashScreen (v3.2+)
How do I place a DashScreen in my car?
- Put the
hz_dashscreenitem in your inventory - Get in a vehicle (driver seat)
- Use the item — a preview prop spawns on the dashboard and a keyboard gizmo takes over
- Arrow keys = position, Scroll = height, Q/D (or A/D) = rotate, Z/S (or W/S) = tilt, Enter = confirm, Escape = cancel
- Once placed, use your target system (ox\_target / qb-target) on the car to Turn On DashScreen → Smart TV
The vehicle drifts while I'm fine-tuning the gizmo
Fixed in v3.4 — the vehicle is now automatically frozen for the duration of the gizmo (FreezeEntityPosition + velocity zeroed + controls disabled). Unfrozen on confirm / cancel.
The cam doesn't face forward when I use the DashScreen item
Fixed in v3.4 — first-person cam now snaps to heading=0 / pitch=0 on cockpit-view switch, regardless of where the player was aiming before.
Why don't I hear the DashScreen when I'm outside the car?
Intentional — DashScreen is cabin audio, not a PA speaker. The Web Audio occlusion pipeline (v3.3) fades out completely past 5 m from the vehicle. Inside the car (driver + passengers), audio is fully clean and unfiltered. Listeners in a 5 m bubble outside get a lowpass-filtered, volume-attenuated version depending on how many doors are open.
Adjust Config.DashScreen.AudioCabinRange if you want a different bubble size.
Can I have more than 12 DashScreens on the map?
Yes — unlimited placements. Each client renders the 12 nearest (one per texture-isolated variant), so beyond 12 simultaneously visible on the same client the farther ones are invisible until you approach.
I don't want the in-vehicle DashScreen feature at all
Disable it cleanly via config.lua (v3.4.5+):
Config.DashScreen = { Enabled = false }
This skips the hz_dashscreen* RegisterUsableItem loop, the target option registration, the placer prompt, the reconciliation tick — everything DashScreen-specific. Wall / cinema / billboard TVs continue to work normally.
My DashScreen sometimes falls off after a violent crash
Fixed in v3.4.6 — the reconciliation tick's not-attached invariant detects when IsEntityAttached(prop) returns false (the prop got detached by collision physics), releases the slot, and re-acquires it on the next pass (≤ 500 ms). The prop snaps back onto the same vehicle at its original offsets, and the DUI reactivates automatically because PoweredOn[cpId] is preserved across the release.
Enable Config.Debug = true to see the release reason (not-attached) in the F8 console.
Usage
Screen is black or nothing displays
Checklist:- Is the TV powered on? (Turn On via target menu)
- Has the model been calibrated? Use
/tvcfgnear the prop — the live cyan preview overlay shows exactly where the cursor hit-box sits - For vanilla huge billboards, add the model to
Config.BillboardUseSmartTV(v3.3 render-target auto-detection handles them automatically) - Test with a simple direct video file first, not a livestream
- Check F8 for JS errors
Cursor clicks are off / miss the icons
- Flat props: use
/tvcfgand adjust Scale / Offset / Rotation. The cyan overlay is the exact hit-box. - Curved props: make sure the model has a
Curve = { Radius, Arc, Invert }entry and that the arc overlay (16 cyan segments) aligns with the real surface. SetCurve.Invert = truefor props that curve toward the viewer.
No sound / sound too low
- Power the TV on
- Get closer — volume decreases linearly between
MinSoundDistanceandMaxSoundDistance - Raise
Config.Display.MaxSoundDistancefor a larger audio range - For DashScreen: audio only plays inside the car (+ a 5 m bubble around it)
A video URL doesn't play
Embedded sources: some pages disable embedding, or restrict it by region. Test the URL in a normal browser in incognito — if it doesn't play in an embed there, it won't play in-game either. Live channels: a stream source must point at a live channel URL, not an archive. V3 uses the source's native player SDK where one exists, so volume / pause / mute work natively.Other players don't see my Web Browser content (login required sites)
Every player's TV is its own independent CEF browser instance with its own cookies and session. The script syncs the URL to all viewers, but not the session state — that's a fundamental browser-isolation limit of how DUIs work, not a script bug.
A URL that depends on an account therefore renders per player, each seeing whatever their own session returns. Only publicly reachable URLs render identically for everyone.
Late joiners don't see the video / browser content
Real-time sync (5 s heartbeat, 1.5 s drift tolerance) catches them when they stream the TV in — they get the current playback position automatically.
If you're seeing late joiners get a blank screen on browser mode specifically, the issue is usually a race between DUI creation and the first SetDuiUrl call when the player streams in. Make sure your hz_television is up to date (the late-join browser sync was hardened in recent versions with retry passes).
Other things to check:
- OneSync must be enabled (
set onesync oninserver.cfg) - If you're inside a routing bucket, both players need to be in the same bucket — the sync events are bucket-scoped on purpose
Configuration
How do I add a custom TV / billboard model?
- Add an entry in
Config.Modelskeyed by model name with a reasonable starting Scale / Offset / Rotation - Load in-game, get close to the prop
- Run
/tvcfg→ pick the model → calibrate with the 3D gizmo; the cyan overlay shows the hit-box in real time - For curved screens, tick Curve + set Radius / Arc / Invert
- Save — values are written to
tv_config.json
How do I block players from placing props on roads?
Enable the v3.4 road guard:
Config.Placer.BlockOnRoad = true
The placement preview outline turns red when aiming at a road surface and Enter is blocked. DashScreen in-vehicle placement is always exempt — that's the point of DashScreen.
How do I prevent inactive players from leaving TVs behind forever?
Use the v3.4 abandon-protection fields:
Config.Placer = {
MaxPerPlayer = 5, -- hard cap per owner
AutoCleanupDays = 45, -- remove after 45 days inactive
AutoCleanupInterval = 6, -- re-scan every 6 hours
}
Also available on demand via /tvclean run (admin command) or exports['hz_television']:RunHZTVCleanup().
How do I wipe all placements for a specific player?
/tvclean purge <identifier>
Also: /tvclean list shows the top 20 owners by inactivity to help you find abandoned accounts.
Placed TVs disappear on restart
Enable persistence:
Config.Placer.Persistence = true
Requires oxmysql. Tables hz_television_placed and hz_dashscreen_placed are created (+ migrated for the last_seen column) automatically.
How do I add pre-recorded channels?
Config.Channels = {
{ name = 'Weazel News', url = 'https://example.com/stream.m3u8', category = 'news' },
{ name = 'LS Rock Radio',url = 'https://example.com/stream.m3u8', category = 'music' },
}
Appears as a "Channels" section in the Smart TV UI.
Permissions
Reserve TVs / placement for admins only
Config.Permissions = {
UseTV = 'admin',
PlaceTV = 'admin',
}
Job-based gating
Config.Permissions = {
UseTV = 'job:police,ambulance',
PlaceTV = 'job:estate',
}
Format: 'job:jobname' or 'job:job1,job2' for multiple.
Advanced / Integration
TVs don't sync between players
Enable OneSync — set onesync on in server.cfg. Also make sure you're on a reasonably recent FiveM build (2802+).
Lag / stutter with many TVs
Since v3.1 the rendering engine caches vertex data, so 6 on-screen TVs cost about the same as 1 TV pre-cache. If you still hit issues, lower Config.Display.RenderDistance (e.g. 30 m) and Config.Display.DefaultRange (e.g. 20 m).
Error "Failed to load video" in F8
Usually an embed restriction, regional block, or deleted video. Test the URL in a normal browser with incognito. If the URL needs browser rendering, pass mode = 'browser' when calling PlayVideoOnTelevision.
How do I disable billboards entirely?
Remove billboard models from Config.BillboardUseSmartTV AND from Config.Models. The vanilla GTA V billboards (prop_huge_display_01/02) will then fall back to their default render-target content (which is usually nothing in-game).
How do I integrate with esx\_property / qb-houses?
Use server events to gate placement — see Exports & Events for full examples.
AddEventHandler('hz_television:placeTV', function(model, coords, heading)
local src = source
if not exports['esx_property']:IsPlayerInOwnedProperty(src) then
TriggerClientEvent('esx:showNotification', src, 'You must be in your property')
CancelEvent()
end
end)
Emergency broadcast on all TVs
Use PlayVideoOnTelevision over the list from GetAllPlacedTVs — see the Exports examples.
