LibreTV README

The project's README from github.com/LibreSpark/LibreTV. As one markdown file: README.md.

LibreTV

LibreTV Next.js 迁移版:免费在线视频聚合搜索与观看平台。基于 Next.js 15(App Router)+ TypeScript + Tailwind CSS,播放内核为 ArtPlayer + hls.js,支持亮暗双主题。

📖 完整文档:GitHub Wiki · 架构 · 部署 · 配置 · 数据源 · 首页推荐 · 播放器 · 代理与安全 · FAQ

核心特性

部署

Docker(推荐)

# 在 .env 中设置 PASSWORD
echo "PASSWORD=your-password" > .env

# 方式一:拉取发布镜像(零构建)
docker compose pull && docker compose up -d

# 方式二:源码构建
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   # 必填:访问密码,务必修改
      # - PROXY_SECRET=your-secret          # 会话/代理签名密钥,多实例部署建议设置
      # - DEFAULT_SOURCES=[{"name":"示例源","url":"https://example.com/api.php/provide/vod"}]
      # - DEFAULT_LIVE_SOURCES=[{"name":"示例直播源","url":"https://example.com/list.m3u"}]
      # - DEFAULT_SUBSCRIPTIONS=["https://example.com/sources.json"]  # 预置订阅,自动导入点播源+直播源
      # - LIVE_ALLOW_PRIVATE=1              # 自建内网 IPTV 源时开启

其余可选变量见下方环境变量表;仓库内的 docker-compose.yml 含完整注释版本(含 build: . 源码构建分支)。

docker compose pull && docker compose up -d

⚠️ 生产部署必须通过 HTTPS 访问(localhost 除外):生产模式下会话 cookie 带 Secure 标记,浏览器只在 HTTPS(或 localhost)下保存它。因此用 http://服务器IP:端口 访问时,会出现"密码正确却无法登录"的现象——登录请求实际成功,但 cookie 被浏览器丢弃。请通过反向代理(Nginx / Caddy / Traefik)或 Cloudflare 等为站点套上 TLS 后再对外提供服务;本地开发用 localhost 不受影响。

镜像发布在 GHCR:ghcr.io/librespark/libretv(latest / 主.次 / 完整版本号三个 tag, linux/amd64 与 linux/arm64 双架构)。需要固定版本时在 .env 中设置 LIBRETV_IMAGE=ghcr.io/librespark/libretv:2.0.1。

版本号以 package.json 为单一来源,部署后可用 /api/status 返回的 version 字段核对。详见部署文档。

手动运行

npm install
PASSWORD=your-password npm run build
PASSWORD=your-password npm start   # 监听 8080

环境变量

变量 必填 说明
PASSWORD 是 访问密码;未设置时站点会提示管理员配置
PROXY_SECRET 否 会话/代理签名密钥;不设置时从 PASSWORD 派生(多实例部署建议显式设置)
DEFAULT_SOURCES 否 预置采集站(JSON 数组),用户端自动出现且默认勾选,详见配置文档
REQUEST_TIMEOUT 否 代理上游请求超时(毫秒),默认 8000
MAX_RETRIES 否 代理请求重试次数,默认 1
SEARCH_MAX_PAGES 否 每个搜索源最多抓取的页数(1-50,默认 5)。第一页会读取源站 pagecount,实际页数 = min(源站总页数,该值);页间并行请求,单页失败只丢该页
60S_API_BASE 否 影视榜单推荐源(60s API)实例地址,默认官方公共实例 https://60s.viki.moe;有限流,高频使用可自部署
DEFAULT_LIVE_SOURCES 否 预置直播源(M3U 订阅),JSON 数组:[{"name":"源名","url":"https://.../list.m3u","epg":"https://.../epg.xml.gz"}],epg 为可选的 XMLTV 节目单地址
DEFAULT_SUBSCRIPTIONS 否 预置数据源订阅(LibreTV-SourceList JSON 链接),JSON 数组:["https://.../sources.json", {"url":"https://.../list.json","name":"名称"}]。首次访问自动导入点播源与直播源,之后每 24h 静默刷新;用户删除后不再自动加回
LIVE_ALLOW_PRIVATE 否 设为 1 时允许直播流代理访问内网/保留地址(自建 IPTV 场景),默认关闭以维持 SSRF 防护
DEBUG 否 调试日志

使用说明

  1. 添加点播源:设置 → 点播源 → 添加 API,填入 Apple CMS 采集站地址(如 https://example.com/api.php/provide/vod),可选填详情页地址(部分源需要爬详情页提取播放地址)。
  2. 搜索:勾选点播源后输入片名;搜索通过服务端聚合,个别源失败不影响整体结果。
  3. 播放:详情弹窗选择剧集进入 /watch;支持快捷键(空格/←→/↑↓/F/Alt+←→)、移动端长按 3 倍速、自动连播、换源测速。
  4. 进度与历史:自动保存在本设备 IndexedDB,仅定位信息入库,播放时自动同步最新剧集。
  5. 配置迁移:设置 → 导出/导入配置(兼容旧版 LibreTV-Settings JSON 的历史记录迁移)。

直播 / IPTV

  1. 添加直播源:设置 → 直播源 → 填入 M3U/M3U8 地址(可选填 XMLTV 节目单地址),添加后自动探活并显示频道数量;也可在「订阅与配置 → 数据源订阅」中与点播源一起订阅导入;部署者还可用 DEFAULT_LIVE_SOURCES 环境变量预置。
  2. 观看:进入「直播」页,按分组标签筛选或搜索频道,点击即播;支持 HLS(m3u8)与 HTTP-FLV 两种直播流,直连失败自动走代理通道重试。
  3. 节目单:频道带 tvg-id 且订阅配置了 EPG 地址时,展示当前/接下来节目与播放进度。
  4. 收藏与导出:频道可收藏;订阅可一键导出为标准 M3U 文件,供 PotPlayer / VLC 等外部播放器使用。

⚠️ 项目不内置任何频道源,也不存储、不制作任何直播内容,仅提供第三方公开播放列表的解析与播放能力,内容的合法性由对应数据源负责。内网自建源默认被 SSRF 防护拦截,自部署者可显式设置 LIVE_ALLOW_PRIVATE=1 放行。

数据源订阅 / 分享

数据源(点播源 + 直播源)可以 导出为一份 JSON → 托管到公开 URL → 他人在「设置 → 订阅与配置 → 数据源订阅」里填入该 URL 订阅。

托管地址没有特殊要求,可用 npoint.io 免费托管 JSON(粘贴内容即可得到一个公开 URL),Gist、对象存储、任意静态托管同样可用。

订阅格式(LibreTV-SourceList JSON)

{
  "name": "我的源列表",
  "version": 2,
  "sources": [
    { "name": "示例点播源", "url": "https://example.com/api.php/provide/vod" }
  ],
  "liveSources": [
    { "name": "示例直播源", "url": "https://example.com/list.m3u", "epg": "https://example.com/epg.xml.gz" }
  ]
}

订阅行为

订阅由服务端拉取(经过 SSRF 校验),因此订阅地址无需配置 CORS。完整说明见 数据源文档。

开发

npm install
PASSWORD=dev-password npm run dev   # http://localhost:8080
npm test                            # 核心库单元测试(cms-parser / m3u8 / ssrf)
npm run typecheck

发布新版本

版本号以 package.json 为单一来源,发布镜像由 GitHub Actions 自动完成:

npm version patch       # 或 minor / major;会更新 package.json 并打 git tag
git push && git push --tags

CI 校验通过后自动构建并推送 ghcr.io/librespark/libretv:<版本>(详见部署文档)。

安全说明

衍生作品

项目 说明
OrionTV Apple TV / Android TV 客户端(React Native TVOS + Expo),配合 MoonTV 使用
LunaTV 影视聚合站(Next.js),支持 Redis / Upstash 等多存储后端
Selene-TV Android TV(Leanback)客户端,Kotlin + Compose,对接 MoonTV / Helios
EchoTV Flutter 全平台客户端(已归档)
WarHutTV Go + React 的自托管影视聚合站
DecoTV 聚合播放站(原 KatelyaTV)
Joyflix macOS 原生影视聚合客户端(Objective-C)
MoonCakeTV 影视聚合搜索站(Next.js),文件存储、一键脚本部署
OrangeTV 跨平台影视聚合播放器(Next.js),Kvrocks/Redis/Upstash 多存储与多端同步

旧版 LibreTV(静态 HTML + Express)完整代码见 backup-2025 分支。

免责声明

本项目不存储、不制作任何视频内容,仅提供第三方公开接口的聚合与播放能力,内容的合法性由对应数据源负责。

☕ 觉得有用的话,可以到 AFDIAN 请我喝杯咖啡。

LibreTV (LibreSpark/LibreTV)

Searching Database…

19.2K ·GitHub
这是什么?LibreTV 是一个可自行部署的网页应用,可以搜索并播放从第三方视频源网站聚合而来的视频,还可以通过 M3U 播放列表观看直播电视/IPTV。它基于 Next.js 15(App Router)、TypeScript 和 Tailwind CSS 构建,播放器使用 ArtPlayer + hls.js。
这是托管服务,还是需要我自己运行?需要自行部署。你要部署自己的实例(官方镜像发布在 GHCR,支持 amd64/arm64),并用密码保护它;没有公开共享的实例。
我该如何部署?推荐使用 Docker 或 Docker Compose,搭配 ghcr.io/librespark/libretv 镜像;仓库中也记载了手动运行的方式。
要让它正常工作,我需要先配置什么?只有 PASSWORD 环境变量是必填的,用于设置访问密码;其他内容(代理密钥、默认视频源、超时时间等)都是可选的。视频源(Apple CMS 风格的 API)和直播 M3U 播放列表需要在部署后手动添加,或通过订阅添加。
为什么即使密码正确,登录也会失败?在生产模式下,会话 Cookie 带有 Secure 标记,因此除非网站通过 HTTPS 提供服务(localhost 除外),浏览器会丢弃该 Cookie。要让登录真正生效,你需要在前面加一层反向代理或 TLS 服务(如 Nginx、Caddy、Traefik、Cloudflare)。
LibreTV 自己会存储或托管任何视频内容吗?不会。它只聚合并播放第三方公开视频源,从不存储或制作视频内容,内容的合法性由视频源网站负责。
同一部电影出现在多个视频源时会怎样?LibreTV 会把不同视频源中同名的结果合并成一张卡片。你可以展开这张卡片来比较、测速,并在切换视频源时保留当前的集数位置。
我也能观看直播电视频道,而不只是电影吗?可以。/live 页面可以解析 M3U/M3U8 播放列表,支持按分组浏览或搜索频道,支持通过 HLS 或 HTTP-FLV 播放,还可以显示 XMLTV EPG 节目单,并支持频道收藏。
还有基于 LibreTV 开发的其他应用吗?有的,社区中有几个衍生项目,包括 OrionTV(Apple TV/Android TV 客户端)、LunaTV(基于 Next.js,使用 Redis/Upstash 后端)和 Joyflix(原生 macOS 客户端)。
What are similar projects?iptv, bug, IPTV, iptv-api, IPTV, awesome-iptv, m3u, my-tv-webview
Creator
LibreSpark
Size
3.6 MB
Stars
19.2K
Updated
CommitOct 17
Age
1y
Commits · 90 Days