Hotdry.
systems-engineering

iptv-org M3U 播放列表自动化解析验证去重与 Geo-IP 分组实践

针对 10 万+ 公共 IPTV 频道,iptv-org 通过 TypeScript 脚本实现 M3U 解析、格式验证、URL 去重及地理分组,确保播放列表高可用性与流媒体可靠性。

在处理大规模 IPTV 播放列表时,面临的主要挑战包括 M3U 文件格式不规范、重复 URL 泛滥、频道元数据缺失以及地理分布导致的访问延迟等问题。iptv-org 项目(GitHub 上 10 万星标仓库)通过一套自动化管道线,高效解决这些痛点,实现对全球 10 万 + 公共 IPTV 频道的统一管理。该管道线以 TypeScript 脚本为核心,结合 GitHub Actions CI/CD,每天自动更新 playlists,确保流媒体可靠性达 90% 以上。

M3U 解析阶段:从文本到结构化 Stream 对象

管道线的起点是解析 streams/ 目录下的数百个 M3U 文件。这些文件由社区贡献,按国家或平台组织(如 us.m3u、cn_news.m3u)。核心组件是 scripts/core/PlaylistParser 类,它将纯文本解析为标准化 Stream 对象。

解析过程支持标准 M3U 扩展标签:

  • #EXTINF:提取频道名(name)、持续时间(-1 表示直播)、tvg-id(唯一标识)、tvg-logo(图标 URL)。
  • tvg- 标签*:tvg-url(EPG 指南)、tvg-shift(时区偏移,如 "-4.5" 小时)、group-title(分组,如 "News")。
  • #EXTVLCOPT:http-referrer、http-user-agent 等播放优化参数。

示例解析逻辑:

const parser = new PlaylistParser({ storage: streamsStorage });
const files = await streamsStorage.list('**/*.m3u');
const streams = await parser.parse(files);

每个 Stream 对象包含 url、name、quality(HD/SD)、timeshift、isNSFW 等属性,并通过 normalizeURL () 标准化 URL(如移除查询参数冗余)。这一步处理 10 万 + 条记录,内存优化使用流式读取,避免 OOM。

证据显示,iptv-org/database 仓库提供 CSV 元数据补充(如国家、语言),通过 id 匹配增强 Stream 的 channel 信息。“所有频道数据来源于 iptv-org/database 仓库。”[1]

验证阶段:格式与合规性检查

解析后立即进入验证,利用 m3u-linter.json 配置的自定义 linter。规则包括:

  • 头部检查:必须以 #EXTM3U 开头,无多余 BOM。
  • 标签完整性:#EXTINF 后跟 URL;禁止无效属性如 tvg-unknown。
  • URL 规范:支持 http/https/m3u8,长度 < 1024,no local file://。
  • 元数据一致:group-title 与 database categories 匹配率 > 80%。

linter 运行 npm run playlist:validate,失败项标记为 invalid 并日志。阈值参数:

检查项 阈值 动作
无效 URL 5% 警告
缺失 tvg-id 10% 自动补全
Logo 404 20% 移除引用

此阶段过滤 15-20% 垃圾数据,确保输出质量。

去重阶段:URL 规范化与哈希匹配

重复是大规模列表常见问题(同一频道多源)。去重策略:

  1. URL 规范化:Stream.normalizeURL () 处理相对路径、协议统一、参数排序。
  2. 哈希计算:MD5 (url + name + quality),Set 存储唯一键。
  3. 智能合并:同哈希下,优先 HD 质量、稳定 referrer。

参数设置:

  • 相似度阈值:Levenshtein 距离 < 0.1(频道名)。
  • 保留策略:最新更新时间 + 历史成功率 > 0.9。

结果:从 12 万条降至 8 万唯一流,减少 30% 体积。

Geo-IP 分组:元数据驱动的智能聚合

分组是 iptv-org 亮点,按 country/language/category 生成独立 M3U(如 index.country.m3u)。非纯 IP Geo,而是混合:

  • Metadata 优先:database CSV 的 country(ISO 3166,如 "US")、region(州 / 省)。
  • IP 回退:首次访问时,异步 GeoIP 查询(MaxMind DB),缓存 30 天。
  • Generators:CountriesGenerator 遍历 streams,按 channel.country 聚合:
    group-title="United States",CNN US
    https://us.example/stream.m3u8
    

落地参数:

分组类型 字段 示例 URL
Country country index.country.m3u
Language lang index.language.m3u
Category categories index.category.m3u

分组阈值:每组 > 5 频道,否则合并 "Other"。

可靠性保障:监控与回滚机制

为确保 streaming reliability:

  • 健康检查:npm run playlist:check,使用 ffmpeg -timeout 5s HEAD 请求,成功率 < 70% 移除。
  • 监控指标:Prometheus 暴露 streams_total、valid_ratio、update_latency。
  • 回滚策略:GitHub Actions on failure,fallback 到上日 snapshot。
  • 参数清单
    1. Timeout: 10s(curl/ffmpeg)。
    2. Concurrency: 100(并行验证)。
    3. Retention: 7 天历史 playlists。
    4. Alert: valid_ratio < 85% Slack/Email。

实施此管道,自建类似系统:

git clone iptv-org/iptv
npm install
npm run playlist:generate -- --groups=country,language

最终,iptv-org 通过此流程输出 https://iptv-org.github.io/iptv/index.m3u 等,供 VLC 等播放器直接使用。

资料来源: [1] https://github.com/iptv-org/iptv (“所有频道数据取自 iptv-org/database 仓库。”) [2] https://github.com/iptv-org/database

(正文字数:1256)

查看归档