LibreSpark/LibreTV

GitHub Trending (daily) Tools

Summary

LibreTV is a free online video aggregation search and viewing platform built on Next.js 15 + TypeScript + Tailwind CSS. It supports multi-source parallel search, HLS playback, live/IPTV subscriptions, source switching with speed testing, PWA installation, and one-click deployment via Docker.

Build a video streaming site in one minute, with support for Docker and other deployment options.
Original Article
View Cached Full Text

Cached at: 10/16/26, 06:47 AM

LibreSpark/LibreTV

Source: https://github.com/LibreSpark/LibreTV

LibreTV

LibreTV Next.js migration: a free online video aggregation search and viewing platform. Built on Next.js 15 (App Router) + TypeScript + Tailwind CSS, with ArtPlayer + hls.js as the playback engine, supporting both light and dark themes.

🏠 Website: LibreTV official site (https://libretv.is-an.org/)

🌐 Demo: tv.bagiinlink.eu.org (https://tv.bagiinlink.eu.org) (access password: libretv)

📖 Full Documentation: Documentation Home (https://libretv.is-an.org/wiki/) · Architecture (https://libretv.is-an.org/wiki/Architecture.html) · Deployment (https://libretv.is-an.org/wiki/Deployment.html) · Configuration (https://libretv.is-an.org/wiki/Configuration.html) · Data Sources (https://libretv.is-an.org/wiki/Data-Sources.html) · Live / IPTV (https://libretv.is-an.org/wiki/Live-IPTV.html) · Homepage Recommendations (https://libretv.is-an.org/wiki/Recommendations.html) · Player (https://libretv.is-an.org/wiki/Player.html) · Proxy & Security (https://libretv.is-an.org/wiki/Proxy-Security.html) · FAQ (https://libretv.is-an.org/wiki/FAQ.html)

Core Features

  • Aggregated Search: Server-side parallel search across multiple scraping sites
  • Cross-Source Same-Title Aggregation: Movies/shows with the same title are merged into a single card; expand to compare and choose between sources
  • HLS Playback: ArtPlayer + hls.js with ad-segment filtering, auto-play next episode, playback speed control, keyboard shortcuts, and 3x long-press speed on mobile
  • Live / IPTV: M3U subscription parsing; the /live page supports browsing by group, searching channels, and in-app playback (HLS + HTTP-FLV), with XMLTV EPG (program guide) and channel favorites; live streams are relayed through a dedicated long-connection proxy (/api/live/stream)
  • Progress Sync: Playback progress and watch history are stored in local IndexedDB, with second-accurate resume
  • Source Switching with Speed Testing: Searches for the same title across sources, tests and ranks them by speed, and lets you switch sources with one click while preserving the current episode position
  • Source Testing & Subscriptions: One-click health check for VOD and live sources (batch testing supported); search results automatically track source health, and sources with consecutive failures are automatically disabled in escalating time windows (30 minutes → 24 hours → long-term), restorable with one click; subscribe to remote source lists (a single LibreTV-SourceList JSON can deliver both VOD and live sources; TVBOX configuration URLs are also accepted, auto-importing usable interfaces), with export and sharing support
  • Homepage Recommendations: Douban (movies/series browsing), Bangumi seasonal anime schedule, or trending rankings (Douban weekly + Baidu hot, via 60s API); switchable in settings; all fetched server-side directly with caching; Bangumi/rankings require no API key or configuration (60S_API_BASE can point to a self-hosted 60s instance)
  • PWA: Installable on desktop / home screen, with light and dark themes and no first-paint flash

Deployment

Docker (Recommended)

# Set PASSWORD in .env
echo "PASSWORD=your-password" > .env

# Option 1: Pull the published image (zero build)
docker compose pull && docker compose up -d

# Option 2: Build from source
docker compose up -d --build

Docker Compose

services:
  libretv:
    image: ghcr.io/librespark/libretv:latest
    container_name: libretv
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      - PASSWORD=change-me
      # Required: access password, must be changed
      # - PROXY_SECRET=your-secret
      # Session/proxy signing secret, recommended for multi-instance deployments
      # - DEFAULT_SOURCES=[{"name":"Example Source","url":"https://example.com/api.php/provide/vod"}]
      # - DEFAULT_LIVE_SOURCES=[{"name":"Example Live Source","url":"https://example.com/list.m3u"}]
      # - DEFAULT_SUBSCRIPTIONS=["https://example.com/sources.json"]
      # Pre-configured subscriptions, auto-imports VOD + live sources
      # - DEFAULT_RECOMMEND_SOURCE=douban
      # Default homepage recommendation source (douban/bangumi/hot-list), only applies to users who haven't actively chosen
      # - LIVE_ALLOW_PRIVATE=1
      # Enable when using self-hosted LAN IPTV sources

See the Environment Variables table below for other optional variables; the docker-compose.yml in the repo contains a fully commented version (including the build: . source-build branch).

docker compose pull && docker compose up -d

⚠️ Production deployments must be accessed via HTTPS (except on localhost): in production mode, session cookies are marked Secure, and browsers only save them over HTTPS (or localhost). Accessing via http://server-ip:port will result in “correct password but cannot log in” — the login request actually succeeds, but the cookie is discarded by the browser. Use a reverse proxy (Nginx / Caddy / Traefik) or Cloudflare to put TLS in front of the site before serving it publicly; local development on localhost is unaffected.

Images are published on GHCR and Docker Hub: ghcr.io/librespark/libretv and docker.io/bestzwei/libretv (three tags: latest / major.minor / full version number, dual-architecture linux/amd64 and linux/arm64, with identical image digests on both registries). To pin a version, set LIBRETV_IMAGE=ghcr.io/librespark/libretv:2.0.1 in .env.

Version numbers use package.json as the single source of truth; after deployment, you can verify via the version field returned by /api/status. See the Deployment documentation for details.

Manual Run

npm install
PASSWORD=your-password npm run build
PASSWORD=your-password npm start
# Listens on 8080

Environment Variables

VariableRequiredDescription
PASSWORDYesAccess password; if not set, the site will prompt the administrator to configure it
PROXY_SECRETNoSession/proxy signing secret; derived from PASSWORD if not set (explicitly set recommended for multi-instance deployments)
DEFAULT_SOURCESNoPre-configured scraping sites (JSON array), automatically shown and pre-checked on the client side. See the Configuration documentation
REQUEST_TIMEOUTNoProxy upstream request timeout (milliseconds), default 8000
MAX_RETRIESNoProxy request retry count, default 1
SEARCH_MAX_PAGESNoMaximum pages to fetch per search source (1–50, default 5). The first page reads the source’s pagecount; actual pages = min(source total pages, this value). Pages are fetched in parallel; a single page failure only discards that page
SEARCH_SOURCE_TIMEOUT_MSNoTotal deadline per search source (milliseconds, 3s–60s, default 10000): all paginated requests for that source must complete within this time; on timeout they are interrupted and marked as “timed out”. Health-based auto-disable also uses this as the timeout criterion
USER_AGENTNoUser-Agent used for proxy requests (e.g., for Douban cover hotlink protection), defaults to a Chrome UA
FALLBACK_CORS_PROXYNoCORS proxy address to fall back to when direct requests for Douban recommendation data are rejected
COOKIE_SECURENoExplicitly override the Secure flag on session cookies (true / false); auto-derived from the request protocol by default. Set to true if HTTPS logins fail because the reverse proxy doesn’t correctly forward x-forwarded-proto
60S_API_BASENoTrending rankings recommendation source (60s API) instance URL, defaults to https://60s.crystelf.top. Rate-limited; self-host for heavy use (https://github.com/vikiboss/60s)
DEFAULT_LIVE_SOURCESNoPre-configured live sources (M3U subscriptions), JSON array: [{"name":"Source Name","url":"https://.../list.m3u","epg":"https://.../epg.xml.gz"}]. epg is an optional XMLTV EPG URL
DEFAULT_SUBSCRIPTIONSNoPre-configured data source subscriptions (LibreTV-SourceList JSON links, TVBOX configuration URLs also accepted), JSON array: ["https://.../sources.json", {"url":"https://.../list.json","name":"Name"}]. VOD and live sources are auto-imported on first visit, then silently refreshed every 24h; sources deleted by users are not re-added
DEFAULT_RECOMMEND_SOURCENoDefault homepage recommendation source (douban / bangumi / hot-list, factory default hot-list); only applies to users who haven’t actively selected one in settings — the user’s choice always takes priority
LIVE_ALLOW_PRIVATENoSet to 1 to allow the live stream proxy to access LAN/reserved addresses (for self-hosted IPTV scenarios); disabled by default to maintain SSRF protection

Usage

  1. Add VOD sources: Settings → Source Management → VOD Sources → Add API, enter an Apple CMS scraping site address (e.g., https://example.com/api.php/provide/vod); optionally fill in the detail page address (some sources require crawling detail pages to extract playback URLs).
  2. Search: Check VOD sources and enter a title; searches are aggregated server-side, and individual source failures don’t affect overall results.
  3. Playback: Select an episode from the detail modal to enter /watch; supports keyboard shortcuts (Space / ←→ / ↑↓ / F / Alt+←→), 3x long-press speed on mobile, auto-play next episode, and source switching with speed testing. While watching/pausing, subsequent segments are automatically cached locally (can be disabled in settings). The watch page offers a “Download Episode” option (TS/MP4) for offline viewing.
  4. Progress & History: Automatically saved to this device’s IndexedDB; only positioning information is stored, and the latest episode is automatically synced during playback.
  5. Configuration Migration: Settings → Data → Configuration Import/Export (supports migration of history from legacy LibreTV-Settings JSON).

Live / IPTV

  1. Add live sources: Settings → Source Management → Live Sources → enter an M3U/M3U8 URL (optionally with an XMLTV EPG URL); after adding, the source is automatically health-checked and the channel count is displayed. Sources can also be imported together with VOD sources via “Source Management → Data Source Subscriptions”. Deployers can also pre-configure via the DEFAULT_LIVE_SOURCES environment variable.
  2. Watch: Go to the “Live” page, filter by group tag or search channels, and click to play. Supports both HLS (m3u8) and HTTP-FLV live stream formats; if a direct connection fails, it automatically retries through the proxy channel.
  3. Program Guide: Channels with tvg-id and a configured EPG URL display current/next programs and playback progress.
  4. Favorites & Export: Channels can be favorited; subscriptions can be exported as standard M3U files with one click for use in external players like PotPlayer / VLC.

Full details in the Live / IPTV documentation.

⚠️ This project does not bundle any channel sources, nor does it store or produce any live content. It only provides parsing and playback capabilities for third-party public playlists; the legality of content is the responsibility of the respective data sources. LAN self-hosted sources are blocked by SSRF protection by default; self-deployers can explicitly set LIVE_ALLOW_PRIVATE=1 to allow them.

Data Source Subscriptions / Sharing

Data sources (VOD sources + live sources) can be exported as a single JSON → hosted at a public URL → others subscribe by entering that URL under “Settings → Source Management → Data Source Subscriptions”.

There are no special requirements for the hosting location; you can use npoint.io to host JSON for free (paste content to get a public URL). Gist, object storage, or any static hosting also works.

Subscription Format (LibreTV-SourceList JSON)

{
  "name": "My Source List",
  "version": 2,
  "sources": [
    {
      "name": "Example VOD Source",
      "url": "https://example.com/api.php/provide/vod",
      "detail": "https://example.com",
      "isAdult": false
    }
  ],
  "liveSources": [
    {
      "name": "Example Live Source",
      "url": "https://example.com/list.m3u",
      "epg": "https://example.com/epg.xml.gz"
    }
  ]
}

Field Descriptions:

FieldLocationTypeRequiredDescription
nameTop levelstringNoList name, displayed on the subscription entry after subscribing; defaults to the subscription URL’s hostname if omitted
versionTop levelnumberNoFormat version, currently 2 (adds liveSources); the import side currently ignores this field
sourcesTop levelarrayNoVOD sources array (Apple CMS scraping sites), up to 100; excess is truncated
sources[].nameItemstringNoSource display name; defaults to the URL hostname if omitted
sources[].urlItemstringYesApple CMS scraping API URL (public http/https); a trailing / is automatically stripped
sources[].detailItemstringNoDetail page root URL, used for sources where the list API doesn’t provide playback URLs and detail pages must be crawled to extract m3u8
sources[].isAdultItembooleanNoAdult content flag, defaults to false. Sources marked true show an (18+) badge next to the name; when “Adult Content Filter” in settings is enabled (default on), such sources cannot be checked or included in searches — the filter must be disabled first to enable them
liveSourcesTop levelarrayNoLive sources array (M3U playlists), up to 50; excess is truncated
liveSources[].nameItemstringNoSource display name; defaults to the URL hostname if omitted
liveSources[].urlItemstringYesM3U playlist URL (http/https)
liveSources[].epgItemstringNoXMLTV EPG URL (xml / xml.gz), used by the /live page for program guide display; if the URL is invalid, only this field is discarded and the entire source is retained

Compatibility & Limitations:

  • Legacy subscriptions with only sources continue to work (pure VOD); those with only liveSources are pure live subscriptions. If both are missing, the message “subscription content format is incorrect” is shown. A bare array [{ "name": "...", "url": "..." }] is treated as VOD sources.
  • Deduplication by url (first come, first served); non-http(s) URLs are filtered out. VOD sources additionally require public network addresses (LAN/loopback/reserved addresses are silently filtered); live sources can use LAN self-hosted addresses when the deployer sets LIVE_ALLOW_PRIVATE=1.
  • Subscriptions are fetched by the server (with SSRF validation before fetching), so no CORS configuration is needed for the subscription URL — Gist, object storage, or any static hosting works.

TVBOX Configuration Compatibility

The subscription URL can also directly accept a TVBOX configuration (in the form of {"sites": [...], "lives": [...], "parses": [...]}): the server automatically detects the format based on content structure, no manual selection needed.

  • VOD sources: Imports JSON interfaces from sites with type: 1 (i.e., Apple CMS scraping sites). Some shared configurations omit type or set it to 0, but they are also imported when the URL matches api.php/provide/vod. Sites marked searchable: 0 (not searchable) are skipped.
  • Live sources: Imports M3U playlists from lives with type: 0 (or omitted), along with the epg field. TXT channel lists and single-repo JSON are not supported.
  • Spider-type sites are skipped: type: 3 Spiders (csp_* / .jar / .js / .py) require TVBOX’s own Spider engine to run and cannot be executed on the Node side. XML interfaces and external JSON links are likewise skipped. Skipped entries don’t affect the rest of the import; the import result is reported accurately, e.g., “Synced 8 VOD sources, 2 live sources (TVBOX config); skipped 96 unavailable entries (Spider engine 92, XML interfaces 4)”.
  • TVBOX configurations often contain hundreds of sites, predominantly Spiders — importing only single digits to low teens of sources is normal.
  • Format tolerance: // comments, trailing commas, and unescaped newlines in strings in the configuration are automatically fixed before parsing (common in shared configurations; the fastjson library used by TVBOX clients also tolerates these).
  • Other limitations: The subscription URL must return JSON directly (Base64/compressed wrapper share links are not supported); TVBOX “multi-repo” configurations (top-level urls array) are not supported — use single-repo configurations. Public URL validation, deduplication, and quantity limits are identical to the format above.

Subscription Behavior

  • Subscribe: Settings → Source Management → Data Source Subscriptions → enter the subscription URL → “Subscribe”. Imported VOD sources are automatically checked and live sources automatically enabled, both marked with a “Subscription” badge; entries display “VOD N · Live M”.
  • Sync: The ⟳ on a subscription entry manually forces a sync, completely replacing the VOD and live sources under that subscription.
  • Management boundary: Subscription sources follow the remote list; individual edits will be overwritten on the next sync, and individual removals will be restored on re-sync. To make changes, edit the remote list or delete the entire subscription. When deleting a subscription, all VOD sources are removed. Live sources are multi-ownership shared — the same M3U can be referenced by multiple subscriptions (name/EPG based on first import); deleting a subscription or removing a source from the remote list and then syncing only removes the reference from that specific subscription; the source is only removed when no subscription references it anymore. Manually added sources are unaffected by sync, and favorited channels are always preserved.
  • Export & Share: Settings → Source Management → Data Source Subscriptions → “Export Data Sources” exports all current VOD and live sources (pre-configured + manually added + subscribed, deduplicated by URL) as the JSON above. There’s also a “Publish as Link” option that uploads all currently checked/enabled sources to a public pasteboard in one click (paste.rs, with automatic fallback to 0x0.st on failure), returning a URL directly fillable into the subscription box — no self-hosting required. Note: published content is publicly readable, and each publish generates a new link; overwriting updates are not supported. For long-term stable hosting, use export + self-hosting.

Subscriptions are fetched by the server (with SSRF validation), so no CORS configuration is needed for the subscription URL. Full details in the Data Sources documentation.

Development

npm install
PASSWORD=dev-password npm run dev
# http://localhost:8080
npm test
# Unit tests for core libraries (cms-parser / m3u8 / ssrf)
npm run typecheck

See the Development documentation for test coverage, release process, and documentation structure.

Releasing a New Version

Version numbers use package.json as the single source of truth; release images are built automatically by GitHub Actions:

npm version patch
# or minor / major; this updates package.json and creates a git tag
git push && git push --tags

Once CI validation passes, the image is automatically built and pushed to ghcr.io/librespark/libretv:<version> (see the Deployment documentation).

Security Notes

  • The password is only stored in server-side environment variables; the frontend holds no replayable credentials.
  • The login endpoint has IP-based rate limiting (10 requests / 10 minutes).
  • The proxy has built-in SSRF protection: rejects LAN/reserved addresses (including post-DNS-resolution validation) and only allows http(s).
  • Unauthenticated sessions may only proxy image-type targets (required for Douban cover hotlink protection).

Derivative Projects

ProjectDescription
OrionTVApple TV / Android TV client (React Native TVOS + Expo), works with MoonTV
LunaTVVideo aggregation site (Next.js) with support for multiple storage backends including Redis / Upstash
Selene-TVAndroid TV (Leanback) client, Kotlin + Compose, integrates with MoonTV / Helios
EchoTVFlutter cross-platform client (archived)
WarHutTVSelf-hosted video aggregation site built with Go + React
DecoTVAggregated playback site (formerly KatelyaTV)
JoyflixmacOS native video aggregation client (Objective-C)
MoonCakeTVVideo aggregation search site (Next.js) with file storage and one-click script deployment
OrangeTVCross-platform video aggregation player (Next.js) with Kvrocks/Redis/Upstash multi-storage and multi-device sync

The legacy LibreTV (static HTML + Express) full source code is available on the backup-2025 branch.

Disclaimer

This project does not store or produce any video content. It only provides aggregation and playback capabilities for third-party public interfaces; the legality of content is the responsibility of the respective data sources.

☕ If you find this useful, you can buy me a coffee on AFDIAN.

Similar Articles

@XAMTO_AI: Still foolishly paying iQiyi, Youku, Tencent Video? Still tolerating those annoying splash ads? Still staring at that blurry 720P quality? Bro, count how many years you've been ripped off. Today, Brother Bird spills the beans—6 open-source free 4K movie/TV sites, zero ads, zero membership, deploy once, never pay again...

X AI KOLs Timeline

Introduces 6 open-source free 4K movie/TV sites that can be deployed with zero ads and zero membership, replacing paid platforms like iQiyi, Youku, etc., using tech stacks like Vue, Golang, Next.js.

@XAMTO_AI: The TV box at home can now smoothly watch free TV channels from around the world. A project has compiled free and legal public TV channel sources from around the world into an M3U playlist. You just need to import it into a player that supports the format to watch. This project is completely free and open source, meaning you no longer need to install a bunch of messy apps, and...

X AI KOLs Timeline

An open-source project compiles free and legal public TV channel sources from around the world into an M3U playlist. Users can import it into a player that supports the format to watch, without needing to install multiple apps or search for live stream sources.

@Daviswh: TV box users still switching back and forth between TVBox and 影视仓: take a look at this if you want all-in-one management for big-screen viewing. @0xGky: Open-source BoxPlayer combines cloud drive management + video playback, supporting Windows / Linux / iOS / macOS / tvOS /…

X AI KOLs Timeline

Introducing the open-source BoxPlayer: a cross-platform media player for Windows/Linux/macOS/iOS/tvOS/Android that integrates multiple cloud drives, Jellyfin/Emby/Plex media servers, movie and TV metadata scraping, music, e-book reading, and an AI workspace, while providing clouddrive-cli and an MCP Server for AI agents to use.

@fhwofjow51260: Recommends an open-source project, DashPlayer, a video player designed for English learning. Unlike ordinary players, it combines watching videos and learning English. American dramas, YouTube, course videos can all become English learning materials. If you usually like using American dramas, movies, or YouTube to learn English, this player…

X AI KOLs Timeline

Recommends open-source project DashPlayer, a video player designed for English learning, supporting bilingual subtitles, subtitle-based jumping, word lookup, Bluetooth remote control, etc., turning American dramas, YouTube, and other videos into English learning materials.

Free-TV/IPTV

GitHub Trending (daily)

An open-source M3U playlist of free TV channels from around the world, organized by country, available on GitHub.