目录

Free-TV/IPTV:把 100+ 国家免费电视频道手工策展成一个 M3U playlist 的数据项目

Free-TV/IPTV:把 100+ 国家免费电视频道手工策展成一个 M3U playlist 的数据项目

学习目标

  • 看清 Free-TV/IPTV 这个仓库不是软件工具,而是一份长期人工维护的 M3U 数据集——理解这一点才不会被"克隆下来跑一下"的预期误导。
  • 记住它的三条策展哲学:质量优先、只免费、只主流,并能用这些哲学解释为什么这个仓库只有几百个频道而不是几万。
  • 读懂仓库的目录结构(lists/*.md + playlist.m3u8)与生成器 make_playlist.py 的关系,知道 PR 只能改 .md、不能直接改 m3u8
  • 区分它跟 iptv-org/iptv 的根本差别:Free-TV 走"几百个稳定频道"路线,iptv-org 走"几十万频道 + 自动失效检测"路线。
  • 知道它的硬约束:无 SPDX License、只收录用户能证明"确实免费"的频道、依赖 IPTV 播放器(VLC/Kodi/IPTV Pro 等)。

目录

  1. 为什么写这篇文章
  2. 核心判断:这不是软件,是数据策展
  3. 系统地图:仓库结构与生成管线
  4. 策展哲学:为什么只有几百个频道
  5. 硬约束与适用边界
  6. [使用方式:3 步上手](#6-使用方式 3-步上手)
  7. 怎么参与贡献
  8. 适用人群与不适用人群
  9. 常见问题(FAQ)
  10. 总结
  11. 自测题
  12. 练习
  13. 进阶路径

1. 为什么写这篇文章

GitHub Trending 周榜最近又一次把 Free-TV/IPTV 顶上来——它是一个 2021 年 4 月创建、到现在 5 年多还在每天更新、Star 17k 的 IPTV 数据项目。仓库里没有任何二进制、没有编译产物、没有 release,只有一个 playlist.m3u8 文件夹 + 一堆 lists/*.md + 一个 Python 生成脚本。

这件事本身就值得专门写一篇:在一个"PR 几分钟就有人合并"的开发节奏里,一个靠人手 PR 维护的纯数据仓库为什么能稳定运行 5 年?它跟同领域的明星项目 iptv-org/iptv(122k stars)到底是什么关系,是竞品、子集、还是不同物种?

仓库当前状态(截至 2026-06-15):

  • 仓库:Free-TV/IPTV
  • Stars / Forks:约 17,099 / 2,547
  • 主语言:Python(仅 make_playlist.py 一个脚本)
  • License:仓库未声明 SPDX(README 也未明示),按 README 内容定位为公开数据集合
  • Topics:help-wantedlooking-for-contributors
  • 创建时间:2021-04-13
  • 收录国家:100+(USA、CA、GB、AU、CN、HK、JP、KR、DE、FR、RU、BR、IN……)

注意:仓库没有 LICENSE 文件、也没有 SPDX 标识。使用前需要自行评估"无明确许可证 = 默认保留权利"这条默认规则的影响——下文第 5 节会展开。


2. 核心判断:这不是软件,是数据策展

很多人第一次看到这个仓库会问:“克隆下来怎么跑?“答案是不需要跑任何东西。仓库的最终产物是:

https://raw.githubusercontent.com/Free-TV/IPTV/master/playlist.m3u8

把这一行粘进 VLC、Kodi、IPTV Pro、TiviMate、OTT Navigator 等任何支持 M3U 的播放器,就能直接拿到一份覆盖 100+ 国家、几百个频道的直播源列表。

这跟同领域的 iptv-org/iptv 在形态上非常像(同样是 M3U playlist + 同样的播放器兼容矩阵),但内部组织完全不同。下表是关键差异:

维度Free-TV/IPTViptv-org/iptv
规模几百个频道几万到十几万个频道
收录策略人工策展(PR 评审质量)自动抓取 + 用户提交
数据形态lists/*.md(人类可读) + playlist.m3u8(生成产物)streams/*.m3u(机器可读) + 外部 iptv-org/database
EPG(电子节目单)不提供iptv-org/epg 单独维护
失效处理手工把失效频道移到 Invalid 分类、[x] 标记自动化 cron 定期探测
频道元数据库无独立数据库iptv-org/database(独立仓库,1.4k stars)
License无 SPDXThe Unlicense(公有领域)

结论:两个项目不是替代关系,是不同物种。Free-TV 的目标是"给我一份稳定能看的清单”,iptv-org 的目标是"尽可能多地收录公开流并提供 API”。


3. 系统地图:仓库结构与生成管线

Free-TV 的仓库布局极简,但每一处都跟"数据策展"这个定位对齐:

Free-TV/IPTV/
├── playlist.m3u8              ← 最终播放列表(生成产物,不要 PR)
├── lists/                     ← 各国/语种的手工策展清单
│   ├── usa.md
│   ├── china.md
│   ├── japan.md
│   ├── germany.md
│   └── ... (100+ 国家)
├── make_playlist.py           ← 从 lists/*.md 生成 playlist.m3u8
└── README.md

3.1 lists/*.md:人类可读的策展层

每个 lists/<country>.md 是一个 Markdown 表格,列是这个频道的元数据。README 给出了清晰的列约定(基于仓库中实际表格示例):

  • Channel:频道名(带国旗 emoji 或图标)
  • URL:流地址,但前面有状态前缀:
    • [>] 表示有效流,会被收入最终 playlist.m3u8
    • [x] 表示失效或暂时不可用,留在表格但不进 playlist
    • 无前缀的 URL 在 README 规则下不会被收入
  • 画质标记(追加在频道名后):
    • = SD(标清)
    • = GeoIP 限制(部分国家能看、部分国家不能)
    • = YouTube Live 来源

举个例子(基于仓库真实片段抽象出的格式):

| Channel | url | HD/SD | Notes |
|---|---|---|---|
| CNN | [>](https://cnn.example.com/live.m3u8) | HD | |
| Local News | [x]() | | 失效流,保留待恢复 |
| YouTube Music Live | [>](https://youtube.com/watch?v=...) | Ⓨ | YouTube 来源 |

这种设计的好处:

  1. PR reviewer 看得懂:一个 PR 上来就是表格的 +/- 行 diff,不需要懂 M3U 格式。
  2. 状态可逆:流失效了,把 [>] 改成 [x],不需要删频道元数据;恢复时改回去就行。
  3. 错误被编码在文本里// 这些 unicode 字符就是机器可读的状态标记,不依赖额外元数据。

3.2 make_playlist.py:唯一的代码

整个仓库只有这一个 Python 脚本,职责单一:

  1. 遍历 lists/*.md 下所有 <country>.md
  2. 用 markdown 解析器读出每个表格行。
  3. 把状态是 [>] 的频道条目转换成 M3U #EXTINF + 流地址格式。
  4. 把所有国家的条目合并、按规则排序,输出 playlist.m3u8

这个脚本本身不抓取、不检测、不更新——它只是把"人工维护的 markdown"编译成"播放器能吃的 M3U"。所有"频道当前还能不能看"的知识都在 lists/*.md 里,由维护者和 PR 贡献者手动维护。

3.3 playlist.m3u8:只读产物

README 明确写了:不要在 PR 里修改 playlist.m3u8 文件本身。它是 make_playlist.py 运行后的产物,由仓库维护者定期(或 CI 自动)重新生成。提交改 playlist 的 PR 会被直接 close。

这条规则的存在说明一件事:仓库把"事实(频道元数据)“和"视图(M3U 播放列表)“明确分层。事实由 PR 改、视图由脚本生成——这是非常经典的数据-视图分离模式。


4. 策展哲学:为什么只有几百个频道

Free-TV 的 README 把策展哲学写得很硬,三条铁律:

Quality over quantity — Less channels is better. All channels should work well. As much as possible in HD, not SD. Only one URL per channel.

Only free channels — No paid channels. Only channels officially provided for free (DVB-S、DVB-T、analog 等)。

Only mainstream channels — No adult, no particular religion, no particular political party, no channels made for a country and funded by a different country。

这三条翻译成技术决策就是:

  • 频道数量天花板被刻意压低。README 自己写"The less channels we support the better”——这种声明在开源数据项目里非常少见。
  • PR 评审要做的事实核查包括:“你能证明这个频道确实是免费的吗?"——这个证明要写到 PR 描述里。
  • 失效流不删元数据,只标记 [x]——确保频道历史信息可追溯、恢复成本低。

直接结果是:这个仓库收录的频道总数长期保持在几百个量级,而 iptv-org/iptv 的 streams 数量是 8-10 万级别。前者是"能看的”,后者是"可能能看的”


5. 硬约束与适用边界

5.1 许可证状态

仓库根目录没有 LICENSE 文件,README 也没有声明 SPDX。这在 GitHub 上的默认含义是"All rights reserved"——其他人在没有明确授权的情况下不能直接 fork 后改 license 再发布。

实际使用层面:

  • 个人看直播:playlist URL 是公开的,拿去播放器里用没有法律风险(这是流地址本身的事,跟仓库 License 无关)。
  • 基于这份 playlist 做衍生作品:需要谨慎。最稳妥的做法是联系维护者或在 issue 里问清楚。
  • 要规避 License 不明确的风险:用 iptv-org/iptv(Unlicense / 公有领域)反而更省心。

5.2 频道流的有效期

playlist 里的频道流地址大部分是第三方服务器提供的(电视台自有 CDN、YouTube Live、Dailymotion Live 等)。这些地址会随时间失效,可能几周、几个月、几年。

Free-TV 处理失效的方式是人工——PR 把失效频道移到 Invalid 分类、[x] 标记。这意味着:

  • 任何时刻打开 playlist 都会有一部分频道是失效的;
  • 但失败模式是"少数频道放不出来",不是"整个 playlist 失效";
  • 持续维护(PR 提交 + reviewer 合并)是这个仓库能用的前提。

5.3 地域限制

很多免费频道使用 GeoIP 限制——同一个频道流在美国能看、在欧洲不能看。Free-TV 在表格里用 标记这些频道,PR 时会要求贡献者说明流在哪些国家能用。

这意味着 playlist 不是地域无关的资源——打开播放器看到一堆频道但很多打不开是正常现象。

5.4 没有 EPG、没有 Logo 库、没有 API

Free-TV 不提供:

  • EPG(Electronic Program Guide,节目单)—— 需要自己找;
  • 频道 Logo 数据库—— 部分频道行里附了 imgur 图标,但不是统一库;
  • 查询 API—— playlist 是静态文件,没有元数据查询能力。

如果需要这些,要去找 iptv-org 的 epg / database / api 三个仓库(合计 2k+ stars),或者自建。


6. 使用方式:3 步上手

仓库最终交付物就是一行 URL,使用流程极简:

步骤 1:选一个支持 M3U 的播放器

主流选项:

  • 桌面:VLC(跨平台,免费)、Kodi + PVR IPTV Simple Client(跨平台,免费)
  • 移动:IPTV Pro(Android)、TiviMate(Android,付费但口碑好)、OTT Navigator(Android)、iPlayTV(iOS)
  • 智能电视/盒子:TiviMate(Android TV)、IPTV Smarters

步骤 2:导入 playlist URL

https://raw.githubusercontent.com/Free-TV/IPTV/master/playlist.m3u8

在播放器的"M3U URL"或"Add playlist"位置粘贴这行。播放器会拉取 M3U 文件、解析 #EXTINF 条目、显示出频道列表。

步骤 3:分类浏览

M3U 文件里频道按国家分组(group-title)。展开你所在的国家分组,挑一个频道点开。如果某个频道打不开——大概率是 GeoIP 限制或者流已失效。换另一个频道看就行。

可选:用 make_playlist.py 自定义输出

如果想把所有频道 dump 到本地,自己跑:

git clone https://github.com/Free-TV/IPTV.git
cd Free-TV/IPTV
python3 make_playlist.py
# 输出 playlist.m3u8

不过这个脚本不带参数——要定制(比如只输出某个国家、只输出 HD 频道)需要改源码。


7. 怎么参与贡献

仓库 README 把贡献规则写得很清楚,关键点:

  1. 不要改 playlist.m3u8 文件。这是生成产物,改它的 PR 会被 close。
  2. 只改 lists/*.md。所有频道元数据都在这里。
  3. 添加频道要在 PR 描述里证明"这个频道确实是免费的"。例如贴出电视台官网的"Free to air"声明。
  4. 删除频道要证明"这个频道现在只有付费订阅能看"。注意 README 明确说"公共税收资助的电视(无论叫 TV License 还是其他名字)不构成付费订阅"——这条规则避免误删公共服务频道。
  5. 失效频道不要删,移到 Invalid 分类、把 [>] 改成 [x]
  6. issue 只用来提 bug 和 feature request。添加/编辑/删除频道要走 PR,不要发 issue。

对贡献者来说,这意味着修改的最小颗粒度是一个 Markdown 表格行——非常友好,不需要懂任何 M3U 知识。


8. 适用人群与不适用人群

适合

  • 想有一份"打开就能看"的全球免费电视清单的人。装个 VLC、粘一行 URL、就能看。
  • 研究者 / 数据分析师:想看"100+ 国家公开流媒体地址是怎么组织的"——lists/*.md 是个很干净的样本。
  • 想为开源数据项目做贡献但不想写代码的人:贡献方式就是改 Markdown 表格,门槛极低。
  • 需要规避自动失效检测失效的人:iptv-org 的自动 cron 偶尔会误杀有效流,Free-TV 的人工评审更稳。

不适合

  • 想要 EPG 节目单——Free-TV 不提供,需要用 iptv-org 的 epg 仓库或第三方服务。
  • 想要几万个频道——Free-TV 的定位就是"几百个稳定的",不想要的话用 iptv-org。
  • 想做商业二次分发——仓库 License 不明确,商业场景需要谨慎。
  • 完全不想自己处理失效频道——playlist 里总是有失效项,靠手动跳过去。

9. 常见问题(FAQ)

playlist.m3u8 里的频道突然不能看了,怎么办?

先确认是这个频道失效了,还是你的网络问题。换一个频道试试;如果多个频道都不能看,可能是播放器缓存或网络问题。单个频道失效的话,可以去仓库提 issue 告知维护者。

为什么有些频道显示 GeoIP 限制(Ⓖ)?

这些频道只允许特定国家访问。比如美国本地频道只在美国境内能看。Free-TV 用 标记这些频道,PR 时会要求贡献者说明流在哪些国家能用。如果你在不允许的国家,这个频道就打不开。

我可以商业使用这个 playlist 吗?

仓库没有 LICENSE 文件,默认是"All rights reserved"。商业使用前需要联系维护者确认。个人观看没有问题,因为播放的是公开流地址。

为什么不用 iptv-org/iptv?

两个项目定位不同。Free-TV 走"几百个稳定频道"路线,人工策展、PR 评审质量;iptv-org 走"几十万频道 + 自动失效检测"路线,规模更大但稳定性较低。如果你想要稳定能看的清单,选 Free-TV;如果你想要尽可能多的频道,选 iptv-org。

怎么知道一个频道确实是免费的?

在添加频道的 PR 描述里需要证明。例如贴出电视台官网的"Free to air"声明、Wikipedia 页面说明、或政府公开广播服务的说明。不能只贴一个流地址就提 PR。


10. 总结

Free-TV/IPTV 不是一个软件项目,它是一个用 Markdown 表格 + Python 生成脚本长期人工维护的 M3U 数据集。5 年的稳定运行说明这种"数据-视图分离 + 人工策展 + 严格 PR 规则"的模式在小规模数据项目上完全可行。

它的真正价值不在 playlist 本身,而在三件事:

  1. 策展哲学的样板:质量优先、只免费、只主流——这三条铁律比一万个频道都重要。
  2. 数据-视图分离的最小化实现lists/*.md(事实)+ make_playlist.py(视图)+ playlist.m3u8(产物),三件套互不重叠。
  3. 贡献门槛低到只有 Markdown:PR reviewer 看的是表格 diff,不是代码。

如果你想参与一个低代码、低冲突、长期维护的开源数据项目,Free-TV/IPTV 是个值得 clone 下来看一眼的样本。如果你只想要一个能用的 M3U playlist——粘那行 URL 进 VLC 就行。


自测题

  1. Free-TV/IPTV 仓库的最终产物是什么?

    点击查看答案最终产物是 playlist.m3u8 文件,可以通过 URL https://raw.githubusercontent.com/Free-TV/IPTV/master/playlist.m3u8 直接在支持 M3U 的播放器中使用。
  2. Free-TV/IPTV 与 iptv-org/iptv 的根本区别是什么?

    点击查看答案Free-TV 走"几百个稳定频道"路线,人工策展、PR 评审质量;iptv-org 走"几十万频道 + 自动失效检测"路线,规模更大但稳定性较低。
  3. 为什么 PR 不能直接修改 playlist.m3u8 文件?

    点击查看答案因为 playlist.m3u8 是生成产物,由 make_playlist.py 脚本从 lists/*.md 生成。直接修改生成产物会导致与源数据不同步。
  4. Free-TV/IPTV 的三条策展哲学是什么?

    点击查看答案1. Quality over quantity(质量优先);2. Only free channels(只收录免费频道);3. Only mainstream channels(只收录主流频道)。
  5. Free-TV/IPTV 仓库的 License 状态是什么?这对使用有什么影响?

    点击查看答案仓库没有 LICENSE 文件,默认是"All rights reserved"。个人观看没有问题,但做衍生作品需要联系维护者确认。

练习

练习 1:添加一个新的免费频道

  1. Fork Free-TV/IPTV 仓库
  2. lists/ 下找到对应国家的 .md 文件
  3. 添加一个新的频道条目,使用 [>] 前缀表示有效流
  4. 在 PR 描述中证明该频道确实是免费的(提供电视台官网链接)
  5. 提交 PR 并等待评审

练习 2:运行生成脚本

  1. Clone 仓库到本地
  2. 运行 python3 make_playlist.py
  3. 检查生成的 playlist.m3u8 文件
  4. 尝试用 VLC 打开生成的 playlist

练习 3:标记失效频道

  1. 找到一个已经失效的频道
  2. 将其 URL 前缀从 [>] 改为 [x]
  3. 提交 PR

进阶路径

  1. 了解 M3U 格式规范:阅读 M3U 格式文档,理解 #EXTINF 标签的含义
  2. 研究 iptv-org 项目:对比 iptv-org/iptv 的架构,理解自动失效检测的实现方式
  3. 搭建自己的 IPTV 播放器:基于开源播放器(如 VLC 或 Kodi)定制自己的 IPTV 解决方案
  4. 贡献其他数据源:如果你有其他免费频道数据源,可以贡献给 Free-TV 或创建类似的数据策展项目
  5. 研究 EPG(电子节目单):了解 EPG 格式(XMLTV),尝试为 Free-TV 添加 EPG 支持

资料口径说明

  1. 信息来源:本文基于 Free-TV/IPTV 仓库的 README(2026-06-15 版本)和仓库代码结构分析
  2. 版本时效性:仓库仍在活跃维护中,本文描述的功能和策展哲学可能在未来版本中变化
  3. 数据准确性:仓库的频道数据由社区贡献,本文未逐一验证每个频道的有效性
  4. License 状态:仓库无明确 LICENSE 文件,本文的解释基于 GitHub 的默认规则,不代表法律建议
  5. 使用风险:使用本 playlist 观看电视频道需遵守当地法律法规,某些频道可能有地域限制

参考链接