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.jsloadPlugins (line 117) which imports 14 other server modules. The most connected hub is server/index (imports 14 modules, instability 1).

  • API request flowpublic/js/api.js exports request. The front‑end calls request (e.g. from public/js/app.jsinit). request hits the Express routes defined under server/routes/*.
  • Database accessloadDb (in server/db.js) is called from 22 places, most notably from server/routes/settings.js and server/services/syncService.js. loadDbgetDb (in server/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.js invokes play (from public/js/app.js). play triggers a chain: play → updateTranscodeStatus → fetchEpgData (5 calls each) and finally an outbound network call via API.request. The same path reaches the filesystem when a transcode session writes segment files (transcodeSession.start → ensureCacheDir → fs.writeFile).
  • Transcodingserver/services/transcodeSession.js constructs 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.yml uses 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 imageDockerfile uses mutable tag ubuntu: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 USER directive. Create an unprivileged user.
  • LOW – Set workflow timeoutdocker-publish.yml has no timeout-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.