Skip to content

ZeBadger/tv-player

Repository files navigation

TV Player

A self-hosted web-based TV player for HDHomeRun tuners receiving UK Freeview DVB-T/T2.

Streams live TV in the browser with no plugins required. SD channels are transcoded to H.264 for browser compatibility; HD channels are passed through directly.

Created by ZeBadger.

Features

  • Live TV and radio playback in the browser
  • Channel list with HD/SD/Radio filtering, favourites, search, and sorting
  • EPG now/next programme snippets in the channel list
  • Channel visibility management (hide channels you don't want)
  • Last-channel restore on reload (browser autoplay policy permitting)
  • Unified Settings modal for channel, EPG, and user actions
  • Admin-only access management with user/token controls and usage log
  • Optional admin-only "More info" toggle for playback internals (transcode/passthrough details)
  • DVB subtitle burn-in for supported channels
  • Selectable SD transcode profiles (Quality, Balanced, Low bandwidth)

Requirements

  • HDHomeRun network tuner (tested on FLEX QUATRO)
  • Docker and Docker Compose

Quick start

git clone https://github.com/ZeBadger/tv-player.git
cd tv-player

Edit compose.yaml and set HDHOMERUN_HOST to your HDHomeRun's IP address:

- HDHOMERUN_HOST=192.168.0.X

Then build and start:

docker compose up --build -d

Open http://localhost:8080 in your browser.

Configuration

All settings are in compose.yaml:

Variable Default Description
HDHOMERUN_HOST (required) IP address of your HDHomeRun device
MAX_CONCURRENT_STREAMS 1 Maximum simultaneous playback sessions served by this app. Set to your tuner capacity (for example 4 on FLEX QUATRO)
TUNER_RELEASE_DELAY_MS 300 Delay after forced session takeover before starting the next stream, giving tuner resources time to settle
TUNER_SWITCH_COOLDOWN_MS 350 Minimum gap between stream requests from the same client IP to reduce rapid-switch tuner thrash
AUTH_INITIAL_ADMIN_USERNAME admin Username for the first admin account (only used when no auth data exists yet)
AUTH_INITIAL_ADMIN_TOKEN auto-generated if unset Optional one-time bootstrap token for first admin sign-in
AUTH_REMEMBER_TTL_SECONDS 2592000 Remember-this-device session lifetime in seconds (default 30 days)
TRANSCODE_PRESET medium ffmpeg x264 preset (ultrafastveryslow). Faster = lower CPU, lower quality
TRANSCODE_SCALE 960:-2 Output resolution for SD transcode. -2 preserves aspect ratio
TRANSCODE_FPS 25 Output frame rate
TRANSCODE_VIDEO_BITRATE 1800k Target video bitrate
TRANSCODE_VIDEO_MAXRATE 2200k Maximum video bitrate
TRANSCODE_VIDEO_BUFSIZE 4400k Video rate control buffer size
TRANSCODE_AUDIO_BITRATE 96k AAC audio bitrate
TRANSCODE_QUALITY_PRESET slow Quality profile x264 preset
TRANSCODE_QUALITY_SCALE 1280:-2 Quality profile output resolution
TRANSCODE_QUALITY_FPS 25 Quality profile frame rate
TRANSCODE_QUALITY_VIDEO_BITRATE 2600k Quality profile target video bitrate
TRANSCODE_QUALITY_VIDEO_MAXRATE 3200k Quality profile max video bitrate
TRANSCODE_QUALITY_VIDEO_BUFSIZE 6400k Quality profile video buffer size
TRANSCODE_QUALITY_AUDIO_BITRATE 128k Quality profile AAC bitrate
TRANSCODE_LOW_PRESET veryfast Low-bandwidth profile x264 preset
TRANSCODE_LOW_SCALE 640:-2 Low-bandwidth profile output resolution
TRANSCODE_LOW_FPS 25 Low-bandwidth profile frame rate
TRANSCODE_LOW_VIDEO_BITRATE 900k Low-bandwidth profile target video bitrate
TRANSCODE_LOW_VIDEO_MAXRATE 1200k Low-bandwidth profile max video bitrate
TRANSCODE_LOW_VIDEO_BUFSIZE 2400k Low-bandwidth profile video buffer size
TRANSCODE_LOW_AUDIO_BITRATE 64k Low-bandwidth profile AAC bitrate

The Balanced profile uses the existing TRANSCODE_* settings. In the app, choose profile from Settings -> Channel Settings -> SD transcode profile.

Token Access (No Password Prompts)

TV Player supports token sign-in with persistent device sessions:

  1. On first startup, the server creates an admin user and prints an initial admin token in logs (or uses AUTH_INITIAL_ADMIN_TOKEN if set).
  2. Open TV Player with /?token=YOUR_TOKEN or paste the token into the sign-in prompt.
  3. The token is exchanged, then removed from the URL and saved as a secure session cookie.

Tokens are reusable and stay valid until an admin revokes them. You can still create expiring tokens explicitly if you want to.

Auth data is stored in data/auth.json (and persisted in Compose via ./data:/app/data).

Admin Recovery

If you get locked out of admin:

  1. Delete data/auth.json.
  2. Restart the container.
  3. The app will bootstrap a fresh admin user and print a new initial admin token in container logs.

To find the automatically created admin token, run:

docker logs tv-player-tv-player-1

Admin API (for user/token management)

After signing in as admin, you can use the in-app Admin panel or call these same-origin endpoints directly:

  • GET /auth/admin/users
  • GET /auth/admin/tokens?userId=...
  • POST /auth/admin/users with {"username":"alice","role":"user"}
  • POST /auth/admin/users/disable with {"userId":"..."}
  • POST /auth/admin/users/restore with {"userId":"..."}
  • POST /auth/admin/users/delete with {"userId":"..."} (requires user to be disabled first)
  • POST /auth/admin/tokens with {"userId":"...","label":"Alice phone"} or include expiresInHours for an optional expiry
  • POST /auth/admin/tokens/revoke with {"tokenId":"..."}

POST /auth/admin/tokens returns both the token and a ready-to-share inviteUrl.

Stream Diagnostics

  • GET /diagnostics/streams (authenticated) — Returns live server stream diagnostics including session counters, cooldown activity, and recent FFmpeg errors. The same data is available from Settings -> User Settings -> Diagnostics for admins.

EPG (Electronic Program Guide)

TV Player can display a free EPG (now/next programme information). By default, this project includes an iptv-org/epg Docker sidecar that generates guide.xml locally from epg/channels.xml.

Quick Start: Built-in EPG Server (Recommended)

compose.yaml includes a separate iptv-epg service:

  • Input channels file: epg/channels.xml
  • Generated guide URL inside compose network: http://iptv-epg:3000/guide.xml
  • Refresh schedule: every 12 hours (and at startup)

Start both services:

docker compose up --build -d

Configure your country/provider:

  1. Open TV Player and click EPG settings
  2. Use the iptv-org Channel Lists filter and selectors to choose a site/provider XML list
  3. Click Use Selected List
  4. If a rebuild is not started automatically, click Rebuild Guide Now
  5. Wait for the Guide build status to show that the guide file is up to date
  6. TV Player will load the rebuilt guide automatically, or you can click Reload Current Guide

Debugging:

If you want to expose the guide outside Docker for debugging, add a port mapping to iptv-epg (for example 3000:3000) and then open http://localhost:3000/guide.xml.

External EPG Server (Optional)

To use a manual XMLTV feed URL instead of the built-in sidecar:

  1. Open TV Player and click EPG settings
  2. Select Use an external EPG server
  3. Paste an XMLTV feed URL into the source field
  4. Click Save
  5. Click Reload Guide to import the data

Or set EPG_SOURCE_URL in compose.yaml:

services:
  tv-player:
    environment:
      - EPG_SOURCE_URL=https://example.com/guide.xml

Manual Channel List Setup

The repository ships with a starter epg/channels.xml file. This is only a default example and may not match your country/provider.

To manually replace the channel list:

  1. Open the iptv-org channels folder: https://github.com/iptv-org/epg/tree/master/sites
  2. Find your provider/country file named *.channels.xml
  3. Download the raw XML file
  4. Replace local epg/channels.xml with that file
  5. Open EPG settings and click Rebuild Guide Now

Then open TV Player and click EPG settings -> Reload Current Guide if it has not auto-loaded yet.

Setup Notes

  • Sidecar first build can take several minutes.
  • Guide content refreshes automatically, but channel definitions come from epg/channels.xml.
  • If channels are added/removed by your provider, repeat the replacement steps above.
  • Docker control from the settings modal uses the mounted Docker socket in the default compose setup.
  • EPG data is cached locally so it persists across restarts.
  • If fetch fails, the last cached data is used.

Recommended EPG Sources

  • iptv-org EPG (built-in, multi-country support, recommended)

    • UK Freeview channels map: https://raw.githubusercontent.com/iptv-org/epg/master/sites/freeview.co.uk/freeview.co.uk.channels.xml
    • See iptv-org for other countries
    • Note: current iptv-org workflow is to generate guide.xml locally (or in Docker) from a channels list
  • XMLTV UK Freeview (external, manual setup)

    • Visit xmltv.org
    • Requires local grabber configuration

Options

Variable Default Description
EPG_SOURCE_URL http://iptv-epg:3000/guide.xml URL to an XMLTV feed (leave blank to disable EPG)
EPG_CACHE_DIR /tmp/epg Where to cache the downloaded guide data
EPG_REFRESH_INTERVAL_HOURS 12 How often to refresh the guide (set to 0 to disable auto-refresh)

Endpoints

  • GET /epg/status — Returns EPG health (enabled, last fetch time, channel count)
  • GET /epg/now-next — Returns current and next programme for each mapped channel (JSON)
  • POST /epg/configure — Update EPG source URL at runtime (request body: {"sourceUrl": "..."})
  • POST /epg/refresh — Trigger manual EPG refresh

Notes

  • EPG data is cached locally so it persists across restarts.
  • If fetch fails, the last cached data is used.
  • Channel mapping from HDHomeRun to XMLTV ids is done automatically based on channel names and numbers.

About

TV Player for HD Homerun

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors