iPTV 是什么
iPTV 是 akiralereal 维护的自托管直播源管理程序,用来把分散的直播来源收成一套频道表。它内置央视频、咪咕、各地广电,以及 B 站、抖音、虎牙、斗鱼等直播平台的抓取模块,也可以接入直链和 M3U、TXT 订阅,再在浏览器里编排,并输出播放列表和节目单。
和一份手工保存的播放列表相比,它按模块刷新地址、去掉重复项,并把分组、隐藏和排序留在你自己的机器上。各个平台的官方客户端仍用它们自己的账号;iPTV 把你启用的来源交给电视、盒子和手机上的播放器。
iPTV 能做什么
- 汇总来源:把内置抓取模块、直链和外部订阅收进同一份频道表。
- 在浏览器里编排:分组、排序、重命名、隐藏,并为不同设备准备不同的配置档。
- 输出播放列表和节目单:生成播放器可以订阅的列表,以及对应的 EPG。
- 按播放器换订阅:标准列表给能直接取流的播放器,兼容列表给不跟随跳转的播放器,全代理由服务器转发视频。
- 限制谁能打开:需要时为管理页和订阅地址加上访问密码。
为什么要使用 iPTV
直播地址散在各个平台和别人分享的列表里,链接会过期,电视、盒子和手机还常常各存一份。想改分组或藏掉某个台,就得逐份去改。
iPTV 把刷新和编排放在你的服务器上,播放器只保留一个订阅地址。它适合在 NAS 或家庭服务器上自己管理直播源。
公开能打开的地址,不等于可以拿去转售或公开转播。只启用你有权使用的来源。
使用 Docker 部署 iPTV
iPTV 可以用 Docker 启动,本机不必先安装 Node.js。开始之前,先准备好 Docker,并留出存放配置和频道数据的目录。
下面用 Docker Compose 写好端口和数据目录,启动服务,并在浏览器里打开管理后台,确认频道可以播放。
环境要求
镜像基于 Node.js 22 的 Alpine,并自带 Chromium,供需要网页解析的来源使用。时区在镜像里设为 Asia/Shanghai。
| 项目 | 建议 |
|---|---|
| 系统 | Linux(本文命令按 Ubuntu 目录书写);macOS 把 /www/wwwroot/iptv 换成 ~/docker/iptv |
| Docker | 已安装 Docker Engine 与 Compose V2(docker compose) |
| 内存 | 项目说明网页抓取会启动 Chromium,每路大约 200~400 MB;内存不超过 2 GB 时,多个浏览器容易把机器拖进交换分区 |
| 磁盘 | Docker Hub 上 amd64 记录约为 426 MB,数据目录另计 |
| 端口 | 宿主机 1905 → 容器 1905 |
| 工作目录 | /www/wwwroot/iptv |
docker --version
docker compose version
Linux 未装 Docker 可使用轩辕镜像一键安装脚本:
bash <(wget -qO- https://get.xuanyuan.cloud/docker.sh)
备用地址:
bash <(wget -qO- https://get.xuanyuan.me/docker.sh)
更多见 轩辕镜像使用手册。
标签怎么选
新安装使用 4.51.2。这是 2026-10-26 的发布,Release 标题是「高校与场馆修复、江门综合暂时下架」。镜像标签不带开头的 v,对应的 GitHub 标签是 v4.51.2。
同一次推送里,latest、4、4.51 和 4.51.2 指向同一份镜像。前三个会在下一次发布后改指向,不写入本文命令。
| 标签 | 说明 | 是否写入本文命令 |
|---|---|---|
4.51.2 | 2026-10-26 的版本号标签 | 是 |
4.51 | 4.51 这一条上的浮动标签 | 否 |
4 | 4 这一条上的浮动标签 | 否 |
latest | 当前最新版的浮动标签 | 否 |
完整标签见 标签列表。这一版的说明见 GitHub Release v4.51.2。
拉取镜像
用 轩辕镜像 加速拉取:
docker pull docker.xuanyuan.run/akiralereal/iptv:4.51.2
Ubuntu 24.04 上这次拉取的输出:
4.51.2: Pulling from akiralereal/iptv
930f28a6540c: Pull complete
8cea16b75f2d: Pull complete
25f051386053: Pull complete
7b229517ed22: Pull complete
8776aa3d2ba7: Pull complete
7246d4c6a55d: Pull complete
0ea42358b657: Pull complete
ccacf5c215cf: Pull complete
3b1011d3596c: Pull complete
304511616d6a: Pull complete
2916263b9eca: Pull complete
44136fa355b3: Download complete
b82334cf5b8b: Download complete
Digest: sha256:f4de60bb7930b47104440199d99a8206abafd68347c4fc334e8bea89c6765925
Status: Downloaded newer image for docker.xuanyuan.run/akiralereal/iptv:4.51.2
docker.xuanyuan.run/akiralereal/iptv:4.51.2
Docker Compose 部署
宿主机 1905 对应容器 1905。数据放在 /www/wwwroot/iptv/data,挂到容器内 /iptv/data。mdataDir 要和卷的右边一致,两处一起改。未设置访问密码时,管理后台路径是 /admin。
- 先看 1905 是否已有进程监听。有输出时,下一步把
compose.yaml里冒号左边改成空闲端口,后面的访问地址也改成这个端口。没有输出再继续:
sudo ss -lntp | grep -E ':1905\b' || true
- 创建工作目录和数据目录:
sudo mkdir -p /www/wwwroot/iptv/data
sudo chown "$USER":"$USER" /www/wwwroot/iptv
cd /www/wwwroot/iptv
macOS 使用 ~/docker/iptv 和 ~/docker/iptv/data。
- 写入
compose.yaml:
cat > compose.yaml <<'EOF'
services:
iptv:
image: docker.xuanyuan.run/akiralereal/iptv:4.51.2
container_name: iptv
init: true
restart: always
ports:
- "1905:1905"
environment:
- mport=1905
- mdataDir=/iptv/data
volumes:
- ./data:/iptv/data
EOF
| 配置 | 说明 |
|---|---|
1905:1905 | 冒号左边是宿主机端口,右边是容器内端口。只改左边时,mport 仍保持 1905,并与冒号右边一致 |
mport | 容器内监听端口,要和 ports 右边相同 |
mdataDir | 容器内数据目录,要和卷的右边相同 |
./data | 宿主机 /www/wwwroot/iptv/data,配置、频道编排和订阅源都在这里 |
init: true | 与上游示例一致。镜像入口已是 tini,这次日志前三行因此出现警告 |
always | 容器异常退出或机器重启后会再启动 |
- 启动,并查看状态:
docker compose up -d
docker compose ps
Ubuntu 24.04 上这次启动的输出:
[+] up 2/2
✔ Network iptv_default Created 0.2s
✔ Container iptv Started 2.6s
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
iptv docker.xuanyuan.run/akiralereal/iptv:4.51.2 "/sbin/tini -- node …" iptv 5 seconds ago Up 2 seconds 0.0.0.0:1905->1905/tcp, [::]:1905->1905/tcp
1905 同时映射了 IPv4 和 IPv6。容器命令是 /sbin/tini -- node …。网络名是 iptv_default。
- 看启动日志。输出很长,下面只留和这次启动有关的几行:
docker compose logs iptv
iptv | [WARN tini (7)] Tini is not running as PID 1 and isn't registered as a child subreaper.
iptv | Zombie processes will not be re-parented to Tini, so zombie reaping won't work.
iptv | To fix the problem, use the -s option or set the environment variable TINI_SUBREAPER to register Tini as a child subreaper, or run Tini as PID 1.
iptv | [2026-10-28 14:52:43:361] 加载内置源配置(本地内置): 1/1 个启用 (1 个需要抓取)
iptv | [2026-10-28 14:52:43:473] 开始更新电视频道...(启动模式)iptv | [2026-10-28 14:52:43:476] 更新订阅源: 精选频道 (https://raw.githubusercontent.com/akiralereal/iptv/refs/heads/main/IPTV.m3u)
iptv | [2026-10-28 14:52:52:295] 管理后台访问
iptv | [2026-10-28 14:52:58:484] 订阅获取失败 (raw.githubusercontent.com): 请求超时
iptv | [2026-10-28 14:52:59:714] 订阅获取失败 (ghfast.top): HTTP 403 FORBIDDEN
iptv | [2026-10-28 14:53:00:793] 通过镜像获取成功: gh-proxy.com
iptv | [2026-10-28 14:53:00:795] 精选频道 订阅更新成功,共 32 个频道
iptv | [2026-10-28 14:53:00:809] 抓取模块 央视频:73 个频道
iptv | [2026-10-28 14:53:01:594] 抓取模块 咪咕视频:84 个频道
iptv | [2026-10-28 14:53:15:014] interface.txt 不存在
iptv | [2026-10-28 14:53:15:021] API: 返回 0 个分组(原始: 0 个)iptv | [2026-10-28 14:53:21:318] 内置源 纬来体育 尚未抓取,跳过
iptv | [2026-10-28 14:53:21:344] API: 返回 56 个分组
iptv | [2026-10-28 14:53:21:363] 频道数据获取完成: 咪咕 84 个,内置源 0 个,外部源 32 个,抓取模块 630 个
iptv | [2026-10-28 14:53:21:363] 电视频道 - 获取成功
iptv | [2026-10-28 14:53:42:147] 订阅拉取: GET /interface.m3u(无 relay 参数)|192.168.1.21 UA:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
iptv | Error: ENOENT: no such file or directory, open '/iptv/data/interface.txt'
iptv | [2026-10-28 14:53:42:263] 分组: 体育 更新完成!iptv | [2026-10-28 14:53:57:712] 订阅拉取: GET /playback.xml(无 relay 参数)|192.168.1.21 UA:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
iptv | Error: ENOENT: no such file or directory, open '/iptv/data/playback.xml'
iptv | [2026-10-28 14:54:03:294] 管理后台访问
前三行是 tini 的警告。镜像入口已经是 /sbin/tini,init: true 又让 Docker 的 init 占住 PID 1,所以镜像里的 tini 提示自己不会回收僵尸进程。容器状态仍是 Up。要去掉这三行,删掉 compose.yaml 里的 init: true,再执行 docker compose up -d。上面的日志是带着 init: true 启动的。
精选频道先访问 raw.githubusercontent.com,这次超时;接着 ghfast.top 返回 403;随后从 gh-proxy.com 拉到 32 个频道。
14:53:15 频道列表还是 0 个分组,14:53:21 变为 56 个分组,并打出「电视频道 - 获取成功」。汇总是咪咕 84 个、外部源 32 个、抓取模块 630 个。内置源是 0,同一秒的日志写着纬来体育尚未抓取。这个 630 是各抓取模块报出的数量,和后面页面上的 1036 个频道不是同一个计数。
14:53:42 请求 /interface.m3u、14:53:57 请求 /playback.xml 时,interface.txt 和 playback.xml 都还不在。上面只留了「分组: 体育 更新完成」这一行,后面还有多组。节目单那次请求已经晚于这些「更新完成」,文件仍未生成。管理后台里点「播放」打开的是页面上的播放窗。播放器订阅若失败,隔一会儿再打开同一地址。
日志里若反复出现「开始提取」「Navigation timeout」「浏览器会话已启动」,先看「常见问题」里的内存说明。
- 在服务器本机请求管理页:
curl -sS -o /dev/null -w "%{http_code}\n" --max-time 20 http://127.0.0.1:1905/admin
连着请求了两次,都是:
200
/admin 返回 200,表示管理页已经在听。频道列表要等分组写完,再在浏览器里打开。
打开管理后台和订阅地址
把 服务器 IP 换成这台机器的地址。同一台机器上也可以先用 127.0.0.1。
| 用途 | 地址 |
|---|---|
| 管理后台 | http:// 服务器 IP:1905/admin |
| M3U 播放列表 | http:// 服务器 IP:1905/interface.m3u |
| TXT 播放列表 | http:// 服务器 IP:1905/txt |
| EPG 节目单 | http:// 服务器 IP:1905/playback.xml |
管理后台没有预置账号。顶部四个入口是「我的频道」「源管理」「设置」「关于我们」。第一次启动从 14:52:43 开始更新频道,各组「更新完成」出现在大约一分钟后。订阅地址在那之后仍可能暂时打不开,原因见「Docker Compose 部署」里的日志。改完来源之后,项目说明播放列表会在一两秒内重新生成。
刷新后的「我的频道」标题是共 1036 个频道,当前档是「默认」。左侧选中「体育」,这一组写着 24 个频道;同列还有「体育 - 昨天」「体育 - 明天」。标题下方是订阅地址和节目单 EPG,旁边是「复制」。

在「体育」这一组里点「播放」,页面中央打开播放窗,右上角有「新窗口打开」和「关闭」。下面第一张窗标题是「CCTV5 体育」,画面是体操比赛;第二张窗标题是「CCTV5+ 体育赛事」,画面是篮球比赛。


给不同电视各用一套编排时,在「我的频道」里新建配置档。每档底部有自己的地址,形如 http:// 服务器 IP:1905/interface.m3u?profile= 档名。各档共用同一份底层频道,默认档的地址不变。
账号、画质和模块开关放在后台里改,不必写进 compose.yaml。需要更高画质或会员频道时,在「源管理」里使用你本人的账号。凭据只留在这台机器的数据目录中,不要贴到订阅地址里,也不要使用别人的登录态。
备份可以在「设置」里导出,也可以直接复制 /www/wwwroot/iptv/data。自定义台标若放在数据目录的 logos/,导出配置时要单独拷贝这一目录。
播放器怎么选订阅
能用标准 M3U 就用标准地址。播放器不跟随跳转时再换兼容版。兼容版仍然打不开,才用全代理版。全代理会把视频流量转到这台服务器上。
| 播放器 | 订阅 |
|---|---|
| DIYP、百川影音 | http:// 服务器 IP:1905/txt |
| TiviMate、APTV、Kodi、OK 影视 | http:// 服务器 IP:1905/interface.m3u |
| 飞牛影视 | 同上,地址必须保留 .m3u |
| 极空间极影视、部分老电视盒 | http:// 服务器 IP:1905/interface.m3u?relay=1 |
| 兼容版仍然无法播放 | http:// 服务器 IP:1905/interface.m3u?relay=2 |
| 版本 | 播放清单 | 视频分片 | 服务器带宽 |
|---|---|---|---|
标准版 /interface.m3u | 服务器跳转到上游地址,由播放器自己去取 | 播放器直连上游 | 几乎不占 |
兼容版 ?relay=1 | 服务器取好清单再交给播放器 | 播放器直连上游 | 很少 |
全代理版 ?relay=2 | 服务器转发 | 服务器转发 | 视频流量都经过这台机器 |
有的内置模块会按上游要求,对单个频道改走全代理,和你选的订阅版本无关。其余能直连的频道不受影响。
备选:docker run
没有 Compose 时再用这条。工作目录、端口和数据卷与「Docker Compose 部署」相同。--init 与 init: true 相同。
若已经用 Compose 启动过同名容器,先停掉再运行,避免名称 iptv 冲突:
cd /www/wwwroot/iptv
docker compose down
docker run -d \
--name iptv \
--init \
--restart always \
-p 1905:1905 \
-e mport=1905 \
-e mdataDir=/iptv/data \
-v /www/wwwroot/iptv/data:/iptv/data \
docker.xuanyuan.run/akiralereal/iptv:4.51.2
查看状态:
docker ps --filter name=iptv
docker logs iptv
浏览器仍然打开 http:// 服务器 IP:1905/admin。停掉并删除容器时,数据目录还在:
docker stop iptv && docker rm iptv
常见问题
日志开头为什么说 Tini is not running as PID 1?
镜像入口已经是 /sbin/tini。init: true 或 docker run --init 再套一层 init 之后,tini 不是 PID 1,就会打出启动日志里的三行警告。容器仍然是 Up,/admin 这次返回 200。
要去掉这三行,删掉 compose.yaml 里的 init: true(docker run 则删掉 --init),再启动一次。
订阅地址报 interface.txt 不存在,后台却能播放?
/interface.m3u 和 /playback.xml 读的是数据目录里的 interface.txt、playback.xml。这次在 14:53:42 和 14:53:57 请求时,两个文件都还不在,所以日志是 ENOENT。管理后台的「播放」不读这两个文件。刷新后的「我的频道」是 1036 个频道,体育分组里可以打开播放窗。
播放器订阅若失败,隔一会儿再打开同一地址。
为什么命令里不写 latest?
latest、4、4.51 会在下次发布后改指向。本文命令使用 4.51.2。要换版本时,先改 compose.yaml 里的标签,再执行「怎么升级」里的两条命令。
1905 已经被占用怎么办?
只改冒号左边,例如改成 11905:1905,mport 保持 1905。浏览器和播放器地址里的端口改成 11905。容器内端口要改的话,冒号右边和 mport 一起改成同一个数。
以前的数据挂在 /migu/data,要改路径吗?
4.51.2 的默认数据目录是 /iptv/data。镜像仍声明了 /migu/data。旧的 Compose 如果挂的是 ./data:/migu/data,可以继续用;新路径没有数据、旧路径有数据时,程序会沿用旧目录。新部署按本文挂到 /iptv/data。
设置访问密码之后,地址怎么写?
在 compose.yaml 的 environment 里增加 mpass,值为大小写字母和数字,然后执行 docker compose up -d。管理页、播放列表和节目单都要带上这段路径,例如 http:// 服务器 IP:1905/ 密码 /admin。未带密码的请求会返回 403。播放列表里的频道链接会带上同一段路径。
只有内网在用,要填 mhost 吗?
不用。前面有反向代理,或希望播放列表里写成固定公网地址时,再增加 mhost,值为完整的 http:// 或 https:// 地址,然后执行 docker compose up -d。
只有声音,没有画面
项目说明这通常是 H.265 兼容问题。打开「源管理」里对应模块,取消「启用 H.265 原画」后重新播放。个别频道仍然如此,再关掉 HDR。用环境变量时,把 menableH265=false 写进 environment,需要时再加 menableHDR=false,然后重建容器。
频道和台标都在,播放一直转圈
播放器可能没有跟随跳转。换「播放器怎么选订阅」里的兼容版地址,重新加到播放器。兼容版仍然失败,再试全代理版。全代理占用这台机器的上行带宽,标准版或兼容版能播时不必开。
机器变卡,日志里反复启动浏览器
网页抓取、部分广电续签会启动无头 Chromium。项目说明每路大约 200~400 MB,内存不超过 2 GB 时容易进入交换分区。不需要网页抓取的来源,在「源管理」里关掉。内存较小的机器,在 environment 里加上 mbrowserConcurrency=1,让同时存活的浏览器不超过 1 个,然后重建容器。
怎么升级?
把 compose.yaml 里的 4.51.2 改成新的版本号标签,再执行:
cd /www/wwwroot/iptv
docker compose pull
docker compose up -d
数据在 ./data。不要执行 docker compose down -v,那会删掉卷。升到 4.51.2 时,该版说明是现有配置和订阅不用改。再往上升之前,先看对应 Release。
能不能拿去售卖订阅?
不能把未获授权的频道拿去售卖订阅、公开转播,或绕过登录、付费和地域限制。项目维护者写明,这是个人学习和家庭自用的工具。权利边界以 项目说明 里的免责声明为准。无法确认某个来源时,在「源管理」里关掉它。
只想从空白频道表开始、自己加来源时,在数据目录还是空的第一次启动前加上 mblank=true。这项会把内置模块默认关掉。数据目录里已经有配置时,再设这个变量不会把现有开关清掉,要在「源管理」里改。
命令速查
docker pull docker.xuanyuan.run/akiralereal/iptv:4.51.2
cd /www/wwwroot/iptv
docker compose up -d
docker compose ps
docker compose logs iptv
curl -sS -o /dev/null -w "%{http_code}\n" --max-time 20 http://127.0.0.1:1905/admin
docker compose down
没有 Compose 时用「备选:docker run」里的命令。浏览器打开 http:// 服务器 IP:1905/admin。没有预置账号。播放列表是 http:// 服务器 IP:1905/interface.m3u。
延伸阅读
阅读原文
本文基于 akiralereal/iptv:4.51.2,以 4.51.2 版本实测,测试平台 Ubuntu 24.04 Linux。