Installation
Step 1 — Download
After your purchase on hzscripts.com/shop, your FiveM Keymaster account receives two separate assets:
- Log in to keymaster.fivem.net (or portal.cfx.re/assets)
- Go to Granted Assets
- Download both:
HZ-Television — the main script
* HZ-PropsCarplay — the 12 in-vehicle CarPlay prop variants (shipped as a dedicated asset so prop updates don't force a re-download of the full logic resource)
HZ-Television, the 12 CarPlay prop models won't stream and CarPlay placement will silently hang at lib.requestModel.Step 2 — Dependencies
Required
- HZ-Bridge — free asset from hzscripts.com/shop. Handles framework / inventory / target / menu / notification detection. Always use the latest version — every HZ-Television release is tested against the latest Bridge. Must start before HZ-Television. See HZ-Bridge Installation.
- HZ-PropsCarplay — downloaded separately from Keymaster alongside HZ-Television (see Step 1). Streams the 12 CarPlay prop variants (
hz_carplay+hz_carplay_1..11) + their calibration JSON. Must start before HZ-Television. - A menu system — at least one of:
- A SQL driver (required for persistence, accounts, playlists, abandon cleanup). HZ-Television auto-detects both at runtime:
Optional
- ox\_target or qb-target — for crosshair-based interaction (otherwise TextUI / DrawText3D fallback)
- lb-phone — required for the phone companion app
lb-hztelevision
oxmysql or mysql-async at boot and installs the matching MySQL.Async shim. You'll see one of these lines in the server console on startup:
[HZ-Television] SQL compat: detected oxmysql, MySQL.Async shim installed
[HZ-Television] SQL compat: detected existing MySQL.Async (mysql-async or compatible)
If you see a red ERROR: no SQL resource detected, make sure ensure oxmysql (or ensure mysql-async) comes before ensure HZ-Television in your server.cfg.
HZ-Bridge/config.lua and every Hz-Script inherits. See HZ-Bridge Configuration.Step 3 — Files
- Extract both archives (
HZ-Television.zipandHZ-PropsCarplay.zip) downloaded from Keymaster in Step 1 - Place the two resulting folders in your
resources/directory — grouping them under a common category folder like[hz-scripts]/keeps things tidy
server/
├── resources/
│ ├── ox_lib/
│ ├── oxmysql/ ← or mysql-async (both supported)
│ ├── [hz-scripts]/
│ │ ├── HZ-Bridge/
│ │ ├── HZ-PropsCarplay/ ← 2nd Keymaster download (12 carplay props + calibration.json)
│ │ ├── HZ-Television/ ← 1st Keymaster download (the main script)
│ │ │ ├── client/
│ │ │ ├── server/
│ │ │ ├── html/
│ │ │ ├── config.lua
│ │ │ ├── fxmanifest.lua
│ │ │ └── ...
Step 4 — Inventory Items
HZ-Television ships 10 placeable items out of the box. Pre-configured item definitions for every supported inventory are in HZ-Television/items/.
Items shipped
| Item | Prop | Description |
|---|---|---|
hz_tv_s / hz_tv_m / hz_tv_l | hz_tv_* | Wall-mounted Smart TVs — small / medium / large |
hz_tv_s_stand / hz_tv_m_stand / hz_tv_l_stand | hz_tv_*_stand | Floor-stand Smart TVs — small / medium / large |
curved_screen_s / curved_screen_m / curved_screen_l | prop_curved_screen_* | Curved cinema screens |
hz_carplay | hz_carplay + 11 variants | In-vehicle CarPlay (placed via keyboard gizmo) |
For ox\_inventory
Open ox_inventory/data/items.lua and append the content of HZ-Television/items/ox_inventory.txt (10 entries including hz_carplay).
Example entry:
['hz_tv_m'] = {
label = 'Smart TV (Medium)',
weight = 12000,
stack = true,
close = true,
description = 'A medium wall-mounted smart TV',
client = {
event = 'HZ-Television:useItem'
}
},
['hz_carplay'] = {
label = 'CarPlay Screen',
weight = 3000,
stack = true,
close = true,
description = 'Dashboard Smart TV — use while sitting in a vehicle',
client = {
event = 'HZ-Television:useItem'
}
},
For qb-inventory / qs-inventory / ps-inventory
Copy the content of the matching HZ-Television/items/ file into your inventory's items file.
HZ-Television:useItem client event, which the script catches and dispatches to the right placement flow (static gizmo for TVs, in-vehicle keyboard gizmo for CarPlay).Step 5 — Database (recommended)
Enable in config.lua:
Config.Placer = {
Persistence = true, -- placed TVs + CarPlays survive restart
MaxPerPlayer = 0, -- 0 = unlimited, N = cap per owner identifier
AutoCleanupDays = 0, -- 0 = disabled, N = auto-remove after N days inactive
AutoCleanupInterval = 6, -- hours between cleanup ticks (0 = startup only)
BlockOnRoad = false, -- true = block placing props on roads (CarPlay exempt)
CleanupAdminPermission = 'admin', -- ACE perm for /tvclean
}
The following tables are created automatically on first startup (all use CREATE TABLE IF NOT EXISTS + additive ALTER TABLE ADD COLUMN IF NOT EXISTS migrations):
hz_television_placed— static placed TVs (walls, floors, curved, billboards)hz_carplay_placed— CarPlay placements keyed by vehicle platehz_tv_users,hz_tv_sessions,hz_tv_favorites,hz_tv_history,hz_tv_playlists,hz_tv_playlist_items— account / login / favorites / history / playlists (populated on first Smart TV login)
Manual install (fallback — v3.4.3+)
If a table fails to create automatically (MySQL user missing CREATE permission, connection string pointing at the wrong database, etc.), you'll see a red error in the server console right after [HZ-Television] SQL compat: ... with the exact table name + error. In that case, run the bundled install.sql manually:
mysql -u <user> -p <database> < resources/[standalone]/HZ-Television/install.sql
…or open HZ-Television/install.sql in phpMyAdmin / HeidiSQL / DBeaver and execute it against your server's database. Then restart HZ-Television. The script only contains CREATE TABLE IF NOT EXISTS statements, so running it twice is safe.
Table 'yourdb.hz_tv_sessions' doesn't exist on login now fails cleanly with a db_not_ready response instead of crashing, and the server log points you at install.sql. Previous versions would crash the session flow.Step 6 — server.cfg
Add the resources to your server.cfg in this order:
# Dependencies (must start BEFORE HZ-Bridge)
ensure oxmysql # or ensure mysql-async — HZ-Television supports both
ensure ox_lib # or qb-menu + qb-input
ensure ox_target # or qb-target (optional)
Framework (if applicable)
ensure qbx_core # or ensure qb-core, or ensure es_extended
ensure qb-core
ensure es_extended
HZ-Scripts — order matters
ensure HZ-Bridge # handles auto-detection
ensure HZ-PropsCarplay # streams the 12 carplay prop variants (separate Keymaster download)
ensure HZ-Television # the TV logic resource
HZ-Bridge, HZ-PropsCarplay, and your SQL driver (oxmysql or mysql-async) must all start before HZ-Television. If HZ-PropsCarplay isn't ensured, the 12 carplay variant models won't stream and CarPlay placement will silently fail at lib.requestModel. If no SQL driver is ensured, persistence silently stops working.Step 7 — Configuration
Open HZ-Television/config.lua and adapt the settings. See Configuration for every option in detail.
Config.Locale—'en'/'fr'/'es'/'de'Config.Permissions— who can use/tvcfg, place TVs, use TVsConfig.Placer.Persistence—trueto enable DB savingConfig.Placer.BlockOnRoad—trueif you want to block road placementConfig.Placer.MaxPerPlayer+Config.Placer.AutoCleanupDays— abandon protectionConfig.BillboardUseSmartTV— which billboard/cinema models should run the full Smart TV UI (default: the 3 curved cinema props + 2 vanilla huge billboards)
Step 8 — Verification
- Start the server
- Console should show (in order):
[HZ-Bridge] detected, detected, ...
* [HZ-PropsCarplay] shared/models.lua loaded
[HZ-Television] SQL compat: detected oxmysql, MySQL.Async shim installed (or detected existing MySQL.Async (mysql-async or compatible))*
* [HZ-Television] v3.4.1 loaded successfully
* [HZ-Television] Database tables initialized
- Connect in-game
- Approach any TV prop (wall TV, curved cinema screen, or use the
hz_carplayitem in a vehicle) - Select Power On → Smart TV → paste a YouTube URL
Quick Troubleshooting
Script doesn't start
Check:
- Folders are correctly named
HZ-Television,HZ-PropsCarplay,HZ-Bridge(case sensitive) - All three are
ensured inserver.cfgin the right order (Bridge → PropsCarplay → Television) - Your FiveM license is valid on Keymaster
- A menu system (
ox_liborqb-menu) isensured before HZ-Bridge
Error "Framework not detected"
Detection is handled by HZ-Bridge. Make sure:
es_extended,qb-core, orqbx_coreisensured before HZ-Bridge- HZ-Bridge is
ensured before HZ-Television - Check the HZ-Bridge console line to verify auto-detection
- Force a framework if needed in HZ-Bridge's
config.lua— e.g.HZBridge.Framework = 'esx'
CarPlay placement silently fails
Most common cause: HZ-PropsCarplay isn't started. lib.requestModel(hz_carplay) hangs forever because the model isn't streamed.
HZ-PropsCarplay is a separate download on Keymaster — not bundled with HZ-Television. Confirm:
- Both assets are listed in your Keymaster Granted Assets and have been downloaded
- The
HZ-PropsCarplayfolder sits next toHZ-Televisioninresources/ ensure HZ-PropsCarplayis in yourserver.cfgbeforeensure HZ-Television- Resource is listed as
startedin the server console
Placed TVs don't save after restart / Error "no SQL resource detected"
HZ-Television needs either oxmysql or mysql-async running. At boot the server console prints one of:
[HZ-Television] SQL compat: detected oxmysql, MySQL.Async shim installed
[HZ-Television] SQL compat: detected existing MySQL.Async (mysql-async or compatible)
[HZ-Television] ERROR: no SQL resource detected (oxmysql or mysql-async)
If you get the red error:
- Make sure
ensure oxmysql(orensure mysql-async) is inserver.cfg - It must come before
ensure HZ-Television— if the SQL resource loads after, the runtime detection misses it - Both drivers are supported — pick one; don't run them simultaneously
Error "Table 'yourdb.hz_tv_sessions' doesn't exist" when a player logs in on a Smart TV
The auto-create step couldn't build one or more tables. You'll see red lines right after SQL compat: detected … during boot:
[HZ-Television] CREATE TABLE hz_tv_sessions FAILED: <error>
[HZ-Television] Import HZ-Television/install.sql manually to create the missing tables.
Fix (v3.4.3+):
mysql -u <user> -p <database> < resources/[standalone]/HZ-Television/install.sql
Or open HZ-Television/install.sql in phpMyAdmin / HeidiSQL / DBeaver and run it against your server's database. Then restart HZ-Television. The file only contains CREATE TABLE IF NOT EXISTS statements — running it twice is safe.
Common causes of the auto-create failing:
- The MySQL user configured in
set mysql_connection_stringdoesn't haveCREATEpermission on the target database → grantCREATE, ALTER, INDEXand reboot - The connection string points at a database the user can read but not write to → verify the DB name
- MySQL running in STRICT mode with incompatible session settings →
install.sqlexplicitly setsSQL_MODE = ''at the top to bypass this
If you see SQL Error 1067 (
Invalid default value for 'last_login') or SQL Error 1075 (Incorrect table definition; there can be only one auto column and it must be defined as a key) when importing install.sql, you're on an older HZ-Television. Both errors were fixed in v3.4.6 — update and re-run the new install.sql.
On v3.4.3+ the login flow now aborts cleanly with db_not_ready when tables are missing, instead of crashing mid-query.
Screen stays black / no display
- Use
/tvcfgnear the TV to calibrate Scale/Offset/Rotation (live cyan preview overlay shows exactly where the cursor hit-box sits) - Test with a simple YouTube video first (not a livestream)
- Check F8 console for JavaScript errors
- For vanilla huge billboards, make sure the model is in
Config.BillboardUseSmartTV(v3.3 render-target auto-detection handles them)
No sound or global sound
- Increase
Config.Display.MaxSoundDistanceinconfig.lua - Make sure the TV is powered on
- Get closer (volume decreases between
MinSoundDistanceandMaxSoundDistance) - For CarPlay specifically: audio has a 5 m cabin range with Web Audio occlusion. Driver + passengers get full clean audio; outside listeners get filtered+attenuated sound
TV items don't appear in inventory
- Add the items from
HZ-Television/items/to your inventory's items file.txt - Restart the server completely after adding items (not just the resource)
- For ox\_inventory the path is
ox_inventory/data/items.lua - For QBCore/QBox it's
qb-core/shared/items.luaorqbx_core/shared/items.lua
