LibreSpark/LibreTV
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.
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
/livepage 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_BASEcan 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.ymlin the repo contains a fully commented version (including thebuild: .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 viahttp://server-ip:portwill 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 onlocalhostis 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.jsonas the single source of truth; after deployment, you can verify via theversionfield 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
| Variable | Required | Description |
|---|---|---|
PASSWORD | Yes | Access password; if not set, the site will prompt the administrator to configure it |
PROXY_SECRET | No | Session/proxy signing secret; derived from PASSWORD if not set (explicitly set recommended for multi-instance deployments) |
DEFAULT_SOURCES | No | Pre-configured scraping sites (JSON array), automatically shown and pre-checked on the client side. See the Configuration documentation |
REQUEST_TIMEOUT | No | Proxy upstream request timeout (milliseconds), default 8000 |
MAX_RETRIES | No | Proxy request retry count, default 1 |
SEARCH_MAX_PAGES | No | Maximum 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_MS | No | Total 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_AGENT | No | User-Agent used for proxy requests (e.g., for Douban cover hotlink protection), defaults to a Chrome UA |
FALLBACK_CORS_PROXY | No | CORS proxy address to fall back to when direct requests for Douban recommendation data are rejected |
COOKIE_SECURE | No | Explicitly 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_BASE | No | Trending 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_SOURCES | No | Pre-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_SUBSCRIPTIONS | No | Pre-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_SOURCE | No | Default 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_PRIVATE | No | Set 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
- 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). - Search: Check VOD sources and enter a title; searches are aggregated server-side, and individual source failures don’t affect overall results.
- 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. - Progress & History: Automatically saved to this device’s IndexedDB; only positioning information is stored, and the latest episode is automatically synced during playback.
- Configuration Migration: Settings → Data → Configuration Import/Export (supports migration of history from legacy LibreTV-Settings JSON).
Live / IPTV
- 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_SOURCESenvironment variable. - 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.
- Program Guide: Channels with
tvg-idand a configured EPG URL display current/next programs and playback progress. - 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=1to 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:
| Field | Location | Type | Required | Description |
|---|---|---|---|---|
name | Top level | string | No | List name, displayed on the subscription entry after subscribing; defaults to the subscription URL’s hostname if omitted |
version | Top level | number | No | Format version, currently 2 (adds liveSources); the import side currently ignores this field |
sources | Top level | array | No | VOD sources array (Apple CMS scraping sites), up to 100; excess is truncated |
sources[].name | Item | string | No | Source display name; defaults to the URL hostname if omitted |
sources[].url | Item | string | Yes | Apple CMS scraping API URL (public http/https); a trailing / is automatically stripped |
sources[].detail | Item | string | No | Detail 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[].isAdult | Item | boolean | No | Adult 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 |
liveSources | Top level | array | No | Live sources array (M3U playlists), up to 50; excess is truncated |
liveSources[].name | Item | string | No | Source display name; defaults to the URL hostname if omitted |
liveSources[].url | Item | string | Yes | M3U playlist URL (http/https) |
liveSources[].epg | Item | string | No | XMLTV 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
sourcescontinue to work (pure VOD); those with onlyliveSourcesare 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 setsLIVE_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
siteswithtype: 1(i.e., Apple CMS scraping sites). Some shared configurations omittypeor set it to0, but they are also imported when the URL matchesapi.php/provide/vod. Sites markedsearchable: 0(not searchable) are skipped. - Live sources: Imports M3U playlists from
liveswithtype: 0(or omitted), along with theepgfield. TXT channel lists and single-repo JSON are not supported. - Spider-type sites are skipped:
type: 3Spiders (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
urlsarray) 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
| Project | Description |
|---|---|
| OrionTV | Apple TV / Android TV client (React Native TVOS + Expo), works with MoonTV |
| LunaTV | Video aggregation site (Next.js) with support for multiple storage backends including Redis / Upstash |
| Selene-TV | Android TV (Leanback) client, Kotlin + Compose, integrates with MoonTV / Helios |
| EchoTV | Flutter cross-platform client (archived) |
| WarHutTV | Self-hosted video aggregation site built with Go + React |
| DecoTV | Aggregated playback site (formerly KatelyaTV) |
| Joyflix | macOS native video aggregation client (Objective-C) |
| MoonCakeTV | Video aggregation search site (Next.js) with file storage and one-click script deployment |
| OrangeTV | Cross-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...
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...
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 /…
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…
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
An open-source M3U playlist of free TV channels from around the world, organized by country, available on GitHub.