About LibreSpark/LibreTV
LibreSpark/LibreTV is an open-source project on GitHub, mainly written in TypeScript. 一分钟搭建影视站,支持Docker等部署方式 It currently holds 22,794 stars and 30,401 forks with 0 open issues, and was last pushed on an unknown date (repository created unknown).
Project Overview
Git Homed tracks it on the Today's Trending board.
GitHub Repository Details
README
LibreTV
LibreTV Next.js 迁移版:免费在线视频聚合搜索与观看平台。基于 Next.js 15(App Router)+ TypeScript + Tailwind CSS,播放内核为 ArtPlayer + hls.js,支持亮暗双主题。
🏠 官网:LibreTV 官网
> 🌐 演示站:tv.bagiinlink.eu.org(访问密码:libretv)
> 📖 完整文档:文档首页 · 架构 · 部署 · 配置 · 数据源 · 直播 / IPTV · 首页推荐 · 播放器 · 代理与安全 · FAQ>
核心特性
- 聚合搜索:多采集站服务端并行搜索
- 跨源同名聚合:同名影片合并为一张卡片,展开即可比较和选择各来源
- HLS 播放:ArtPlayer + hls.js,广告分片过滤、跳过片段(片头/中段/片尾标记与自动跳过)、自动连播、倍速、快捷键、移动端长按 3 倍速
- 直播 / IPTV:M3U 订阅解析,
/live页面按分组浏览、搜索频道并站内播放(HLS + HTTP-FLV),支持 XMLTV 节目单(EPG)与频道收藏;直播流经专用长连接代理(/api/live/stream)转发 - 进度同步:播放进度与观看历史存于本机 IndexedDB,精确到秒的续播
- 换源测速:跨源搜索同名资源并测速排序,一键切换保留集数位置
- 源测试与订阅:一键探活点播源与直播源(支持批量测活);搜索时自动记录各源健康度,连续失败的源按阶梯时长自动停用(30 分钟 → 24 小时 → 长期),可一键恢复;订阅远程源列表(一份 LibreTV-SourceList JSON 可同时下发点播源与直播源,也可直接填 TVBOX 配置地址,自动导入其中可直接使用的接口),可导出分享
- 首页推荐:豆瓣(电影/剧集分类浏览)、Bangumi 新番放送表或影视榜单(豆瓣周榜 + 百度热播,经 60s API),设置中切换;均服务端直连 + 缓存,Bangumi/榜单免 key 免配置(
60S_API_BASE可指向自部署 60s 实例) - PWA:可安装到桌面 / 主屏幕,亮暗双主题无首屏闪烁
部署
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"] # 预置订阅,自动导入点播源+直播源
# - DEFAULT_RECOMMEND_SOURCE=douban # 首页推荐数据源默认值(douban/bangumi/hot-list),仅对未主动选择过的用户生效
# - LIVE_ALLOW_PRIVATE=1 # 自建内网 IPTV 源时开启
其余可选变量见下方环境变量表;仓库内的docker-compose.yml含完整注释版本(含build: .源码构建分支)。
docker compose pull && docker compose up -d
💡 对外提供服务建议套上 HTTPS:登录密码在 POST body 中以明文传输,公网 HTTP 会被中间人看到,推荐用反向代理(Nginx / Caddy / Traefik)或 Cloudflare 终结 TLS。
登录本身不依赖 HTTPS:会话 cookie 的Secure标记按请求协议(x-forwarded-proto)自动推导,http://服务器IP:端口也能正常登录,不会再出现"密码正确却无法登录"。需要强制指定时用COOKIE_SECURE。
镜像发布在 GHCR 与 Docker Hub:ghcr.io/librespark/libretv 与 docker.io/bestzwei/libretv
(latest / 主.次 / 完整版本号三个 tag,linux/amd64 与 linux/arm64 双架构,
两个 registry 的镜像 digest 一致)。需要固定版本时在 .env 中设置
LIBRETV_IMAGE=ghcr.io/librespark/libretv:<版本>。
版本号以package.json为单一来源,部署后可用/api/status返回的version字段核对。详见部署文档。
免 Docker 运行(预构建包)
每个版本都会在 Releases 附一个 libretv-<版本>-standalone.tar.gz 与对应的 SHA256SUMS,解压后直接用 Node 启动:
# 版本号替换为 Releases 中的实际版本(也可用 /api/status 返回的 version 核对)
VER="<版本>"
mkdir -p libretv # 包内没有顶层目录,目标目录必须先存在
tar -xzf "libretv-${VER}-standalone.tar.gz" -C libretv
cd libretv
PASSWORD=your-password PORT=8080 node server.js
不传PORT时监听 3000(standalone 的server.js默认值),与 Docker 镜像内的 8080 不同,按需显式指定即可。
包内是 Next.js standalone 产物(server.js + public + 静态资源 + 运行时依赖),与 CPU 架构无关,x86_64 / arm64 / armv7 都能跑,适合用不了 Docker 的设备(如 ARMv7 路由器)。环境变量与 Docker 部署一致(PASSWORD、PORT 等),需要 Node 18+;包内不含 sharp(本项目不开图片优化,封面走代理原图)。
手动运行
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(源站总页数,该值);页间并行请求,单页失败只丢该页 |
| SEARCH_SOURCE_TIMEOUT_MS | 否 | 单个搜索源的总死线(毫秒,3s-60s,默认 10000):该源所有分页请求须在时限内完成,到点中断并将其标记为「超时」;健康度自动停用也以此为超时判定依据 |
| USER_AGENT | 否 | 代理请求使用的 UA(豆瓣封面防盗链等场景),默认 Chrome UA |
| FALLBACK_CORS_PROXY | 否 | 豆瓣推荐数据直连被拒时降级使用的 CORS 代理地址 |
| COOKIE_SECURE | 否 | 显式覆盖会话 cookie 的 Secure 标记(true / false);默认按 x-forwarded-proto 自动推导。反向代理终结了 TLS 但没传这个头时,cookie 不会带 Secure(不影响登录,但少了这层保护),设 true 可强制 |
| 60S_API_BASE | 否 | 影视榜单推荐源(60s API)实例地址,默认 https://60s.crystelf.top;有限流,高频使用可自部署 |
| DEFAULT_LIVE_SOURCES | 否 | 预置直播源(M3U 订阅),JSON 数组:[{"name":"源名","url":"https://.../list.m3u","epg":"https://.../epg.xml.gz"}],epg 为可选的 XMLTV 节目单地址 |
| DEFAULT_SUBSCRIPTIONS | 否 | 预置数据源订阅(LibreTV-SourceList JSON 链接,也接受 TVBOX 配置与接口目录地址),JSON 数组:["https://.../sources.json", {"url":"https://.../list.json","name":"名称","refreshDays":10}]。首次访问自动导入点播源与直播源,之后按 refreshDays(1-365,缺省 1 天)静默刷新;用户删除后不再自动加回。refreshDays 只是初始值,用户在源管理面板改过之后以面板设置为准 |
| DEFAULT_RECOMMEND_SOURCE | 否 | 首页推荐数据源的默认值(douban / bangumi / hot-list,出厂默认 hot-list);仅对未在设置中主动选择过的用户生效,用户的选择始终优先 |
| LIVE_ALLOW_PRIVATE | 否 | 设为 1 时允许直播流代理访问内网/保留地址(自建 IPTV 场景),默认关闭以维持 SSRF 防护 |
使用说明
1. 添加点播源:设置 → 源管理 → 点播源 → 添加 API,填入 Apple CMS 采集站地址(如 https://example.com/api.php/provide/vod),可选填详情页地址(部分源需要爬详情页提取播放地址)。
2. 搜索:勾选点播源后输入片名;搜索通过服务端聚合,个别源失败不影响整体结果。
3. 播放:详情弹窗选择剧集进入 /watch;支持快捷键(空格/←→/↑↓/F/Alt+←→)、移动端长按 3 倍速、自动连播、换源测速。观看/暂停时后续分片自动缓存到本地(设置可关),播放页可「下载本集」(TS/MP4)离线观看。播放页「跳过标记」可标记片头/中段/片尾区间(快捷键 Shift+I 片头结束、Shift+O 片尾开始、Shift+S·Shift+E 中段区间),之后同剧各集与同名资源自动跳过——片头/中段跳到片段末尾,片尾则直接结束本集(是否连播下一集由自动连播决定),三类片段共用「自动跳过片段」一个开关;跳过时提示条带「撤销」,「跳过标记」侧栏可逐剧关闭、微调边界、试跳起点/终点(记录与试跳都会先暂停),命中区间在进度条上着色。侧栏是非模态的:不遮画面、不挡播放器点击,可以一边看一边标。
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 等外部播放器使用。
完整说明见 直播 / IPTV 文档。
⚠️ 项目不内置任何频道源,也不存储、不制作任何直播内容,仅提供第三方公开播放列表的解析与播放能力,内容的合法性由对应数据源负责。内网自建源默认被 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",
"detail": "https://example.com",
"isAdult": false
}
],
"liveSources": [
{
"name": "示例直播源",
"url": "https://example.com/list.m3u",
"epg": "https://example.com/epg.xml.gz"
}
]
}
字段说明:
| 字段 | 位置 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- | --- |
| name | 顶层 | string | 否 | 列表名称,订阅后显示在订阅条目上;缺省时显示订阅地址主机名 |
| version | 顶层 | number | 否 | 格式版本,当前为 2(新增 liveSources);导入端目前忽略该字段 |
| sources | 顶层 | array | 否 | 点播源数组(Apple CMS 采集站),最多 100 个,超出部分截断 |
| sources[].name | 项 | string | 否 | 源显示名;缺省时使用 URL 主机名 |
| sources[].url | 项 | string | 是 | Apple CMS 采集接口地址(公网 http/https),结尾 / 自动去除 |
| sources[].detail | 项 | string | 否 | 详情页根地址,用于列表接口拿不到播放地址、需要爬详情页提取 m3u8 的源 |
| sources[].isAdult | 项 | boolean | 否 | 成人内容标记,默认 false。标记为 true 的源名称旁显示 (18+) 徽章;设置中的「成人内容过滤」开启(默认开启)时该源不可勾选、不参与搜索,需先关闭过滤才能启用 |
| liveSources | 顶层 | array | 否 | 直播源数组(M3U 播放列表),最多 50 个,超出部分截断 |
| liveSources[].name | 项 | string | 否 | 源显示名;缺省时使用 URL 主机名 |
| liveSources[].url | 项 | string | 是 | M3U 播放列表地址(http/https) |
| liveSources[].epg | 项 | string | 否 | XMLTV 节目单地址(xml / xml.gz),用于 /live 页展示节目单;地址非法时只丢弃该字段、保留整条源 |
兼容与限制:
- 只写
sources的老订阅照常可用(纯点播),只写liveSources则是纯直播订阅;两者都缺时提示「订阅内容格式不正确」;裸数组[{ "name": "...", "url": "..." }]视为点播源; - 按
url去重(先到先得);非 http(s) 地址会被过滤;点播源另需为公网地址(内网/回环/保留地址会被静默过滤),直播源在部署者设置LIVE_ALLOW_PRIVATE=1时可使用内网自建源地址; - 订阅由服务端拉取(拉取前经过 SSRF 校验),因此订阅地址无需配置 CORS,Gist、对象存储、任意静态托管均可。
兼容 TVBOX 配置
订阅地址也可以直接填 TVBOX 配置(形如 {"sites": [...], "lives": [...], "parses": [...]}):服务端按内容结构自动识别格式,无需手动选择。
- 点播源:导入
sites中type: 1的 JSON 接口(即 Apple CMS 采集站);部分共享配置省略type或写成0,但地址命中api.php/provide/vod时同样导入;站点自身标记searchable: 0(不可搜索)时跳过; - 直播源:导入
lives中type: 0(或省略)的 M3U 播放列表,epg字段一并带上;txt 频道列表与单仓 JSON 不支持; - Spider 类站点会跳过:
type: 3的 Spider(csp_*/.jar/.js/.py)需要 TVBOX 自身的 Spider 引擎才能运行,Node 侧无法执行;XML 接口、外链 JSON 同理。被跳过的条目不影响其余导入,导入结果会如实提示,如「已同步 8 个点播源、2 个直播源(TVBOX 配置);跳过 96 个不可用条目(Spider 引擎 92、XML 接口 4)」; - TVBOX 配置常含上百条站点且以 Spider 为主,只导入个位数到十几个属正常现象;
- 格式容错:配置里的
//注释、尾随逗号、字符串内未转义的换行会自动修正后再解析(共享配置中很常见,TVBOX 客户端用的 fastjson 同样容忍这些写法); - 其他限制:订阅地址需直接返回 JSON(Base64 / 压缩包装的分享链接不支持);TVBOX「多仓」配置(顶层为
urls数组)不支持,请填单仓配置;地址公网校验、去重与数量上限与上方格式完全一致。
兼容接口目录(source-catalog)
订阅地址也可以填一份接口目录——裸数组,元素为 { "name": "...", "baseUrl": "..." }:
[
{ "name": "示例接口", "baseUrl": "https://example.com/api.php/provide/vod" },
{ "name": "已停用的接口", "baseUrl": "https://old.example.com/api.php/provide/vod", "enabled": false }
]
- 只导入
baseUrl(点播接口),不含直播源;enabled缺省视为启用,写false的条目跳过并在结果里计数; - 顶层数组全部条目都带
baseUrl才按接口目录解析;混用baseUrl与url两种条目会直接报格式错误,避免其中一批被静默丢弃; - 地址归一化、去重与数量上限与 LibreTV 源列表一致(
baseUrl去尾部斜杠与空的?/#)。
订阅行为
- 订阅:设置 → 源管理 → 数据源订阅 → 填入订阅地址 → 「订阅」,导入的点播源自动勾选、直播源自动启用,均带「订阅」标识,条目上显示「点播 N · 直播 M」;
- 同步:订阅条目上的 ⟳ 手动强制同步,整体替换该订阅名下的点播源与直播源;
- 自动刷新:每个订阅可单独设置刷新周期(条目上的周期下拉:关闭 / 1 / 3 / 7 / 14 / 30 天,默认关闭即纯手动)。设为 N 天后,打开站点时检查是否到期,到期才在后台静默同步;单次最多刷新 5 个、并发 2 个,页面不可见或离线时跳过,不阻塞首屏。连续失败 3 次自动暂停该订阅(条目显示「已暂停」),手动同步成功或改周期后恢复计数。环境变量
DEFAULT_SUBSCRIPTIONS里的refreshDays只作为初始值,用户在面板里改过之后以面板为准; - 管理边界:订阅源以远端列表为准,单独编辑会在下次同步时被覆盖,单独移除会在重新同步时恢复;如需调整请改远端列表,或直接删除整个订阅。删除订阅时点播源全部移除;直播源为多归属共享——同一 M3U 可被多个订阅引用(名称/EPG 以首次导入为准),删除订阅或远端列表中移除该源后再同步,都只摘除本订阅的引用,仅当不再被任何订阅引用时才移除该源,手动添加的源不受同步影响,收藏的频道始终保留;
- 导出分享:设置 → 源管理 → 数据源订阅 → 「导出数据源」,把当前全部点播源与直播源(预置 + 手动 + 订阅,按 URL 去重)导出为上述 JSON;也可用「发布为链接」,把当前已勾选启用的源一键上传到公开粘贴板(paste.rs,失败自动降级 0x0.st),直接返回可填入订阅框的 URL,无需自备托管。注意:发布的内容公开可读,且每次发布生成新链接、不支持覆盖更新,需长期稳定请用导出 + 自行托管。
订阅由服务端拉取(经过 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:<版本>(详见部署文档)。
安全说明
- 密码只保存在服务端环境变量中,前端不持有任何可重放凭证。
- 登录接口有 IP 速率限制(10 次 / 10 分钟)。
- 代理内置 SSRF 防护:拒绝内网/保留地址(含 DNS 解析后校验),仅放行 http(s)。
- 未登录会话仅允许代理图片类目标(豆瓣封面防盗链需要)。
衍生作品
| 项目 | 说明 | | --- | --- | | 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 多存储与多端同步 | | MQTV | 重构与优化 LibreTV | | NextTV | 影视聚合站(Next.js + Zustand),支持弹幕 | | DpadTV | Android TV 原生客户端(Kotlin + Media3/ExoPlayer),对接自建服务端,不依赖 WebView | | LibreTV-for-HarmonyOS | HarmonyOS NEXT 原生客户端(ArkTS + ArkUI + AVPlayer) |
旧版 LibreTV(静态 HTML + Express)完整代码见 backup-2025 分支。
免责声明
本项目不存储、不制作任何视频内容,仅提供第三方公开接口的聚合与播放能力,内容的合法性由对应数据源负责。
☕ 觉得有用的话,可以到 AFDIAN 请我喝杯咖啡。