The Problem
Enterprises that run their own Xtream‑Codes or M3U IPTV sources need a self‑hosted UI that can handle thousands of channels without choking the browser. Existing players are either cloud‑only or require heavyweight desktop clients, making deployment behind a corporate firewall painful.
What This Does
nodecast-tv serves a single‑page React/Express app that streams Live TV, VOD, and EPG data directly from the configured provider. The front‑end lives in public/ (e.g. public/index.html, public/js/app.js) while the back‑end API and data persistence are in server/ (e.g. server/index.js, server/db.js). Docker support (Dockerfile, docker‑compose.yml) lets you drop the whole stack into a container with a single command.
Key files:
server/index.js– creates the Express server, loads plugins, and registers routes.server/db.js/server/db/sqlite.js– thin wrappers around a SQLite DB used for settings, favorites, and channel metadata.public/js/components/ChannelList.js– virtual‑scroll list that can render 7 000+ channels efficiently.server/services/transcodeSession.js– builds FFmpeg arguments for GPU‑accelerated transcoding.
How It Is Wired
Execution starts at server/index.js → loadPlugins (line 117) which imports 14 other server modules. The most connected hub is server/index (imports 14 modules, instability 1).
- API request flow –
public/js/api.jsexportsrequest. The front‑end callsrequest(e.g. frompublic/js/app.js→init).requesthits the Express routes defined underserver/routes/*. - Database access –
loadDb(inserver/db.js) is called from 22 places, most notably fromserver/routes/settings.jsandserver/services/syncService.js.loadDb→getDb(inserver/db/sqlite.js) opens the SQLite file; all CRUD ops (add,remove,getAll) funnel through this module, giving it the widest blast radius. - Channel playback – UI component
public/js/components/VideoPlayer.jsinvokesplay(frompublic/js/app.js).playtriggers a chain:play → updateTranscodeStatus → fetchEpgData(5 calls each) and finally an outbound network call viaAPI.request. The same path reaches the filesystem when a transcode session writes segment files (transcodeSession.start → ensureCacheDir → fs.writeFile). - Transcoding –
server/services/transcodeSession.jsconstructs FFmpeg args (buildFFmpegArgs) and writes temporary caches. It also generates a session ID (generateSessionId) – the only cryptographic operation in the repo. - External touches – 23 functions issue HTTP requests, 17 read/write the SQLite DB, 13 touch the file system, and 4 perform cryptographic work.
No circular imports were detected, but several modules have deep nesting (up to 6 levels) and duplicated 6‑line blocks across UI components, increasing cognitive load for future changes.
How To Use It
# Clone the fork (required URL)
git clone https://github.com/moses-y/nodecast-tv
cd nodecast-tv
# Install Node dependencies
npm install
# Development server (Express + hot‑reload)
npm run dev
# Open http://localhost:3000 in a browser
Docker deployment (uses the provided Dockerfile and docker-compose.yml):
docker compose up -d # builds from the repo, exposes port 3000
Configuration files are not present in the repo; the application expects environment variables such as PORT (shown in the README) and provider credentials supplied at runtime via the UI or a custom data/ volume mounted into the container.
Real‑World Use
A cable operator can host nodecast-tv behind its internal network, point the UI at an existing Xtream‑Codes endpoint, and let employees browse live channels, VOD, and EPG without installing a separate client. The built‑in GPU transcode (server/services/transcodeSession.js) can off‑load H.264/HEVC decoding to the server, allowing low‑power thin clients to receive a compatible stream.
Code Health & Issues
- HIGH – Pin GitHub Actions –
.github/workflows/docker-publish.ymluses tag references (docker/setup-qemu-action@v3, etc.). Replace with 40‑character SHAs. - HIGH – No test suite – 41 source files, zero test files. Add unit/integration tests for each public entry point.
- MEDIUM – Enable Dependabot – No
dependabot.yml; add to auto‑update npm and GitHub‑Action dependencies. - MEDIUM – Pin base image –
Dockerfileuses mutable tagubuntu:24.04. Pin by digest. - MEDIUM – Add vulnerability scan – CI lacks a dependency‑review or OSV scanner step.
- MEDIUM – Run container as non‑root – Dockerfile lacks a
USERdirective. Create an unprivileged user. - LOW – Set workflow timeout –
docker-publish.ymlhas notimeout-minutes; add a reasonable limit.
Additional observations: the repository contains no automated tests, no code‑coverage reporting, and the README does not document required provider credentials, which must be supplied manually.
The Bottom Line
nodecast-tv delivers a functional, Docker‑ready IPTV front‑end with solid performance for large playlists, but the codebase suffers from high cognitive complexity, duplicated UI logic, and a lack of automated testing or security hardening. It is suitable for teams comfortable refactoring JavaScript and adding their own test harness; otherwise, the maintenance burden may outweigh the benefits.