A complete, no-root setup for running your own IPTV app on an LG webOS TV β with a self-healing Arabic-first playlist and automation that keeps everything alive.
Built for (and tested on) a 2018 LG TV running webOS 4.4, using only LG's official Developer Mode. No rooting, no firmware changes.
| Feature | What it does | |
|---|---|---|
| π‘ | OmarTV app | A customised build of the excellent open-source webos-iptv-player: Arabic / RTL interface, bigger text, friendlier remote keys |
| π | Never skips a channel | A failing channel tries its alternate streams, then keeps retrying with a growing pause β it never jumps to the next channel on its own |
| π§Ή | Curated playlist builder | Merges several public playlists, probes every stream from your own network, drops the dead ones, groups channels in Arabic categories with your home country first |
| π | Fallback streams | When several sources carry the same channel, the best working stream is published first and the others become automatic fallbacks |
| β | Favourites that survive | Favourites stay attached to the channel even when its stream URL changes |
| β³ | Grace period | A channel that is down today is kept for a few days before it is removed, and comes back by itself |
| π | Developer Mode keep-alive | Extends the TV's Developer Mode session every day, so sideloaded apps are never wiped |
| π | Raspberry Pi ready | Two systemd timers keep the playlist fresh and Developer Mode alive 24/7 |
| πͺ | Windows workflow | One-command build β package β install β launch β logs, plus remote keys and screenshots from the PC |
Public playlists βββ
(iptv-org, β¦) β playlist/curate.mjs ββββββββββββββββ
βββΊ merge Β· probe Β· rank Β· group ββΊ curated.m3u ββββΊ πΊ OmarTV app on the TV
curation.json ββββββ (remembers state between ββββββββββββββββ β²
(your sources, rules, runs in channel-state.json) β
custom channels) β
β
π Raspberry Pi / πͺ PC ββ every 30 min: rebuild when stale, upload ββββββββββ€
βββ every day: extend Developer Mode βββββββββββββββββ
| Folder | Purpose |
|---|---|
playlist/ |
The playlist builder (curate.mjs) and its configuration (curation.json) |
automation/ |
Cross-platform Node jobs: devmode-keepalive.mjs, playlist-refresh.mjs |
pi/ |
Raspberry Pi / Linux installer, systemd units and helper scripts |
scripts/ |
Windows PowerShell workflow (build, deploy, logs, remote keys, β¦) |
apps/ |
The OmarTV patch for webos-iptv-player and how to apply it |
tools/ |
package.json for the LG webOS CLI and ws (installed locally, nothing global) |
docs/ |
Detailed toolkit notes |
- Install the Developer Mode app from the LG Content Store and sign in with a free LG developer account.
- Switch Dev Mode Status on (the TV restarts), then switch Key Server on.
- Note the TV's IP address and give it a fixed address (DHCP reservation) in your router.
You need Node.js 20+ and Git.
git clone https://github.com/smartboy223/LG-webOS-DevKit.git
cd LG-webOS-DevKit/tools
npm ciπͺ Windows (PowerShell, from the repository root):
$env:APPDATA = "$PWD\tools\ares-home"
tools\node_modules\.bin\ares-setup-device -a lgtv -i "username=prisoner" -i "host=<tv-ip>" -i "port=9922" -i "default=true"
tools\node_modules\.bin\ares-novacom --getkey -d lgtv # type the passphrase shown on the TVπ Raspberry Pi / Linux:
./pi/install.sh
./pi/pair-tv.sh <tv-ip>.\scripts\get-app.ps1 # downloads webos-iptv-player v1.16.0 and applies the OmarTV patch
.\scripts\deploy.ps1 # build β package β install β launch.\scripts\update-playlist.ps1The first run probes every stream (about 15 minutes) and uploads the result into the app.
A Pi on the same home network as the TV is the ideal home for the automation β it must share the TV's internet connection so that stream probes see the same geo-blocks the TV does.
./pi/install.sh # Node check, npm dependencies, systemd timers
./pi/status.sh # timers, Developer Mode time left, recent log lines| Timer | Schedule | Job |
|---|---|---|
β° omartv-devmode-keepalive |
daily + after boot | Resets the Developer Mode session timer (works even while the TV is off) |
π omartv-playlist-refresh |
every 30 minutes | Rebuilds the playlist once it is 20 hours old; uploads it when the app is open on the TV |
The refresh job never launches or restarts the app, so it cannot interrupt what you are watching. A new playlist waits until the app is next on screen and is shown the next time the app starts.
Other helpers: ./pi/reinstall-apps.sh (reinstall every .ipk in builds/) and ./pi/uninstall.sh.
π‘ Run the automation in one place only. If you move it to a Pi, remove the Windows tasks:
scripts\scheduled-refresh.ps1 -Uninstallandscripts\devmode.ps1 -Uninstall.
Everything lives in playlist/curation.json and is applied again by every rebuild.
| Setting | Use |
|---|---|
π homeCountry, priorityCountries |
Whose channels come first |
ποΈ arabicGroups, internationalGroups |
Category names and their order |
β additionalSources |
More playlists. "admit": "focus" adds only Arabic / focus channels; "alternates": false for sources with unreliable channel ids |
π― focus |
Extra channels to admit from "focus" sources (by category or name pattern) |
π customChannels |
Your own channels (name, url, optional fallbackUrls, category, country, logo). Never dropped |
π« rules.exclude* |
Leave channels or streams out |
π·οΈ rules.rename, rules.groupOverrides |
Rename channels, add name-based groups |
π merge.maxFallbacks |
How many alternate streams to publish per channel |
β³ retention.keepDeadDays |
How long a channel that is down stays listed |
Handy commands:
node playlist/curate.mjs # full rebuild with probing
node playlist/curate.mjs --reuse-probes # rebuild in seconds from the last probe results
node playlist/curate.mjs --no-probe # regroup onlyplaylist/out/report.json summarises each build: sources used, new Arabic channels found, channels kept while down, and what was dropped and why.
Run from scripts\ in PowerShell.
| Command | What it does |
|---|---|
.\deploy.ps1 |
Check TV β build β package β install β cold start β startup logs |
.\logs.ps1 |
Live console / exception / network-error log from the app |
.\remote.ps1 down,enter |
Send remote-control keys from the PC |
.\update-playlist.ps1 |
Rebuild the playlist and store it on the TV |
.\scheduled-refresh.ps1 -Install |
Daily unattended refresh via Task Scheduler |
.\devmode.ps1 -Install |
Daily Developer Mode keep-alive via Task Scheduler |
.\save-config.ps1 -Destination <folder> |
Snapshot of configuration, app changes and the app's TV data |
.\netcheck.ps1 |
TV download speed, Wi-Fi quality and DNS timings |
More detail: docs/TOOLKIT.md.
| Symptom | Fix |
|---|---|
π Cannot reach TV |
TV on? Developer Mode enabled? IP changed? (ares-setup-device -m lgtv -i "host=<new-ip>") |
| ποΈ Scheduled jobs say "No matched device" | The pairing must live in tools/ares-home β the scripts point the LG CLI there so services and packaged apps all see it |
| π "New playlist waiting" in the log | Normal: open the app on the TV and the next run uploads it |
| π§ App disappeared from the TV | Developer Mode expired or was reset: ./pi/reinstall-apps.sh, then check the keep-alive log |
| π Rebuild "kept the previous playlist" | Fewer than 40% of streams answered β the internet connection was unreliable at that moment |
- πΊ lennylxx/webos-iptv-player β the IPTV player this builds on (Apache-2.0)
- π iptv-org and Free-TV/IPTV β community-maintained lists of publicly available streams
- π§° LG webOS TV CLI
This project contains no streams and no channel content β only tools. The default sources are community lists of streams that broadcasters make publicly available; what you add to curation.json is your responsibility. Use it only with content you are entitled to watch. Not affiliated with LG Electronics or any broadcaster.
MIT for the toolkit. The app patch in apps/ modifies webos-iptv-player and is distributed under that project's Apache-2.0 license (see apps/README.md).