A feature-rich IPTV player for Windows, built with Electron, React, and TypeScript.
Supports multiple Xtream Codes API and M3U/M3U8 playlist providers, with EPG, VOD, TV series, favorites, live stream recording (including scheduled recordings), VOD downloads, and subtitle support.
- Multiple providers — add and switch between several providers at once (Xtream Codes API or M3U/M3U8 playlists), each with its own credentials and sources
- Xtream Codes API — connect with server / username / password, browse live TV, movies (VOD), and series
- M3U / M3U8 playlists — load from a URL or file, browse channels by group
- EPG (TV Guide) — program guide for channels, with
tvg-idmapping for M3U channels - Live TV — category and channel browsing, direct playback
- VOD & Series — movie details, season/episode selection, playback
- Favorites — bookmark channels, movies, and series with persistence
- Downloads — download VOD content with progress, pause/resume/cancel
- Recording — record live streams to MP4 using ffmpeg (video stream-copy, audio transcoded to AAC), with automatic reconnection, low-disk guard, and a recording index that reconciles with the files on disk
- Scheduled recordings — schedule one-off or recurring recordings (daily, weekdays, weekly, monthly) with pre-roll/post-roll padding
- System tray — minimize to tray, with a menu showing active recordings
- Subtitles — subtitle display and selection during playback
- Multiple players — mpv (via
electron-libmpv), hls.js for HLS streams, native<video>for MP4, and an ffmpeg transcode proxy fallback - Custom frameless UI — custom title bar, sidebar navigation, dark theme
| Live TV | Video player |
|---|---|
![]() |
![]() |
- Node.js (v18+)
- npm
- Windows (primary target), with build tools for native modules:
- Visual Studio Build Tools
with the "Desktop development with C++" workload (required for the
electron-libmpvnative addon)
The mpv player is powered by the libmpv
C library, which is loaded as a prebuilt binary — it is not compiled from
source and is not included in this repository. Download the prebuilt
libmpv-2.dll from the
mpv releases page and
place it in the repo root (next to package.json) so it can be found at
runtime during development.
You will need the mpv development files to build the electron-libmpv
native addon. These come from the prebuilt Windows mpv package
(mpv-player-windows
— the same package referenced by the electron-libmpv docs), which ships the
headers and the import library alongside the runtime libmpv-2.dll. Download
and extract the dev archive, then place the files in a C:\mpv-dev folder with
this layout:
C:\mpv-dev\
├── include\
│ ├── mpv/client.h
│ ├── mpv/render.h
│ ├── mpv/render_gl.h
│ └── mpv/stream_cb.h
└── x86_64\
└── libmpv-2.dll.a
The addon's binding.gyp links against -llibmpv-2.dll.a from
C:/mpv-dev/x86_64 with headers from C:/mpv-dev/include on Windows.
npm installThe postinstall step runs electron-builder install-app-deps, which rebuilds
the native electron-libmpv addon against the installed Electron version.
The electron-libmpv native addon (a C++/N-API wrapper around libmpv) is
built from source during npm install via node-gyp. To rebuild it manually
against a different Electron or libmpv version:
# In the project root
npm rebuild electron-libmpv --runtime=electron --target=<electron-version> --dist-url=https://electronjs.org/headers
# or, after an Electron upgrade
npx electron-builder install-app-depsRequirements for building the addon:
- Visual Studio Build Tools with the "Desktop development with C++" workload
- The libmpv development files in
C:\mpv-dev(see above) libmpv-2.dllnext to the built addon at runtime — in the repo root for development, or in the final Electron app directory for production so Windows can resolve it.
# Start the app with hot-reload (electron-vite dev)
npm run dev
# Start the built app in preview mode
npm run start# Typecheck (main + renderer) and build
npm run build
# Build an unpacked app directory
npm run build:unpack
# Build a Windows installer
npm run build:winNote: the app is Windows-focused.
build:macandbuild:linuxscripts exist, but the embedded mpv player relies on native Windows bindings.
npm run typecheck # tsc --noEmit for both main and renderer configs
npm run lint # eslint with autofix
npm run format # prettier --writesrc/
├── main/ # Electron main process
│ ├── index.ts # Window creation, app lifecycle
│ ├── ipc.ts # IPC handlers (Xtream, downloads, recordings, mpv, window)
│ └── services/
│ ├── providers.ts # Multi-provider registry (Xtream + M3U), active provider
│ ├── xtream.ts # Xtream Codes API client (player_api.php)
│ ├── m3u-parser.ts # M3U/M3U8 playlist parsing
│ ├── m3u.ts # M3U provider instance (caching, refresh)
│ ├── proxy.ts # Local ffmpeg transcode proxy (HLS/MP4 fallback)
│ ├── mpv.ts # Embedded mpv player via electron-libmpv
│ ├── downloader.ts # VOD downloads with progress events
│ ├── recorder.ts # Live stream recording via fluent-ffmpeg
│ ├── recording-types.ts # Recording/schedule types
│ ├── recordingStore.ts # Recording + schedule persistence and reconciliation
│ ├── scheduler.ts # Scheduled recording engine (recurring rules)
│ ├── tray.ts # System tray, notifications, show/hide window
│ ├── favorites.ts # Favorites persistence
│ └── storage.ts # Settings storage (electron-store)
├── preload/ # contextBridge API exposed to the renderer as window.api
└── renderer/ # React UI
├── App.tsx # Routes: live, epg, vod, series, favorites, downloads,
│ # recordings, schedules, settings
├── components/ # Feature pages and shared components
├── store/ # Zustand stores (connection, player, downloads, ...)
└── types/ # Shared TypeScript types
The renderer and main process communicate exclusively through the typed API
exposed by the preload script (src/preload/index.ts), so pages never touch
Electron/Node APIs directly.
This project is licensed under the MIT License.

