--- url: /guide/fcc-setup.md --- # FCC 快速换台配置 FCC (Fast Channel Change) 是运营商级的快速换台协议,可实现毫秒级换台响应。中国大多数省份的 IPTV 机顶盒都是通过 FCC 实现快速换台。 ## FCC 工作原理 ### 为什么纯组播起播慢? 视频编码(如 H.264/H.265)采用帧间压缩,只有关键帧(IDR 帧)才包含完整的画面信息,后续帧(P 帧、B 帧)都依赖关键帧进行解码。组播流是持续不断发送的,当播放器中途加入时,收到的第一个包大概率不是关键帧,播放器必须等到下一个关键帧到达才能开始解码。关键帧的间隔(GOP)通常为 1-5 秒,因此纯组播换台时会有明显的等待时间。 ### FCC 如何实现快速起播? FCC 服务器缓存了各频道最近的关键帧。当播放器换台时: 1. rtp2httpd 向 FCC 服务器发起单播请求 2. FCC 服务器立即回传缓存的关键帧及后续数据,播放器无需等待即可开始解码 3. 与此同时,rtp2httpd 也加入了对应频道的组播组 4. 当单播流和组播流的数据同步后,rtp2httpd 无缝切换到组播流,断开单播连接 整个过程对播放器透明,保证播放器收到的第一帧是可立即解码出画面的 IDR 帧。 因此必须先找到组播源对应的 FCC 服务器,才可以使用。 ## FCC 服务器获取方法 ### 方法一:查询已知 FCC 服务器列表 可以先查看 [各地 FCC 地址汇总](../reference/cn-fcc-collection.md),尝试能否找到自己本地可用的地址。 ### 方法二:从机顶盒抓包获取 如果列表中没有你的地区,则需要从 IPTV 机顶盒抓包获取。 #### 使用 Wireshark 抓包 1. **安装 Wireshark**:在 PC 上安装 Wireshark 抓包工具 2. **连接机顶盒**: * 方式 1:使用网络分路器或镜像端口 * 方式 2:将 PC 设置为机顶盒的网关进行中间人抓包 具体方式这里不再详述,网络教程很多。 3. **找到频道清单请求,搜索关键字段**: * 查找 `ChannelFCCIP` 字段:FCC 服务器 IP 地址 * 查找 `ChannelFCCPort` 字段:FCC 服务器端口号 4. **或者直接识别 FCC 协议包**: * 或者你也可以直接尝试播放,通过换台触发 FCC 流程,直接抓 FCC 协议包 * 下载安装 [Wireshark FCC 协议插件](https://github.com/stackia/rtp2httpd/blob/main/wireshark-support/README.md) * 通过筛选 `fcc` 定位 FCC 协议包,记录下对端 IP 和端口 ## 配置和使用 FCC ### 在 URL 中指定 FCC 服务器 ```url http://服务器地址:端口/rtp/组播地址:端口?fcc=FCC服务器IP:端口[&fcc-type=协议类型] ``` **示例**: ```url # 默认使用电信 FCC 协议 http://192.168.1.1:5140/rtp/239.253.64.120:5140?fcc=10.255.14.152:15970 # 手动指定华为 FCC 协议 http://192.168.1.1:5140/rtp/239.253.64.120:5140?fcc=10.255.14.152:8027&fcc-type=huawei # 如果使用 rtp2httpd 的 M3U 转换功能,也可以在 M3U 里这样写 rtp://239.253.64.120:5140/?fcc=10.255.14.152:15970 ``` #### fcc-type 参数说明 * **telecom** 或 不指定:使用电信/中兴/烽火 FCC 协议 * **huawei**:使用华为 FCC 协议 两种协议区别很小,大多数情况使用 `telecom` 就可以工作。在一些特定网络环境下可能需要 `huawei` 协议。 ### 在 M3U 中配置 FCC 如果使用 M3U 播放列表,可以在每个频道的 URL 中添加 FCC 参数: ```m3u #EXTM3U #EXTINF:-1,CCTV-1(电信 FCC) http://192.168.1.1:5140/rtp/239.253.64.120:5140?fcc=10.255.14.152:15970 #EXTINF:-1,CCTV-2(华为 FCC) http://192.168.1.1:5140/rtp/239.253.64.121:5140?fcc=10.255.14.152:8027 ``` ## NAT 穿透配置 > \[!IMPORTANT] > 只有当 rtp2httpd 运行在 NAT 设备之后(例如 NAS、二级路由),才需要进行 NAT 穿透配置。如果 rtp2httpd 所在设备/容器拥有直接的 IPTV 网络访问能力(可以直接获得 IPTV 内网 IP),则无需做任何 NAT 穿透配置。 ### 华为 FCC 协议 华为 FCC 协议原生支持 NAT 穿透,无需额外配置端口转发即可在 NAT 后面正常工作。华为 FCC 协议只在华为 IPTV 平台下可以使用。 ### 电信 FCC 协议 如果使用电信/中兴/烽火 FCC 协议,则需要配置端口转发,FCC 才可以正常工作。 基本上所有 IPTV 平台(包括华为)都支持电信 FCC 协议。 此外,你也需要在上级路由器配置 IGMP / 组播转发(`igmpproxy` / `omcproxy`),才能正常接收组播流。 #### 配置方法 请先手动指定 `--fcc-listen-port-range`: ```bash # 命令行 rtp2httpd --fcc-listen-port-range 40000-40100 # 配置文件 [global] fcc-listen-port-range = 40000-40100 ``` 然后需要在上级路由器配置端口转发,将这个端口范围(例如 `40000-40100`)转发到运行 rtp2httpd 的设备。 > \[!TIP] > 如果你的环境需要 NAT 穿透,且 FCC 服务器同时支持两种协议,建议优先使用华为 FCC 协议(端口 8027),可以省去端口转发配置。 ## 测试 FCC 是否工作 1. **使用起播较快播放器**:确保播放器本身起播速度足够快,不能成为瓶颈,例如 [内置 Web 播放器](./web-player.md)。 2. **观察换台速度**: * 正常启用 FCC:换台延迟 < 1s * 未启用 FCC:换台延迟 2-5 秒 3. **查看日志**: * 出现 `FCC: Unicast stream started successfully` 表示 FCC 地址有效,并且成功收到单播流。 * 出现 `FCC: Server response timeout (80 ms), falling back to multicast` 有两种可能 1. FCC 地址无效。 2. 你的网络配置不正确,导致无法连接到 FCC 服务器。一般来说必须通过 DHCP/IPoE/PPPoE 获得 IPTV 内网 IP 后,并启用 rtp2httpd `--upstream-interface-fcc` 或 `--upstream-interface` 选项指定 IPTV 接口后,才能访问 FCC。请结合 ping / traceroute 等工具判断。 ## 相关文档 * [各地 FCC 地址汇总](../reference/cn-fcc-collection.md):中国各省 FCC 服务器地址 * [URL 格式说明](./url-formats.md):FCC URL 格式 * [配置参数详解](../reference/configuration.md):FCC 相关配置参数 --- --- url: /guide/m3u-integration.md --- # M3U 播放列表集成 rtp2httpd 全面支持 M3U/M3U8 播放列表格式,可自动识别节目并提供转换后的播放列表,让你可以一键导入外部 m3u 频道列表,自动替换 URL,直接在 IPTV 播放器中使用。 ## 配置方法 ### 方法一:使用外部 M3U 文件 在配置文件中指定外部 M3U URL: ```ini [global] # 外部 M3U 配置(支持 file://, http://, https://) # 注意:HTTP/HTTPS 需要安装 curl 或 uclient-fetch 或 wget 命令 external-m3u = https://example.com/iptv.m3u # 或使用本地文件 external-m3u = file:///path/to/playlist.m3u # 外部 M3U 更新间隔(秒) # 默认 7200(2 小时),设为 0 禁用自动更新 external-m3u-update-interval = 7200 ``` ### 方法二:在配置文件中直接内联 M3U 在 `[services]` 区段直接编写 M3U 内容: ```ini [services] # 直接编写 M3U 内容,以 #EXTM3U 开头 #EXTM3U x-tvg-url="https://example.com/epg.xml.gz" # 基础频道配置 #EXTINF:-1 tvg-id="CCTV1" tvg-name="CCTV1" tvg-logo="https://example.com/logo/CCTV1.png" group-title="央视",CCTV-1 rtp://239.253.64.120:5140 # 带时移回看的频道配置 #EXTINF:-1 tvg-id="CCTV2" tvg-name="CCTV2" group-title="央视" catchup="default" catchup-source="rtsp://10.0.0.50:554/catchup?playseek={utc:YmdHMS}-{utcend:YmdHMS}",CCTV-2 rtp://239.253.64.121:5140 # 简单配置(只有频道名) #EXTINF:-1,广东卫视 rtp://239.194.10.15:1234 ``` ## 使用播放列表 ### 方式一:使用内置播放器 配置好 M3U 后,通过浏览器访问 `http://服务器地址:端口/player` 即可使用 [内置 Web 播放器](./web-player.md)。 ### 方式二:导出播放列表到其他播放器 转换后的 M3U 播放列表可通过以下 URL 访问: ``` http://服务器地址:端口/playlist.m3u ``` **示例**: ``` http://192.168.1.1:5140/playlist.m3u ``` 将此 URL 添加到支持 M3U 的 IPTV 播放器(如 APTV、TiviMate 等)即可使用。 ## 转换示例 ### 输入 M3U ```m3u #EXTM3U x-tvg-url="https://example.com/epg.xml.gz" #EXTINF:-1 tvg-id="CCTV1" tvg-name="CCTV1" tvg-logo="https://example.com/logo/CCTV1.png" group-title="央视" catchup="default" catchup-source="rtsp://10.0.0.50:554/catchup?auth=loremipsum&playseek={utc:YmdHMS}-{utcend:YmdHMS}",CCTV-1 rtp://239.253.64.120:5140 #EXTINF:-1 tvg-id="CCTV2" tvg-name="CCTV2" group-title="央视",CCTV-2 rtp://239.253.64.121:5140 #EXTINF:-1 tvg-id="HLS1" tvg-name="内网HLS源",内网HLS源 http://10.0.0.60/live/stream.m3u8 ``` ### 输出 M3U(转换后) ```m3u #EXTM3U x-tvg-url="http://192.168.1.1:5140/epg.xml.gz" #EXTINF:-1 tvg-id="CCTV1" tvg-name="CCTV1" tvg-logo="https://example.com/logo/CCTV1.png" group-title="央视" catchup="default" catchup-source="http://192.168.1.1:5140/CCTV-1/catchup?playseek={utc:YmdHMS}-{utcend:YmdHMS}",CCTV-1 http://192.168.1.1:5140/央视/CCTV-1 #EXTINF:-1 tvg-id="CCTV2" tvg-name="CCTV2" group-title="央视",CCTV-2 http://192.168.1.1:5140/央视/CCTV-2 #EXTINF:-1 tvg-id="HLS1" tvg-name="内网HLS源",内网HLS源 http://192.168.1.1:5140/内网HLS源 ``` > \[!NOTE] > > * EPG 的 URL 已转换为 rtp2httpd 代理地址 > * CCTV-1 和 CCTV-2 的 URL 已转换为 rtp2httpd 代理地址 > * CCTV-1 的 catchup-source 也已转换,并保留动态占位符 > * HLS 源的 HTTP URL 也会被转换为 rtp2httpd 代理地址,便于通过 rtp2httpd 为内网 HLS 源提供外网访问 ## 使用建议 1. **HTTP/HTTPS 支持** * 需要系统安装 `curl` 或 `uclient-fetch` 或 `wget` 命令 * rtp2httpd 会自动检测并使用可用的工具 2. **更新策略** * 默认 2 小时自动更新外部 M3U * 可根据源更新频率调整 `external-m3u-update-interval` * 设为 0 禁用自动更新(需手动重启服务更新) 3. **混合使用** * 可同时配置外部 M3U 和内联 M3U * 两者会合并到同一个转换后的播放列表中 * 内置 M3U 转换会转换所有可识别 URL(包括普通 HTTP URL)。这适合把内网 HLS 源转换为 rtp2httpd 代理地址后提供外网访问;如果希望某些 HTTP 源在导出的播放列表中保留原始 URL,请自行维护给播放器使用的 M3U 文件,而不要依赖 rtp2httpd 的转换输出。 4. **使用反向代理时开启 `xff` 选项** * M3U 在转换过程中,需要知道自身的完整访问地址,因此如果使用反向代理,请开启 `xff` 选项,并确保反代程序可以透传 `X-Forwarded-*` 相关头。详见 [公网访问建议](./public-access.md)。 ## URL 识别与转换规则 ### 支持的 URL 格式 rtp2httpd 能够识别并转换以下格式的 URL: 1. **直接协议 URL**: * `rtp://[source@]multicast_addr:port[?query]` * `rtsp://server:port/path[?query]` * `udp://multicast_addr:port[?query]` * `http://server/path[?query]`(作为 HTTP 反向代理服务) 2. **UDPxy 格式的 HTTP URL**: * `http://hostname:port/rtp/multicast_addr:port` * `http://hostname:port/rtsp/server:port/path` * `http://hostname:port/http/server/path` * 会自动把 `hostname:port` 替换为 rtp2httpd 实际的地址和端口 ### 转换示例 | 原始 URL | 转换后 URL | | ------------------------------------------- | --------------------------------------------- | | `rtp://239.253.64.120:5140` | `http://hostname:5140/CCTV-1` | | `rtsp://10.0.0.50:554/live` | `http://hostname:5140/CCTV-2` | | `http://router:5140/rtp/239.1.1.1:1234` | `http://hostname:5140/频道名` | | `http://10.0.0.60/live/stream.m3u8`(HLS 源) | `http://hostname:5140/频道名` | **服务名称提取规则**:使用 `#EXTINF` 行中最后一个逗号后的文本作为服务名称。 ``` #EXTINF:-1 tvg-id="..." tvg-name="..." group-title="...",CCTV-1 ^^^^^^ 服务名称 ``` ## 时移回看(Catchup)支持 当 M3U 中包含 `catchup-source` 属性时,rtp2httpd 会自动创建对应的时移服务。 ### 配置示例 ```m3u #EXTINF:-1 tvg-id="CCTV1" catchup="default" catchup-source="rtsp://10.0.0.50:554/catchup?playseek={utc:YmdHMS}-{utcend:YmdHMS}",CCTV-1 rtp://239.253.64.120:5140 #EXTINF:-1 catchup="append" catchup-source="?starttime=${(b)yyyyMMdd|UTC}T${(b)HHmmss|UTC}&endtime=${(e)yyyyMMdd|UTC}T${(e)HHmmss|UTC}",CCTV-1 http://iptv.example.com/live/channel1.m3u8 ``` ### 转换结果 * **直播服务**:`http://hostname:5140/CCTV-1` * **时移服务**:`http://hostname:5140/CCTV-1/catchup?playseek={utc:YmdHMS}-{utcend:YmdHMS}` ### 占位符处理 * **动态占位符**(包含 `{` 或 `}`):保留在转换后的 URL 中,由播放器填充 * 例如:`{utc:YmdHMS}`、`{utcend:YmdHMS}` * **静态参数**:其他查询参数不会保留在转换的 m3u 中。但依然会保留在对上游的请求中。 ### 不可识别 URL 的处理 无法识别的 URL 会原样保留,不进行转换。例如,`catchup-source` 使用不支持的 HTTPS URL(如 `https://10.0.0.60/catchup`)时会保持原样。 ## 线路标签 通过在 URL 末尾添加 `$标签` 后缀,可以为频道源指定显示标签(如清晰度)。`$标签` 必须位于整个 URL 的最末尾。 只有在支持标签和频道聚合的播放器中(例如 [内置 Web 播放器](./web-player.md))才有效果。 ### 示例输入 ```m3u #EXTINF:-1 tvg-id="广东卫视" tvg-name="广东卫视" tvg-logo="https://example.com/logo/广东卫视.png" group-title="卫视",广东卫视 rtp://239.253.64.96:5140/?fcc=10.255.75.73:15970$超高清 #EXTINF:-1 tvg-id="广东卫视" tvg-name="广东卫视" tvg-logo="https://example.com/logo/广东卫视.png" group-title="卫视",广东卫视 rtp://239.253.64.200:5140/?fcc=10.255.75.73:15970$高清 #EXTINF:-1 tvg-id="广东卫视" tvg-name="广东卫视" tvg-logo="https://example.com/logo/广东卫视.png" group-title="卫视",广东卫视 rtp://239.253.64.44:5140/?fcc=10.255.75.73:15970$标清 ``` ### 示例输出 每个带 `$label` 的频道会生成独立的服务路径,`$label` 转换为 `/label` 子路径,同时 `$label` 保留在转换后 URL 的末尾: ```m3u #EXTINF:-1 tvg-id="广东卫视" tvg-name="广东卫视" tvg-logo="https://example.com/logo/广东卫视.png" group-title="卫视",广东卫视 http://192.168.1.1:5140/卫视/广东卫视/超高清$超高清 #EXTINF:-1 tvg-id="广东卫视" tvg-name="广东卫视" tvg-logo="https://example.com/logo/广东卫视.png" group-title="卫视",广东卫视 http://192.168.1.1:5140/卫视/广东卫视/高清$高清 #EXTINF:-1 tvg-id="广东卫视" tvg-name="广东卫视" tvg-logo="https://example.com/logo/广东卫视.png" group-title="卫视",广东卫视 http://192.168.1.1:5140/卫视/广东卫视/标清$标清 ``` ## 相关文档 * [内置 Web 播放器](./web-player.md):播放器功能、频道聚合、时间占位符 * [URL 格式说明](./url-formats.md):了解所有支持的 URL 格式 * [配置参数详解](../reference/configuration.md):查看完整配置选项 --- --- url: /guide/url-formats.md --- # URL 格式说明 rtp2httpd 支持多种流媒体协议,通过不同的 URL 前缀进行区分。 基本格式:`http://服务器地址:端口/路径[?参数1=值1][&参数2=值2][&参数3=值3]` 如果配置了 `app-path-prefix`,所有路径都需要加上此前缀。例如 `app-path-prefix = /app/rtp2httpd` 时,`/rtp/...`、`/status`、`/player`、`/playlist.m3u` 等路径分别变为 `/app/rtp2httpd/rtp/...`、`/app/rtp2httpd/status`、`/app/rtp2httpd/player`、`/app/rtp2httpd/playlist.m3u`。 当配置了 `r2h-token(HTTP 请求认证令牌)` 时,所有 URL 都需要额外带上参数 `r2h-token=` 才能访问。 > \[!TIP] > 除了 URL 参数,也支持通过 Cookie 或者 User Agent 来传递 `r2h-token`。例如 `Cookie: r2h-token=xxx` 或 `User-Agent: R2HTOKEN/xxx`。 ## 组播 RTP 转 HTTP 单播流 ```url http://服务器地址:端口/rtp/组播地址:端口[?fcc=FCC服务器:端口][&fcc-type=协议类型][&fec=FEC端口] ``` **示例**: ```url http://192.168.1.1:5140/rtp/239.253.64.120:5140 http://192.168.1.1:5140/rtp/239.253.64.120:5140?fcc=10.255.14.152:15970 http://192.168.1.1:5140/rtp/239.253.64.120:5140?fcc=10.255.14.152:8027&fcc-type=huawei http://192.168.1.1:5140/rtp/239.81.0.195:4056?fec=4055 http://192.168.1.1:5140/rtp/239.253.64.120:5140?fcc=10.255.14.152:15970&r2h-ifname=eth0&r2h-ifname-fcc=eth1 ``` ### 参数说明 * **组播地址**:IPTV 运营商提供的组播地址 * **端口**:组播端口号 * **fcc**(可选):FCC 快速换台服务器地址,格式为 `IP:端口` * **fcc-type**(可选):FCC 协议类型,可选值: * `telecom`:电信/中兴/烽火 FCC 协议(默认) * `huawei`:华为 FCC 协议 * **fec**(可选):FEC 前向纠错端口号,用于接收 FEC 冗余数据包来恢复丢包 * **r2h-ifname**(可选):指定使用的上游网络接口(覆盖全局配置) * **r2h-ifname-fcc**(可选):指定 FCC 使用的上游网络接口(覆盖全局配置) ### 使用场景 * 将运营商 IPTV 组播流转换为 HTTP 单播流 * 在局域网内多设备共享 IPTV 流 * 配合 FCC 实现毫秒级换台 * 配合 FEC 实现丢包恢复,提高播放稳定性 ## RTSP 转 HTTP ```url http://服务器地址:端口/rtsp/RTSP服务器:端口/路径[?参数] ``` **示例**: ```url # 直播流 http://192.168.1.1:5140/rtsp/iptv.example.com:554/channel1 # 时移回看(使用 playseek 参数) http://192.168.1.1:5140/rtsp/iptv.example.com:554/channel1?playseek=20240101120000-20240101130000 # 时移回看(使用 tvdr 参数) http://192.168.1.1:5140/rtsp/iptv.example.com:554/channel1?tvdr=20240101120000GMT-20240101130000GMT # 自定义时移参数名 + 起止时间独立偏移 http://192.168.1.1:5140/rtsp/iptv.example.com:554/channel1?seek=20240101120000-20240101130000&r2h-seek-name=seek&r2h-seek-offset=12,-12 # 显式开启 RTSP 近实时优化(参见 r2h-seek-mode 文档) http://192.168.1.1:5140/rtsp/iptv.example.com:554/channel1?playseek=20240101120000&r2h-seek-mode=range(UTC%2B8/3600) # 指定上游网络接口 http://192.168.1.1:5140/rtsp/iptv.example.com:554/channel1?r2h-ifname=eth0 ``` ### 使用场景 * 将 IPTV RTSP 单播流转换为 HTTP 流 * 实现 RTSP 时移回看功能 > \[!IMPORTANT] > rtp2httpd 的 RTSP 支持仅适用于承载单路 MPEG-TS 流的场景(即 IPTV 单播/时移回看),不支持监控摄像头等其他 RTSP 用途。 ### 常见问题:时移回看时,实际回看时间比节目单早了/晚了 8 小时 这是由于时区未能匹配。需要做时区转换。你可以尝试以下几种方式。 * 修改播放器 User Agent 设置,加上 `TZ/UTC+8` 或 `TZ/UTC-8`。例如 `AptvPlayer/1.3.3 TZ/UTC+8`。 * 修改播放链接,加上参数 `&r2h-seek-offset=28800` 或 `&r2h-seek-offset=-28800`。如果只需要调整起始/结束边界,可以使用 `&r2h-seek-offset=12,-12` 这样的形式分别偏移起始和结束时间 关于时移回看的参数处理(时区、偏移),详见 [时间处理说明](./time-processing.md)。 ## HTTP 反向代理 ```url http://服务器地址:端口/http/上游服务器[:端口]/路径[?参数] ``` **示例**: ```url # 代理 HLS 流(指定端口) http://192.168.1.1:5140/http/upstream.example.com:8080/live/stream.m3u8 # 代理 HTTP 请求(省略端口,默认 80) http://192.168.1.1:5140/http/api.example.com/video?auth=xxx&quality=hd ``` ### 参数说明 * **上游服务器**:目标 HTTP 服务器地址 * **端口**(可选):目标服务器端口,默认 80 * **路径**:请求路径,包括查询参数 ### 使用场景 * 代理上游 HLS/DASH 流媒体,统一认证和访问控制 * 为不支持直接访问的 IPTV 内网服务提供 HTTP 反向代理 ### 时移回看支持 HTTP 代理同样支持 `r2h-seek-name`、`r2h-seek-offset` 参数和 User-Agent 时区转换,处理方式与 RTSP 代理一致。 ```url # 自动识别 playseek 参数并进行时区转换 http://192.168.1.1:5140/http/iptv.example.com/channel1?playseek=20240101120000-20240101130000 # 使用自定义参数名 + 时间偏移 http://192.168.1.1:5140/http/iptv.example.com/channel1?catchup=20240101120000&r2h-seek-name=catchup&r2h-seek-offset=3600 # 指定上游网络接口 http://192.168.1.1:5140/http/iptv.example.com/channel1?r2h-ifname=eth0 ``` 详见 [时间处理说明](./time-processing.md)。 ### 注意事项 * 仅支持 HTTP 上游(不支持 HTTPS) * 可通过 `upstream-interface-http` 配置指定上游网络接口,也可以通过 `r2h-ifname` 参数在每次请求中指定 * 如果被代理的目标 URL 是 m3u 类型,其中所有 `http://` URL 会被自动改写为经过 rtp2httpd 代理后的地址(为了保证 HLS 流能被正确代理) ## IPv6 支持 所有 URL 中的主机地址均支持 IPv6。在 URL 中书写 IPv6 字面量时,需要使用方括号 `[]` 包裹: ```url # HTTP 反向代理(IPv6 上游) http://192.168.1.1:5140/http/[2001:db8::1]:8080/live/stream.m3u8 # RTSP 转 HTTP(IPv6 上游) http://192.168.1.1:5140/rtsp/[2001:db8::1]:554/channel1 # RTSP URL 带认证信息 rtsp://user:pass@[2001:db8::1]:554/live # IPv6 组播(需要系统和网络接口支持 IPv6 组播) http://192.168.1.1:5140/rtp/[ff3e::1]:1234 ``` ### 行为说明 * **域名自动双栈解析**:上游地址为域名时,按系统解析顺序依次尝试 IPv6 / IPv4 地址,连接失败时自动回退到下一个地址 * **Host 校验**:配置了 `hostname` 时,请求头中的 `[IPv6]:端口` 格式 Host 也能正确通过校验 * **服务监听**:`[bind]` 配置节和 `--listen` 参数均支持 IPv6 地址(如 `::1 5140` 或 `-l [::1]:5140`) ### 限制 * **`mcast-rejoin-interval` 不支持 IPv6** ## M3U 播放列表访问 ```url http://服务器地址:端口/playlist.m3u ``` **示例**: ```url http://192.168.1.1:5140/playlist.m3u ``` 获取转换后的 M3U 播放列表,包含所有通过配置文件和外部 M3U 定义的频道,并将 URL 转换成 rtp2httpd 监听的地址和端口,并使用频道名替换原始 IP、查询参数、认证信息。 ### 使用场景 * 一键导入别人维护的 m3u 频道源 * 隐藏频道源 IP、认证信息 * 自动更新频道信息 详见 [M3U 播放列表集成](./m3u-integration.md)。 ## 内置 Web 播放器 ```url http://服务器地址:端口/player ``` **示例**: ```url http://192.168.1.1:5140/player ``` 访问[内置 Web 播放器](./web-player.md),可以在网页端播放已配置的 M3U 频道列表。 播放器页面路径可以通过配置项 `player-page-path` 自定义。设置为 `/` 可以实现不带任何路径直接访问。 ## 状态页面 ```url http://服务器地址:端口/status ``` **示例**: ```url http://192.168.1.1:5140/status ``` 访问 Web 状态页面,查看: * 实时客户端连接统计 * 每个连接的 IP、状态、带宽使用、传输数据量 * 系统日志查看 * 远程管理功能(强制断开连接、调整日志级别等) * 服务控制:重载配置、重启工作进程 **服务控制**(等效于向 supervisor 发送 Unix 信号): | 操作 | 等效信号 | API | | --- | --- | --- | | 重载配置 | `SIGHUP` | `POST /status/api/reload-config` | | 重启工作进程 | `SIGUSR1` | `POST /status/api/restart-workers` | 将 `/status` 替换为实际的 `status-page-path` 配置值。详见 [配置参数详解 — 运行时配置管理](../reference/configuration.md#运行时配置管理)。 状态页面路径可以通过配置项 `status-page-path` 自定义。设置为 `/` 可以实现不带任何路径直接访问。 ## udpxy 兼容模式 rtp2httpd 完全兼容 udpxy URL 格式,可以无缝替换 udpxy / msd\_lite 等组播转单播服务。 ### udpxy 格式 ```url http://服务器地址:端口/udp/组播地址:端口 http://服务器地址:端口/rtp/组播地址:端口 ``` **示例**: ```url http://192.168.1.1:5140/udp/239.253.64.120:5140 http://192.168.1.1:5140/rtp/239.253.64.120:5140 ``` udpxy 兼容模式默认启用,可以通过配置参数 `udpxy = no` 禁用。禁用后仅支持通过 m3u 提供服务。 > \[!TIP] > 使用 `/udp/` 和 `/rtp/` 没有任何差别,选择任意一种即可。 ## 视频快照 在任意流媒体 URL 后添加 `snapshot=1` 参数,或在 HTTP 请求头中添加 `Accept: image/jpeg` 或 `X-Request-Snapshot: 1`,即可获取视频流的 JPEG 快照。 **示例**: ```url # 方式 1:URL 参数 http://192.168.1.1:5140/rtp/239.253.64.120:5140?snapshot=1 # 方式 2:HTTP 请求头 curl -H "Accept: image/jpeg" http://192.168.1.1:5140/rtp/239.253.64.120:5140 # 方式 3:自定义请求头 curl -H "X-Request-Snapshot: 1" http://192.168.1.1:5140/rtp/239.253.64.120:5140 ``` 详见 [视频快照配置](./video-snapshot.md)。 ## 相关文档 * [M3U 播放列表集成](./m3u-integration.md):播放列表配置 * [FCC 快速换台配置](./fcc-setup.md):启用毫秒级换台 * [视频快照配置](./video-snapshot.md):频道预览图功能 * [配置参数详解](../reference/configuration.md):查看完整配置选项 --- --- url: /guide/public-access.md --- # 公网访问建议 如果你需要将 rtp2httpd 暴露到公网,请务必做好安全防护。 目前公网上存在大量自动化扫描器,专门探测开放的 udpxy / msd\_lite 等无认证组播转单播服务,一旦被发现就会被持续盗用带宽。rtp2httpd 默认兼容 udpxy URL 格式,如果不加任何防护直接暴露,同样会被这些扫描器利用。 ## 安全配置 开放公网访问时,建议修改 `hostname` / `r2h-token` / `status-page-path` / `player-page-path` 以加强安全性。 ```ini [global] hostname = iptv.example.com r2h-token = my-secret-token-12345 status-page-path = /my-status-page player-page-path = /my-player ``` ## 前置反向代理 如有条件,建议前置 nginx / lucky / caddy 等反向代理负责转发,并开启 rtp2httpd 的 `xff` 选项 ```ini [global] xff = yes ``` 需要确保反向代理可以透传 `X-Forwarded-For` / `X-Forwarded-Host` / `X-Forwarded-Proto` 头。 对于 lucky,开启 `万事大吉` 选项即可。 对于 nginx,以下是一个配置示例: ```nginx server { listen 80; server_name iptv.example.com; location / { proxy_pass http://127.0.0.1:5140; proxy_http_version 1.1; # 透传客户端真实 IP 和协议信息 proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Proto $scheme; # 流媒体相关优化 proxy_buffering off; } } ``` ## 性能调优 建议修改内核参数,[开启 BBR](https://blog.clash-plus.com/post/openwrt-bbr/) 有助于在公网环境提高传输稳定性、降低起播延迟。 ## 跨运营商公网访问 > \[!NOTE] > 本节内容主要针对**中国大陆**的网络环境。其他国家和地区的 ISP 政策可能有所不同。 近年来中国大陆运营商大力整治 PCDN,对家庭宽带的上行带宽实施了越来越严格的限制。许多地区上行带宽虽然标称 30-50Mbps,但如果发生跨网上行(例如从中国移动上传到中国电信),会出现非常严格的上行限速(可能只有几 Mbps,不足以串流 4K 视频)。 此外,如果因为过往行为,被运营商判断为 PCDN 用户后,全部上行流量将会被送入流量清洗池,即使是同运营商,上行带宽也可能会被严格限制。 一条 1080p IPTV 流的码率通常在 6-10 Mbps,4K 流可达 30-40 Mbps。这意味着在 30Mbps 上行带宽下,可能只能同时支持 3-5 个 1080p 客户端,或仅 1 个 4K 客户端。 ### 带宽不足时的表现 当上行带宽不足以承载所有客户端的流量时,rtp2httpd 会出现以下现象: * **日志输出缓冲池扩容消息**:由于数据发送不出去,在内存中持续积累,rtp2httpd 会自动扩容缓冲池以尝试容纳更多待发送数据 * **状态页面显示慢客户端**:在 `/status` 页面可以看到部分客户端被标记为 `慢客户端`,表示其发送队列已积压 * **客户端缓冲池占满后丢包**:当某个客户端的缓冲积压达到上限,新到达的数据包会被丢弃,在观看端表现为频繁花屏、卡顿、重新加载 这些现象的根本原因是上行带宽受限,数据无法及时发送到客户端。 ## 相关文档 * [配置参数详解](../reference/configuration.md):完整配置选项说明 * [URL 格式说明](./url-formats.md):认证令牌传递方式 * [性能测试报告](../reference/benchmark.md):与其他方案的性能对比 --- --- url: /guide/web-player.md --- # 内置 Web 播放器 rtp2httpd 内置了一个基于 Web 的现代化播放器,可以直接在浏览器中观看已配置的 M3U 频道列表,无需安装任何客户端。 ## 访问方式 配置好 M3U 播放列表后,通过浏览器访问: ```url http://服务器地址:端口/player ``` **示例**: ```url http://192.168.1.1:5140/player ``` 播放器页面路径可以通过配置项 `player-page-path` 自定义。设置为 `/` 可以实现不带任何路径直接访问。 ## 功能特性 * **频道列表**:自动加载配置的 M3U 频道列表 * **在线直播**:在浏览器中直接观看直播 * **时移回看**:支持 EPG 电子节目单和时移回看(需要有回看源) * **快速起播**:搭配 FCC 可实现毫秒级换台速度 * **无缝换台**:换台时预加载新流,减少黑屏 * **响应式设计**:桌面和移动端 UI 自适应 * **PWA 支持**:可添加到手机、平板、桌面或 LG webOS 电视主屏幕,像原生应用一样快捷打开 * **零开销**:纯 Web 前端实现,对 rtp2httpd 运行几乎没有资源占用(无解码转码开销) > \[!IMPORTANT] > 播放器依赖浏览器的原生解码能力,部分编码格式(如 E-AC3)可能在某些浏览器中无法播放(表现为无音频、画面黑屏)。推荐使用最新版本的 Chrome、Edge 或 Safari。 ## PWA 支持与添加到主屏幕 内置 Web 播放器支持 PWA(Progressive Web App)。你可以将播放器页面添加到设备主屏幕(包括手机、平板、电脑,以及 LG webOS 智能电视),像打开原生应用一样一键进入,获得全屏、沉浸式的观看体验。 添加到主屏幕后,桌面图标名称默认为 **IPTV**,并会使用内置的应用图标。播放器会保留主题等本地设置。 ### iOS / iPadOS(Safari) 1. 在 Safari 中打开播放器页面(例如 `http://192.168.1.1:5140/player`) 2. 点击地址栏左侧扩展按钮中的 **分享** 3. 在分享菜单中下滑,选择 **添加到主屏幕** 4. 确认名称后点击 **添加** ### Android(Chrome、Edge 等) 1. 在浏览器中打开播放器页面 2. 点击浏览器右上角的 **菜单**(⋮) 3. 选择 **添加到主屏幕** 或 **安装应用** 4. 按提示确认安装 部分浏览器还会在地址栏或页面底部显示安装横幅,点击 **安装** 或 **添加** 即可完成。 ### 桌面端(Chrome、Edge) 1. 在浏览器中打开播放器页面 2. 点击地址栏右侧的 **安装** 图标(如有),或从浏览器菜单中选择 **投放、保存和分享** → **创建快捷方式** 3. 按提示确认 安装后,播放器会以独立窗口运行,可从系统应用列表或 Dock / 任务栏快速启动。 ### LG 电视(webOS) LG webOS 智能电视同样支持通过内置浏览器使用播放器,并将页面固定到电视桌面: 1. 在电视上打开 **Web Browser** 应用 2. 在地址栏输入播放器页面地址(例如 `http://192.168.1.1:5140/player`) 3. 打开浏览器菜单,选择 **添加到主屏幕**(Add shortcut to the Home screen) 4. 返回电视主界面,即可从桌面快捷方式启动播放器 > \[!NOTE] > 若通过 `player-page-path` 自定义了播放器路径,请使用实际路径访问后再添加到主屏幕。添加到主屏幕的快捷方式会固定指向添加时的 URL,包括其中的 `r2h-token` 等查询参数(如有)。 ## 频道聚合 当 M3U 中存在多个**同组同名**的频道时,播放器会自动将它们聚合为一个频道的多个源,在频道列表中只显示一次。用户可以通过线路选择器切换不同线路(如不同清晰度): ![频道源选择器](../images/channel-source-selector.png) 如果源 URL 带有 `$标签` 后缀,播放器会将其提取为源的显示标签(如「超高清」「高清」「标清」)。没有 `$标签` 的源则按序号显示(如「线路 1」「线路 2」)。 > \[!NOTE] > 频道聚合是 **内置 Web 播放器** 的前端功能,并非 rtp2httpd 服务端行为。第三方播放器(如 APTV、TiviMate 等)是否支持类似的聚合显示取决于其自身实现。rtp2httpd 服务端仅负责解析 `$标签`、生成独立的服务路径,以及在转换后的 M3U 中保留 `$标签`。 关于线路标签的 M3U 配置方式,详见 [M3U 播放列表集成](./m3u-integration.md#线路标签)。 ## 无缝换台 内置 Web 播放器默认开启 **无缝换台** 。换台或切换线路时,播放器会在后台预先加载新频道的视频流,待新流准备就绪后再切换画面,减少黑屏和等待时间,配合 [FCC 快速换台](./fcc-setup.md) 可获得更流畅的换台体验。 该功能通过双槽位预加载实现。由于在换台过程中短暂存在两路视频同时拉流的情况,如果你的带宽比较小(公网访问时),或是上游只支持单路组播,导致换台出现卡顿,可以手动关闭这个选项——在播放器页面右上角的 **设置**(齿轮图标)中关闭 **无缝换台** 即可。关闭后换台会先断开当前流再加载新流,占用带宽更低,但切换时可能出现短暂黑屏。 ## 时间占位符 内置 Web 播放器支持以下时间占位符格式,可在 M3U `catchup-source` URL 中使用: ### `${}` 格式(使用 long format) | 占位符 | 说明 | 示例输出 | | ----------------------------- | --------------------------------------- | ------------------------ | | `${utc}` | 节目开始时间(UTC,ISO8601 格式) | 2025-01-15T10:30:45.000Z | | `${utc:yyyyMMddHHmmss}` | 节目开始时间(UTC,自定义 long format) | 20250115103045 | | `${utcend}` | 节目结束时间(UTC,ISO8601 格式) | 2025-01-15T12:30:45.000Z | | `${utcend:yyyyMMddHHmmss}` | 节目结束时间(UTC,自定义 long format) | 20250115123045 | | `${start}` | 同 `${utc}` | 2025-01-15T10:30:45.000Z | | `${start:yyyyMMddHHmmss}` | 同 `${utc:yyyyMMddHHmmss}` | 20250115103045 | | `${end}` | 同 `${utcend}` | 2025-01-15T12:30:45.000Z | | `${end:yyyyMMddHHmmss}` | 同 `${utcend:yyyyMMddHHmmss}` | 20250115123045 | | `${lutc}` | 当前时间(UTC,ISO8601 格式) | 2025-01-15T14:00:00.000Z | | `${lutc:yyyyMMddHHmmss}` | 当前时间(UTC,自定义 long format) | 20250115140000 | | `${now}` | 同 `${lutc}` | 2025-01-15T14:00:00.000Z | | `${now:yyyyMMddHHmmss}` | 同 `${lutc:yyyyMMddHHmmss}` | 20250115140000 | | `${timestamp}` | 当前 Unix 时间戳(秒) | 1736949600 | | `${timestamp:yyyyMMddHHmmss}` | 同 `${lutc:yyyyMMddHHmmss}` | 20250115140000 | | `${(b)yyyyMMddHHmmss}` | 节目开始时间(本地时间,long format) | 20250115183045 | | `${(e)yyyyMMddHHmmss}` | 节目结束时间(本地时间,long format) | 20250115203045 | | `${(b)yyyyMMdd\|UTC}` | 节目开始时间(UTC,long format) | 20250115103045 | | `${(e)yyyyMMdd\|UTC}` | 节目结束时间(UTC,long format) | 20250115123045 | | `${(b)timestamp}` | 节目开始时间的 Unix 时间戳(秒) | 1736937045 | | `${(e)timestamp}` | 节目结束时间的 Unix 时间戳(秒) | 1736944245 | | `${yyyy}` | 节目开始时间:4 位年份(本地时间) | 2025 | | `${MM}` | 节目开始时间:月份 01-12(本地时间) | 01 | | `${dd}` | 节目开始时间:日期 01-31(本地时间) | 15 | | `${HH}` | 节目开始时间:小时 00-23(本地时间) | 18 | | `${mm}` | 节目开始时间:分钟 00-59(本地时间) | 30 | | `${ss}` | 节目开始时间:秒数 00-59(本地时间) | 45 | | `${duration}` | 节目时长(秒) | 7200 | | `${offset}` | 当前时间距节目开始的秒数 | 12600 | ### `{}` 格式(使用 short format) | 占位符 | 说明 | 示例输出 | | -------------------- | ---------------------------------------- | ------------------------ | | `{utc}` | 节目开始时间(UTC,ISO8601 格式) | 2025-01-15T10:30:45.000Z | | `{utc:YmdHMS}` | 节目开始时间(UTC,自定义 short format) | 20250115103045 | | `{utcend}` | 节目结束时间(UTC,ISO8601 格式) | 2025-01-15T12:30:45.000Z | | `{utcend:YmdHMS}` | 节目结束时间(UTC,自定义 short format) | 20250115123045 | | `{start}` | 同 `{utc}` | 2025-01-15T10:30:45.000Z | | `{start:YmdHMS}` | 同 `{utc:YmdHMS}` | 20250115103045 | | `{end}` | 同 `{utcend}` | 2025-01-15T12:30:45.000Z | | `{end:YmdHMS}` | 同 `{utcend:YmdHMS}` | 20250115123045 | | `{lutc}` | 当前时间(UTC,ISO8601 格式) | 2025-01-15T14:00:00.000Z | | `{lutc:YmdHMS}` | 当前时间(UTC,自定义 short format) | 20250115140000 | | `{now}` | 同 `{lutc}` | 2025-01-15T14:00:00.000Z | | `{now:YmdHMS}` | 同 `{lutc:YmdHMS}` | 20250115140000 | | `{timestamp}` | 当前 Unix 时间戳(秒) | 1736949600 | | `{timestamp:YmdHMS}` | 同 `{lutc:YmdHMS}` | 20250115140000 | | `{(b)YmdHMS}` | 节目开始时间(本地时间,short format) | 20250115183045 | | `{(e)YmdHMS}` | 节目结束时间(本地时间,short format) | 20250115203045 | | `{(b)YmdHMS\|UTC}` | 节目开始时间(UTC,short format) | 20250115103045 | | `{(e)YmdHMS\|UTC}` | 节目结束时间(UTC,short format) | 20250115123045 | | `{(b)timestamp}` | 节目开始时间的 Unix 时间戳(秒) | 1736937045 | | `{(e)timestamp}` | 节目结束时间的 Unix 时间戳(秒) | 1736944245 | | `{Y}` | 节目开始时间:4 位年份(本地时间) | 2025 | | `{m}` | 节目开始时间:月份 01-12(本地时间) | 01 | | `{d}` | 节目开始时间:日期 01-31(本地时间) | 15 | | `{H}` | 节目开始时间:小时 00-23(本地时间) | 18 | | `{M}` | 节目开始时间:分钟 00-59(本地时间) | 30 | | `{S}` | 节目开始时间:秒数 00-59(本地时间) | 45 | | `{duration}` | 节目时长(秒) | 7200 | | `{offset}` | 当前时间距节目开始的秒数 | 12600 | ### 格式说明 **Long Format(长格式)**:用于 `${}` 括号中的自定义格式 * `yyyy` - 4 位年份 * `MM` - 2 位月份(01-12) * `dd` - 2 位日期(01-31) * `HH` - 2 位小时(00-23) * `mm` - 2 位分钟(00-59) * `ss` - 2 位秒数(00-59) 示例:`${utc:yyyyMMddHHmmss}` → `20250115103045` **Short Format(短格式)**:用于 `{}` 括号中的自定义格式 * `Y` - 4 位年份 * `m` - 2 位月份(01-12) * `d` - 2 位日期(01-31) * `H` - 2 位小时(00-23) * `M` - 2 位分钟(00-59) * `S` - 2 位秒数(00-59) 示例:`{utc:YmdHMS}` → `20250115103045` ## 相关文档 * [M3U 播放列表集成](./m3u-integration.md):M3U 配置和线路标签 * [FCC 快速换台配置](./fcc-setup.md):启用毫秒级换台功能 * [配置参数详解](../reference/configuration.md):播放器相关配置参数 --- --- url: /reference/cn-fcc-collection.md --- # 各地 FCC 地址汇总 以下是从互联网收集的中国各地区 FCC 服务器,不保证可用,如有不可用请到 讨论反馈。 > \[!TIP] > > 1. 如果没有列出本城市 IP,可以尝试临近城市或省会的 IP。 > 2. 有些地区 FCC IP 和 RTSP 单播源的 IP 是一样的,只是端口不一样。如果你能找到当地 RTSP 单播地址,可以把端口换成 8027 或 15970 作为 FCC 地址试试看。 > 3. 可以根据 rtp2httpd 的日志判断 FCC 是否生效。 > * 出现 `FCC: Unicast stream started successfully` 表示 FCC 地址有效,并且成功收到单播流。 > * 出现 `FCC: Server response timeout (80 ms), falling back to multicast` 有两种可能 > 1. FCC 地址无效。 > 2. 你的网络配置不正确,导致无法连接到 FCC 服务器。一般来说必须通过 DHCP/IPoE/PPPoE 获得 IPTV 内网 IP 后,并启用 rtp2httpd `--upstream-interface-fcc` 或 `--upstream-interface` 选项指定 IPTV 接口后,才能访问 FCC。请结合 ping / traceroute 等工具判断。 > 4. 在一些地区,不同的组播地址需要使用不同的 FCC IP,也可能存在一些组播频道未启用 FCC 的情况。 > 5. 有些地区同一运营商内同时存在中兴、华为、烽火等多个 IPTV 平台,可能也会有不同的 FCC 地址,因此可能会出现同地区 A 网友可用,B 网友不可用,因为属于不同的 IPTV 平台。 > * 通常 8027 端口是华为平台,15970 端口是中兴/烽火平台 ## 海南 * 电信:`10.255.75.73:15970` ## 江苏 * 电信: * `180.100.72.185:15970` * `180.100.106.54:554` ## 浙江 * 电信: * `115.233.40.137:8027`(杭州) * `115.233.41.137:8027`(杭州) * `220.186.210.205:8027`(温州) * `220.186.213.242:8027`(温州) * `220.186.213.247:8027`(温州) * `220.186.213.249:8027`(温州) * `220.186.213.250:8027`(温州) * `115.233.43.70:8027`(金华) * `220.191.136.24:8027`(台州) * `115.233.42.69:8027`(绍兴) * `202.101.181.109:8027`(衢州) * `115.208.248.108:8027`(湖州) ## 上海 * 电信: * `124.75.26.151:15970` * `124.75.25.211:7777` * `124.75.25.214:7777` * `124.75.25.212:7777` * `124.75.25.215:7777` * `124.75.25.216:7777` * 联通:`10.223.3.189:8027` ## 天津 * 电信:`10.255.4.140:8027` * 移动:`10.206.255.108:8027` ## 湖南 * 电信: * `10.255.168.4:15970` * `124.232.149.47:15970` * `61.150.161.42:8027` * `222.241.55.41:8027`(常德) * `218.76.213.41:8027`(邵阳) * 移动:`100.127.255.233:15970` ## 湖北 * 电信:`121.60.255.120:15970` ## 河南 * 联通: * `10.254.185.70:15970` * `10.254.192.94:8027` * `10.254.199.130:8027`(郑州) * `10.254.223.130:8027`(驻马店) ## 河北 * 电信: * `192.168.19.28:8027` * `192.168.30.150:8027`(唐山) * `192.168.72.20:8027`(保定) * 联通: * `10.7.50.172:8027`(唐山) * `10.7.35.172:8027`(秦皇岛) * `10.7.10.172:8027`(石家庄) ## 山东 * 电信:`150.138.8.132:8027`(青岛) * 联通: * `124.132.240.66:15970` * `61.156.103.83:8027`(青岛) * `119.184.120.108:8027`(日照) * `60.210.139.78:8027`(潍坊) ## 山西 * 电信:`10.56.17.68:8027` * 联通:`10.112.7.159:8027` ## 陕西 * 电信: * `113.136.29.140:8027`(西安) * `113.136.242.134:8027`(西安) ## 广东 * 电信: * `183.59.156.166:8027`(广州) * `183.59.160.61:8027`(深圳) * `183.59.168.166:8027`(东莞) * `183.59.144.166:8027`(佛山) ## 广西 * 电信: * `180.141.207.228:8027` * `180.141.206.228:8027` * `113.15.79.82:8027` * `171.104.238.90:8027`(柳州) * `10.255.136.86:8027`(柳州) * `10.255.165.82:8027`(防城港) * `124.226.158.81:8027`(贺州、梧州) ## 四川 * 电信: * `182.139.234.40:8027`(成都) * `182.139.229.78:8027`(成都) * `220.167.81.247:8027`(成都) * `118.123.55.74:8027`(成都) * `118.119.188.42:8027`(峨眉山) * `118.119.178.42:8027`(乐山) * `182.128.24.170:8027`(广元) * `182.134.43.42:8027`(宜宾) * 移动:`183.223.164.65:8027` ## 重庆 * 电信: * `172.23.35.216:15970`(永川) * `172.23.2.138:8027`(大足) * 联通:`123.147.117.148:15970` * 移动:`172.16.4.155:8027` ## 贵州 * 电信: * `10.255.133.132:15970` * `10.255.5.32:8027` * 移动:`117.187.29.36:15970`(黔南) ## 安徽 * 电信:`117.71.18.200:15970` ## 辽宁 * 电信: * `10.255.128.136:8027`(沈阳) * `10.255.132.132:15970`(沈阳) * 联通:`218.24.21.133:15970` ## 吉林 * 移动:`111.26.238.155:8027` ## 甘肃 * 电信:`125.76.62.60:8027` ## 青海 * 电信: * `125.72.115.252:158` * `125.72.108.212:15970`(西宁) --- --- url: /guide/installation.md --- # 安装方式 rtp2httpd 支持多种安装方式,适应不同的使用场景。 ## OpenWrt 路由器部署 OpenWrt 是 rtp2httpd 的最佳运行环境。在中国大陆,通常需要先完成 IPTV 网络融合(可以搜索教程 `OpenWrt IPTV 融合`),通过 DHCP 获取到 IPTV 内网 IP,才能访问运营商的 IPTV 组播网络。 详见 [快速上手](./quick-start.md)。 ## 静态二进制文件部署 从 [Releases](https://github.com/stackia/rtp2httpd/releases) 页面下载对应架构的静态二进制文件 `rtp2httpd-<版本号>-<架构>`,上传到设备并 `chmod +x` 后即可运行。 默认从 `/etc/rtp2httpd.conf` 读取配置文件。可用 `--config` 或 `--noconfig` 参数覆盖。 **示例**: ```bash # 获取自己的 CPU 架构 uname -m # 下载二进制文件 wget https://github.com/stackia/rtp2httpd/releases/download/vX.Y.Z/rtp2httpd-X.Y.Z-x86_64 chmod +x rtp2httpd-X.Y.Z-x86_64 # 使用配置文件运行 ./rtp2httpd-X.Y.Z-x86_64 --config /path/to/rtp2httpd.conf # 仅使用命令行参数运行 ./rtp2httpd-X.Y.Z-x86_64 --noconfig --verbose 2 --listen 5140 --maxclients 20 ``` > \[!TIP] > 你可以使用这个示例文件 [rtp2httpd.conf](https://github.com/stackia/rtp2httpd/blob/main/rtp2httpd.conf) 作为基础来修改配置。具体说明见 [配置参数详解](../reference/configuration.md)。 ## Docker 容器部署 适用于支持 Docker 的设备。**需要使用 host 网络模式**以正确接收组播流。 ### 基本启动方式 ```bash docker run --network=host --cap-add=NET_ADMIN --ulimit memlock=-1:-1 --rm \ ghcr.io/stackia/rtp2httpd:latest \ --noconfig --verbose 2 --listen 5140 --maxclients 20 ``` ### 使用 docker-compose ```yaml services: rtp2httpd: image: ghcr.io/stackia/rtp2httpd:latest network_mode: host restart: always cap_add: - NET_ADMIN ulimits: memlock: soft: -1 hard: -1 command: --noconfig --verbose 2 --listen 5140 --maxclients 20 ``` > \[!NOTE] > **关于推荐参数**: > > * `cap_add: NET_ADMIN`:允许通过 `SO_RCVBUFFORCE` 绕过内核参数 `net.core.rmem_max` 限制,设置更大的 UDP 接收缓冲区 > * `ulimits: memlock: -1`:启用零拷贝(`--zerocopy-on-send`)时必需,MSG\_ZEROCOPY 需要锁定内存页 ### 挂载配置文件 如果需要使用配置文件(假设配置文件位于 `/path/to/rtp2httpd.conf`): ```bash docker run --network=host --cap-add=NET_ADMIN --ulimit memlock=-1:-1 --rm \ -v /path/to/rtp2httpd.conf:/usr/local/etc/rtp2httpd.conf:ro \ ghcr.io/stackia/rtp2httpd:latest ``` > \[!TIP] > 你可以使用这个示例文件 [rtp2httpd.conf](https://github.com/stackia/rtp2httpd/blob/main/rtp2httpd.conf) 作为基础来修改配置。具体说明见 [配置参数详解](../reference/configuration.md)。 ## OpenWrt 编译安装 如果你希望通过 OpenWrt 源码构建直接把 rtp2httpd 编译到固件里,可以把本仓库直接加入 `feeds.conf.default`: ```text # 使用 main 分支最新代码 src-git rtp2httpd https://github.com/stackia/rtp2httpd.git ``` 或者指定版本号: ```text # 使用 v3.10.1 版本代码 src-git rtp2httpd https://github.com/stackia/rtp2httpd.git;v3.10.1 ``` 运行 `./scripts/feeds update rtp2httpd` 和 `./scripts/feeds install rtp2httpd` 更新 feed。 运行 `make menuconfig`,找到 `LuCI -> Applications -> luci-app-rtp2httpd`,将其勾选为 `*` (编译到固件) 或 `M` (编译成 ipk/apk 包),保存退出。 运行 `make package/feeds/rtp2httpd/luci-app-rtp2httpd/compile -j1 V=sc` 可单独编译 `luci-app-rtp2httpd` 和 `rtp2httpd` 两个包。 ### 固件维护者集成指南 如果你维护第三方 OpenWrt 固件,希望直接将 rtp2httpd 集成到你的 feeds 仓库中(而非通过 `src-git` 引用),可以使用本项目提供的 `Makefile.versioned`: ```bash git clone https://github.com/stackia/rtp2httpd.git cd rtp2httpd # 用预生成的 Makefile 替换原始 Makefile(已包含固定版本号、源码下载地址和 PKG_HASH) mv openwrt-support/rtp2httpd/Makefile.versioned openwrt-support/rtp2httpd/Makefile mv openwrt-support/luci-app-rtp2httpd/Makefile.versioned openwrt-support/luci-app-rtp2httpd/Makefile # 将 openwrt-support 目录内容复制到你的 feeds 仓库 cp -r openwrt-support/* /path/to/your/feeds/ ``` `Makefile.versioned` 与原始 `Makefile` 的区别在于:版本号已固定、`PKG_HASH` 已填充、构建时会从 GitHub Release 下载源码包,无需本地 git 仓库。每次 rtp2httpd 发布新版本时,main 分支 `Makefile.versioned` 都会自动更新。 ## 传统编译安装 适用于需要自定义编译或开发调试的场景。 ### 安装依赖 ```bash # Ubuntu/Debian sudo apt-get install build-essential cmake pkg-config curl # 安装 Node.js LTS(用于构建 Web UI) curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash - sudo apt-get install -y nodejs corepack enable ``` ### 编译步骤 ```bash # 克隆仓库 git clone https://github.com/stackia/rtp2httpd.git cd rtp2httpd # 构建 Web UI 并嵌入静态资源 pnpm install --frozen-lockfile pnpm run web-ui:build # 配置和编译 cmake -B build -DCMAKE_BUILD_TYPE=Release -DENABLE_AGGRESSIVE_OPT=ON cmake --build build -j$(getconf _NPROCESSORS_ONLN) # 安装 sudo cmake --install build ``` ## 下一步 * [快速上手](./quick-start.md):OpenWrt 快速配置指南 * [配置参数详解](../reference/configuration.md):了解所有配置选项 * [URL 格式说明](./url-formats.md):了解所有支持的 URL 格式 * [M3U 播放列表集成](./m3u-integration.md):配置播放列表 * [FCC 快速换台配置](./fcc-setup.md):启用毫秒级换台功能 --- --- url: /guide/quick-start.md --- # 快速上手 ## OpenWrt 一键安装/更新(推荐) 运行以下命令,自动下载并安装最新版本: ```bash uclient-fetch -q -O - https://raw.githubusercontent.com/stackia/rtp2httpd/main/scripts/install-openwrt.sh | sh ``` 脚本会自动: * 检测设备的 CPU 架构 * 从 GitHub Release 获取最新版本 * 下载并安装所有必需的软件包(主程序 + LuCI 界面 + 语言包) * 如果此前已经安装过,运行此脚本,将会卸载旧版,重新安装最新版 > \[!TIP] > 如果无法使用一键脚本,可以手动在 [Releases](https://github.com/stackia/rtp2httpd/releases) 页面下载对应架构的软件包: > > * `rtp2httpd_<版本号>_<架构>.ipk` - 主程序包 > * `luci-app-rtp2httpd_<版本号>_all.ipk` - LuCI Web 界面 > * `luci-i18n-rtp2httpd-zh-cn_<版本号>_all.ipk` - 中文语言包 > > ```bash > # 如果不知道自己的架构,可以用这条命令获取架构 > cat /etc/openwrt_release | grep ARCH > > # 手动将 ipk 上传至设备并安装 > opkg install rtp2httpd_*.ipk luci-app-rtp2httpd_*.ipk luci-i18n-rtp2httpd-*.ipk > ``` ## 基本配置 安装完成后,在 LuCI 管理界面的 "服务" 菜单中找到 "rtp2httpd" 进行配置: ![LuCI 配置界面](../images/luci-config.png) > \[!WARNING] > 每次更新版本后如果 LuCI 出现工作异常,需要 **Ctrl+F5 刷新** 或 **清空浏览器缓存** 或 **使用无痕模式访问** 解决。 > \[!IMPORTANT] > 如果安装后,LuCI 未出现 rtp2httpd 入口,说明你的 LuCI 版本过低,无法支持 JS-based LuCI 插件。请考虑更新固件,或者手动编辑和维护 `/etc/config/rtp2httpd`(需要将 disabled 设为 0),使用 `/etc/init.d/rtp2httpd restart` 重启服务。 > > 有一些热心网友开发了 Lua 版本 luci-app-rtp2httpd,在这种情况下可以尝试使用(非 rtp2httpd 官方维护) > > * > * ### 必需配置项 1. **基本设置 - 启用**:勾选启用 rtp2httpd 2. **基本设置 - 端口**:默认 5140,也可以自定义 3. **网络与性能 - 上游接口**:设置为 IPTV 网络接口 ### 可选配置项 * **播放器与 M3U - 外部 M3U**:如有现成的 M3U 播放列表,填入此设置项后后即可使用 [内置 Web 播放器](./web-player.md)([M3U 播放列表集成](./m3u-integration.md)) * **FCC 服务器**:如需快速换台,需要在节目 URL 带上 FCC 服务器地址([FCC 快速换台配置](./fcc-setup.md)) ## 测试访问 配置完成后,可以通过以下 URL 测试访问: ```bash # 访问 RTP 组播流 http://路由器IP:5140/rtp/239.253.64.120:5140 # 访问状态页面 http://路由器IP:5140/status # 获取 M3U 播放列表(如已配置) http://路由器IP:5140/playlist.m3u ``` ## 使用内置播放器 如果已配置 M3U 播放列表,可直接在浏览器中访问 `http://路由器IP:5140/player` 打开 [内置 Web 播放器](./web-player.md)。 ## 在其他播放器中使用 将 `http://路由器IP:5140/playlist.m3u` 添加到支持 IPTV 的播放器中即可观看。 ## 查看日志 有三种方式可以查看运行日志: 1. 访问状态页面 `/status`,页面底部查看日志 2. 在 OpenWrt 后台,"状态" -> "系统日志" 查看日志 3. SSH 连接路由器后运行 `logread -e rtp2httpd` ## 下一步 * [内置 Web 播放器](./web-player.md):播放器功能、兼容性说明 * [安装方式](./installation.md):了解其他安装方式(Docker、静态二进制、编译安装) * [M3U 播放列表集成](./m3u-integration.md):配置播放列表自动识别和转换 * [URL 格式说明](./url-formats.md):了解所有支持的 URL 格式 * [配置参数详解](../reference/configuration.md):深入了解所有配置选项 * [FCC 快速换台配置](./fcc-setup.md):启用毫秒级换台功能 --- --- url: /reference/benchmark.md --- # 性能测试报告 **rtp2httpd**、**[msd\_lite](https://github.com/rozhuk-im/msd_lite)**、**[udpxy](https://github.com/pcherenkov/udpxy)** 和 **[tvgate](https://github.com/qist/tvgate)** 四款组播转单播程序性能对比。 ## 测试环境 * **平台**: Ubuntu 24.04 on Apple M3 Max (Parallels Desktop 虚拟机) * **架构**: aarch64 (所有程序均为本机编译的原生 arm64 二进制文件) * **内核**: Linux 6.8.0-90-generic * **单项测试时长**: 10 秒 * **测量方法**: * CPU: 使用 `top -b -n 2` 进行采样 * 内存: 从 `/proc/[pid]/smaps_rollup` 读取 USS (Unique Set Size) * 如果存在 fork 后的子进程,所有父子进程的 CPU、内存分别求和作为总结果 * **测试版本**: * rtp2httpd: v3.8.3 * msd\_lite: commit 79a6c62 (2025-05-02) * udpxy: commit 56fc563 (2026-01-26) * tvgate: v2.1.8 ## 测试场景 | 测试 | 描述 | | -------------- | ----------------------------------------------------------------------- | | **多流测试** | 8 个客户端,每个请求不同的组播地址,单流约 40 Mbps(模拟 4K IPTV 码率) | | **单流测试** | 8 个客户端,全部请求相同的组播地址,单流约 40 Mbps | | **高带宽测试** | 1 个客户端,单流约 400 Mbps | ## 测试结果汇总 ### CPU 使用率 (%) | 测试场景 | rtp2httpd | msd\_lite | udpxy | tvgate | | ------------------ | ------------- | -------- | ------- | ------- | | 多流 (8个不同地址) | 🏆 **17.00%** | 25.80% | 106.00% | 331.00% | | 单流 (8个相同地址) | 🏆 **14.00%** | 14.20% | 85.00% | 51.45% | | 高带宽 (400 Mbps) | 🏆 **26.73%** | 39.50% | 30.85% | 89.53% | ### 内存使用 (MB) | 测试场景 | rtp2httpd | msd\_lite | udpxy | tvgate | | ------------------ | ----------- | ----------- | ----- | ------ | | 多流 (8个不同地址) | 🏆 **4.50** | 10.25 | 12.53 | 182.00 | | 单流 (8个相同地址) | 4.88 | 🏆 **2.62** | 12.53 | 33.25 | | 高带宽 (400 Mbps) | 3.88 | 🏆 **2.62** | 3.21 | 47.38 | ## 详细测试结果 ### 测试一:多流场景 (8个客户端,不同地址,约 40 Mbps) 每个客户端请求不同的组播地址 (239.81.0.1-8),测试服务器处理多个独立流的能力。 | 指标 | rtp2httpd | msd\_lite | udpxy | tvgate | | -------- | -------------- | -------- | -------- | --------- | | CPU 平均 | 🏆 **17.00%** | 25.80% | 106.00% | 331.00% | | CPU 峰值 | 🏆 **18.00%** | 30.00% | 116.00% | 332.00% | | 内存平均 | 🏆 **4.50 MB** | 10.25 MB | 12.53 MB | 182.00 MB | ### 测试二:单流场景 (8个客户端,相同地址,约 40 Mbps) 8个客户端全部请求相同的组播地址,测试服务器的组播复用效率。 | 指标 | rtp2httpd | msd\_lite | udpxy | tvgate | | -------- | ------------- | -------------- | -------- | -------- | | CPU 平均 | 🏆 **14.00%** | 14.20% | 85.00% | 51.45% | | CPU 峰值 | 18.00% | 🏆 **15.00%** | 108.00% | 52.90% | | 内存平均 | 4.88 MB | 🏆 **2.62 MB** | 12.53 MB | 33.25 MB | ### 测试三:高带宽场景 (1个客户端,约 400 Mbps) 单客户端接收高带宽流 (50倍速回放 ≈ 400 Mbps)。 | 指标 | rtp2httpd | msd\_lite | udpxy | tvgate | | -------- | ------------- | -------------- | ------- | -------- | | CPU 平均 | 🏆 **26.73%** | 39.50% | 30.85% | 89.53% | | CPU 峰值 | 🏆 **29.40%** | 40.00% | 46.00% | 96.00% | | 内存平均 | 3.88 MB | 🏆 **2.62 MB** | 3.21 MB | 47.38 MB | ## 测试结论 **rtp2httpd** 在基准测试中展现出优异的综合性能: * **CPU 效率最高**:在所有三个测试场景中均取得最低 CPU 使用率,多流场景下仅为 msd\_lite 的 66%、udpxy 的 16%、tvgate 的 5% * **多流处理能力突出**:同时处理 8 个独立 4K 组播流时,CPU 和内存占用均为最低,适合多频道 IPTV 网关场景 * **高带宽场景表现稳定**:400 Mbps 高码率下 CPU 占用仅 27%,留有充足的性能余量 * **内存占用合理**:约 4 MB 的内存占用(全默认参数下),在各场景下保持稳定,适合资源受限的嵌入式设备 相比 udpxy 的 fork-per-client 模型,rtp2httpd 采用更高效的事件驱动架构,在高并发场景下优势明显。相比 msd\_lite,rtp2httpd 在 CPU 效率上更胜一筹,尤其在多流并发场景下差距显著。 ## 运行基准测试 详见 [tools/stress-test/README.md](https://github.com/stackia/rtp2httpd/blob/main/tools/stress-test/README.md) 了解压力测试工具和方法。 单次压力测试: ```bash uv run python tools/stress-test/stress_test.py --program rtp2httpd --duration 10 --clients 8 --speed 5 ``` 完整基准测试: ```bash scripts/benchmark.sh ``` 测试结果保存至 `tools/stress-test/benchmark_results_YYYYMMDD_HHMMSS.txt`。 --- --- url: /guide/time-processing.md --- # 时间处理说明 本文档说明 rtp2httpd 如何处理「时移回看」(catchup)请求里的时间和时区。RTSP 和 HTTP 代理都适用,但 **Range Seek 模式** 是 RTSP 专属的。 ## 时移回看的两种模式 IPTV 上游服务器通常支持「时移回看」——回放过去时段的直播内容。客户端通过在 URL 中加上时间范围参数(最常见的是 `playseek`、`tvdr`)告诉服务器要看哪一段: ``` http://192.168.1.1:5140/rtsp/iptv.example.com:554/channel1?playseek=20240101120000-20240101130000 ``` rtp2httpd 在向上游转发时支持两种处理方式: ### 模式 1:Playseek 透传(默认) 把客户端的 seek 参数原样作为 URL 查询转发给上游服务器(必要时按时区做格式调整)。 **适用范围**:HTTP 代理 + RTSP 代理,所有支持时移的运营商都能用。 **局限**:上游会按客户端给的「结束时间」播完后关闭流。如果想把后续的实时直播无缝拼上,客户端必须**再发起一次新请求**——中间会有几百毫秒到几秒的间断,可能造成播放卡顿或音视频不同步。 ### 模式 2:RTSP Range Seek(可选,需显式启用) 利用 RTSP 协议自带的 `Range: clock=...` 头让上游从指定时间开始播放,**并在追到当前时间时自动无缝拼到实时直播流**——全程一次连接、无需重连。 启用方式:在 URL 里加 `r2h-seek-mode=range(...)`: ``` http://192.168.1.1:5140/rtsp/iptv.example.com:554/channel1?playseek=20240101120000&r2h-seek-mode=range(UTC%2B8) ``` **优势**:从时移段过渡到直播实时段是一次连续播放,无间断。 **限制**: 1. **不是所有 RTSP 服务器都支持**——这是默认关闭、需要显式启用的根本原因。一旦命中 Range Seek 路径,rtp2httpd 会无条件向上游发送 `Range: clock=...` 头;上游如果不识别,请求会失败而不是自动回退 2. **rtp2httpd 自身有客户端窗口**(默认 1 小时,可通过 `r2h-seek-mode=range(/<秒>)` 调整):仅当起始时间落在窗口内才走 Range Seek,否则按 Playseek 透传处理。把窗口配置得不超过上游服务器实际支持的范围(通常 1–3 小时,因运营商而异),可避免命中上游不支持的过老回看请求 > \[!TIP] > 在 rtp2httpd 客户端窗口外,行为与从未启用 Range Seek **完全一致**(按 Playseek 透传)。窗口内则会发起带 `Range: clock=` 头的 RTSP 请求——只有在确认上游支持 RTSP `Range` 头时才建议启用,并把窗口设置得不超过上游实际支持的回看长度。 > \[!NOTE] > Range Seek 模式只看 seek 的**起始时间**——结束时间被忽略,由实时拼接接管。 ## Seek 参数 ### r2h-seek-name(可选) 指定时移参数的名称。不指定时按以下顺序自动识别:`playseek` → `tvdr`(不区分大小写)。 如果上游使用别的参数名(如 `seek`、`timeshift`),显式指定: ``` ?custom_seek=20240101120000-20240101130000&r2h-seek-name=custom_seek ``` ### r2h-seek-offset(可选) 对识别出的时移时间额外加 / 减若干秒,可正可负。传单个整数时同时作用于起始和结束时间;传 `a,b` 时分别作用于起始时间和结束时间。常用于补偿上游服务器的时钟偏差,或让起播/结束边界分别提前、延后。 ``` # playseek 范围整体后移 1 小时(3600 秒) ?playseek=20240101120000-20240101130000&r2h-seek-offset=3600 # 起始时间后移 12 秒,结束时间提前 12 秒 ?playseek=20240101120000-20240101130000&r2h-seek-offset=12,-12 # 提前 30 秒 ?playseek=20240101120000&r2h-seek-offset=-30 ``` > \[!IMPORTANT] > `r2h-seek-offset` 是「人为时间平移」,不是时区修正。它**总是**叠加到最终结果上,即使输入时间已经自带时区(如 ISO 8601 `Z` 后缀、`yyyyMMddHHmmssGMT`),仍然生效。 > > 在 Range Seek 模式下,offset 也会进入窗口判定——offset 后的起始时间一旦落出窗口,同样回退为透传。使用 `a,b` 形式时,Range Seek 只使用起始时间,因此只有 `a` 会影响窗口判定和 `Range: clock=` 头。 ### r2h-seek-mode(可选,仅 RTSP) 控制是否启用「Range Seek 模式」(参见上方[两种模式说明](#时移回看的两种模式))。 | 取值 | 行为 | | ---------------------------------------------- | ------------------------------------------------------------- | | 不传 / `passthrough` | 默认。使用 Playseek 透传 | | `range` / `range()` | 启用 Range Seek,时区从 UA `TZ/` 推导(无则 UTC),窗口默认 1 小时 | | `range(UTC+8)` / `range(UTC-5)` / `range(UTC)` | 显式指定时区,窗口默认 1 小时 | | `range(7200)` | 自动推导时区,窗口 7200 秒 | | `range(UTC+8/7200)` | 同时显式指定时区与窗口 | | `range(/7200)` | 自动推导时区 + 显式窗口 | 窗口取值范围 1–86400 秒。无法识别的值会按 `passthrough` 处理(不会让请求失败)。 > \[!IMPORTANT] > `range()` 里指定的时区**只在 Range Seek 模式中生效**——用来判断时间是否在窗口内、以及生成 `Range: clock=` 头里的 UTC 时间。一旦回退到 Playseek 透传,行为与不传 `r2h-seek-mode` 时**字节级完全相同**,`range()` 不会去改写透传字符串。 ### r2h-start(可选,仅 RTSP) 从指定的 NPT 时间点(秒)开始播放,常用于续播: ``` ?r2h-start=123.45 ``` 在 RTSP `PLAY` 请求中以 `Range: npt=<时间>-` 头发送给上游。如果同一请求又带了 `r2h-seek-mode=range(...)` 且命中 Range Seek 模式,`r2h-start` 会被忽略,由 seek 起始时间生成 `Range: clock=` 头。 ## 支持的时间格式 rtp2httpd 能识别下面的时间格式。**输出格式始终与输入保持一致**(保留 `Z`、`±HH:MM`、`GMT` 等后缀)。 | 格式 | 示例 | 是否自带时区 | | ----------------------------------- | ----------------------------- | ---------------- | | Unix 时间戳(≤10 位数字) | `1704096000` | 是(UTC) | | 14 位 `yyyyMMddHHmmss` | `20240101120000` | 否 | | 14 位 + `GMT` 后缀 | `20240101120000GMT` | 是(UTC) | | 紧凑 ISO 8601 | `20240101T120000` | 否 | | 紧凑 ISO 8601 + `Z` | `20240101T120000Z` | 是(UTC) | | 紧凑 ISO 8601 + `±HH:MM` | `20240101T200000+08:00` | 是 | | 完整 ISO 8601 | `2024-01-01T12:00:00` | 否 | | 完整 ISO 8601 + `Z` / `±HH:MM` | `2024-01-01T12:00:00Z` | 是 | | 完整 ISO 8601 + 毫秒 | `2024-01-01T12:00:00.123Z` | 视后缀而定 | 「自带时区」的格式 rtp2httpd 不会再去推导时区——任何外部时区配置(UA `TZ/...`、`r2h-seek-mode=range()`)都被忽略,但 `r2h-seek-offset` 仍然会叠加。「不自带时区」的格式按下文「时区推导」处理。 > \[!NOTE] > `yyyyMMddHHmmssGMT` 的 `GMT` 后缀语义与 ISO 8601 的 `Z` 等价——都视为「自带 UTC 时区」。 ## 时区推导 仅适用于「不自带时区」的格式(14 位 `yyyyMMddHHmmss`、不带 `Z`/`±HH:MM` 的 ISO 8601)。 ### 默认(Playseek 透传) rtp2httpd 从 User-Agent 头里查找 `TZ/` 标记获取客户端时区: ``` TZ/UTC → UTC TZ/UTC+8 → 东八区 TZ/UTC-5 → 西五区 ``` UA 里没有 `TZ/` 标记时,按 UTC 处理(不做时区转换)。 ### Range Seek 模式 启用 `r2h-seek-mode=range(...)` 时,**仅 Range Seek 路径**按下面的优先级取时区: 1. `range(UTC+N)` 显式声明 2. UA `TZ/UTC+N` 3. UTC 回退到 Playseek 透传时,时区推导回到上面「默认」一节的规则——`range()` 里的时区不参与。 ## 相关文档 * [URL 格式说明](./url-formats.md):RTSP / HTTP 代理 URL 格式说明 * [配置参数详解](../reference/configuration.md):服务器配置选项 --- --- url: /reference/related-resources.md --- # 相关教程和软件 本页汇总了社区提供的 IPTV 搭建教程、配套工具和播放器软件,方便用户快速找到所需资源。 > \[!NOTE] > 以下资源均由社区用户贡献和维护,不属于 rtp2httpd 项目本身。如有问题请联系对应项目的维护者。 ## IPTV 搭建教程 如果是首次搭建 IPTV 组播转发服务,对相关网络知识比较陌生(DHCP 鉴权、路由、组播、防火墙),可以参考以下教程: * [浙江杭州电信 IPTV 内网融合教程:在局域网任意设备观看 IPTV](https://baiyun.me/zhejiang-hangzhou-telecom-iptv) * [自动抓取IPTV单播地址,实现时移回看](https://www.bandwh.com/net/2571.html) * [K2P 利用 rtp2httpd 刷 openwrt 单线复用双网融合完美解决看 IPTV 超简单详细](https://www.right.com.cn/forum/forum.php?mod=viewthread\&tid=8457970\&fromuid=402348) * [重庆电信 IPTV 内网融合 抓包 rtp2httpd](https://www.right.com.cn/forum/forum.php?mod=viewthread\&tid=8457356\&fromuid=402348) * [浙江 电信 IPTV 组播 转单播 rtp2httpd 去花屏](https://www.right.com.cn/forum/forum.php?mod=viewthread\&tid=8452510\&fromuid=402348) * [使用 Rtp2httpd 酷 9 浙江 电信 IPTV 单播 回看](https://www.right.com.cn/forum/forum.php?mod=viewthread\&tid=8453715\&fromuid=402348) * [上海电信 猫棒/光猫桥接 OpenWrt下实现 Internet+IPTV盒子+udpxy/rtp2httpd+VoIP](https://www.right.com.cn/forum/forum.php?mod=viewthread\&tid=8268077\&fromuid=402348) * [上海电信 SDN光猫桥接 华硕路由器 单线复用 梅林固件 rtp2httpd 开启FCC 功能](https://www.right.com.cn/forum/forum.php?mod=viewthread\&tid=8467200\&fromuid=402348) * [爱快主路由+rtp2httpd(运行在内网设备)开启FCC](https://www.right.com.cn/forum/forum.php?mod=viewthread\&tid=8469614\&fromuid=402348) * [成都 电信IPTV 组播转换单播 openwrt/immortalwrt rtp2httpd](https://www.right.com.cn/forum/forum.php?mod=viewthread\&tid=8468805\&fromuid=402348) * [RouterOS 容器安装 rtp2httpd 看 IPTV](https://www.right.com.cn/forum/forum.php?mod=viewthread\&tid=8470410\&fromuid=402348) * [湖南电信 OpenWrt 拨号 IPTV 全流程教程 | 内网融合组播转单播 + 单播回看全搞定](https://mp.weixin.qq.com/s/_hEVbrgHll_qIePXGtATTw) * [世界杯最强 IPTV 方案:rtp2httpd + VLAN 单线复用 + 全设备可看](https://mp.weixin.qq.com/s/zwPMAkIaHhQ2R6FsuVl0ZQ) * [折腾 IPTV 时一定会遇到的几个概念:IGMP Snooping、IGMP Proxy、泛洪,到底是啥?](https://mp.weixin.qq.com/s/oKS-tl1-hqgcZ_H01CTtXQ) * [IPTV 里的 FCC 和 FEC 到底是什么?为什么有些源“高级得多”?](https://mp.weixin.qq.com/s/5l2Cg204YdqtWAV-RnqiYw) * [IPTV 折腾到最后一步:播放列表的几种写法,一篇讲清](https://mp.weixin.qq.com/s/wZpO74_NJvlwBbI9uvEhWw) * [手把手教你搞定浙江电信IPTV融合:安安稳稳看电视](https://zeaurx.com/archives/iptv) ### 视频教程 * [旁路由 IPTV 插件使用篇](https://www.bilibili.com/video/BV1ioiKBNE8t/) * [组播转单播系列第二期:借助 rtp2httpd 插件实现全家设备观看 iptv](https://www.bilibili.com/video/BV1Zhr4B3ELy/) ## 固件生态 以下固件已经内置 rtp2httpd(或者可以在应用市场、官方源直接下载安装 rtp2httpd)。 > \[!IMPORTANT] > 固件为了保证稳定性,通常内置/上架的 rtp2httpd 版本落后于官方最新版。如果你希望追新,建议使用 [官方支持的安装方式](../guide/installation.md) 来安装 rtp2httpd。 * [飞牛 fnOS](https://www.fnnas.com)(应用中心已上架 rtp2httpd) * [iStoreOS](https://site.istoreos.com)(iStore 已上架 rtp2httpd) * [爱快 iKuai](https://www.ikuai8.com)(应用市场即将上架 rtp2httpd) * [懒猫微服](https://lazycat.cloud)(应用商店已上架 rtp2httpd) * [cooluc's OpenWrt](https://github.com/sbwml/builder)(已内置 rtp2httpd) * [ImmortalWrt](https://github.com/immortalwrt/immortalwrt)(已加入官方源) * [AutoBuildImmortalWrt](https://github.com/wukongdaily/AutoBuildImmortalWrt)([store](https://github.com/wukongdaily/store) 已内置 rtp2httpd,轻松构建) * [潘多拉 QWRT for K2P](https://www.right.com.cn/forum/forum.php?mod=viewthread\&tid=8346913\&fromuid=402348)(已内置 rtp2httpd) ## 相关软件 ### IPTV 播放器 #### 电视直播TV mytv-android * 项目地址: Android 平台 IPTV 播放器,支持 M3U 播放列表、FCC 快速换台、EPG 电子节目单、时移回看等功能。 目前唯一支持 rtp2httpd [视频快照](../guide/video-snapshot.md) 的播放器。 #### APTV * 项目地址: 苹果生态里体验很突出的 IPTV M3U 播放器,覆盖 iPhone、iPad、Mac、Apple Vision、Apple TV、Apple Watch 等设备。支持 M3U 播放列表、EPG 电子节目单、iCloud 配置同步、实时预览、回看、多源配置、4K/HDR/HLG、画中画、AirPlay/DLNA 投屏等功能,并支持组播 FCC 快速换台优化。 #### 源匣 SrcBox * 项目地址: Windows 平台 IPTV 播放器,基于 libmpv 播放内核和 WPF 原生界面。支持 M3U 播放列表、FCC 快速切台、EPG 电子节目单、时移回看、UDP 组播优化等功能。 #### IPTVnator (CGG888 fork) * 项目地址: Windows / macOS / Linux 跨平台 IPTV 播放器,此 fork 针对中国大陆 IPTV 场景增强,主要特性: * 自动识别组播/单播来源,选择最佳播放内核(组播用 mpegts.js,单播用 hls.js) * 支持时移回看 * 4K/高清/标清画质策略,同名频道按质量优先排序 * EPG 频道名称智能匹配与中文化 #### IPTV 影视 iptvys * 项目地址: 基于蜂蜜影视(TVBox)的定制影视播放器,支持通过 rtp2httpd 代理 RTSP 源。开启 RTSP 代理并配置 rtp2httpd 地址后,可播放 rtp2httpd 代理的 RTSP 点播节目,并支持获取节目时长、进度条拖动、快进快退等功能。 ### IPTV 订阅和频道工具 #### 频道哨兵 Channel Sentinel * 项目地址: 基于 Docker 的 IPTV 单播/组播批量扫描检测工具。主要功能: * 批量导入组播流地址,自动检测在线状态、分辨率、编码、帧率等信息 * 支持按在线/离线筛选,按频道名或地址搜索 * 导出为 TXT 或 M3U 格式(M3U 支持 FCC 参数、catchup 回看地址) * 同名频道按质量优先排序(组播 4K > HD > SD > 单播) * 版本管理,支持保存和加载检测结果 #### IPTV 工具箱 iptv-tool * 项目地址: 基于 Docker 部署的 IPTV 综合管理工具箱,集 EPG 节目单管理、直播源管理、台标管理于一体。主要功能: * 支持 DIYP/百川、超级直播、xmltv 等多种格式 * 直播源聚合(TXT/M3U)、测速校验、直播源代理 * 台标模糊匹配,支持 tvbox 接口 * 频道别名、正则表达式匹配,支持繁体中文 * 定时更新数据、缓存支持(Memcached/Redis) #### IPTV Sniffer Web * 项目地址: 适用于 OpenWrt / iStoreOS / 飞牛 NAS / 其它 Linux Docker 宿主机的 IPTV 组播嗅探、运营商频道发现与 rtp2httpd 播放列表统一工作台。支持从机顶盒开机流量中解析频道表和 FCC 参数,也支持网页选择网卡实时嗅探组播流、识别编码/分辨率/截图/EPG,并导出直连 M3U、rtp2httpd 外部源 M3U、JSON、TXT、CSV 等格式。 #### IPTV-channels(四川电信) * 项目地址: 基于 Docker 的 IPTV 订阅获取工具,针对四川电信,自动从 IPTV 内网获取节目地址和 EPG,并生成包含 FCC、FEC 和单播回看地址的 M3U 播放列表。 #### iptv-cd-telecom(四川电信) * 项目地址: 成都/四川电信 IPTV 直播源项目,提供官方单播源和组播转单播两种接入方式,支持回看时移、FCC 快速换台、EPG 电子节目单,兼容 tvbox、KODI、APTV、mytv-android 等主流播放器。提供在线播放列表生成服务,可自定义 FCC、RTSP 代理、r2h-token 等参数。 #### beijing-unicom-iptv-playlist(北京联通) * 项目地址: 北京联通 IPTV 播放列表,每日自动更新。提供组播、单播、RTSP 等多种格式的 M3U 播放列表,支持时移回看和 EPG。配套在线播放链接生成器和 Python 转换工具(generator.py),可灵活自定义直播源、时移源、代理地址等参数,支持 Flask/FastAPI 动态服务部署。 #### plsy1/iptv(山东联通) * 项目地址: 山东联通 IPTV 播放列表,覆盖济南、青岛、烟台、潍坊等山东各地市的组播源,同时提供单播源(APTV、酷九、rtp2httpd 多种格式)。配套机顶盒登录鉴权模拟、EPG 节目单、RTSP 代理、数据抓取与 M3U 生成等工具。 #### SDU-IPTV-PRO(山东 IPTV) * 项目地址: 山东 IPTV 播放列表项目,汇集山东联通、山东移动、山东电信三大运营商的 IPTV 内网直播源,并按各地市用户收视习惯做本地化频道排序。提供通用版和各地市版 M3U,覆盖山东联通组播/单播、山东移动 HTTP/RTSP 单播、山东电信单播等来源,并配套聚合型 EPG。山东联通组播源可配合 rtp2httpd 转为 HTTP 流,并支持 FCC(快速频道切换)参数,起播与换台体验接近单播。 #### Shanghai-IPTV(上海电信) * 项目地址: 上海电信 IPTV 组播节目单管理工具,基于 PHP + SQLite,支持 TXT 格式导入和 M3U8 格式导出。支持多线路、多清晰度(4K/HD/SD/LD)、多 EPG 源映射、UDPXY/rtp2httpd 转换、FCC 快速换台、台标管理等功能,可通过 PHP 内置服务器提供在线播放列表服务。 --- --- url: /guide/video-snapshot.md --- # 视频快照配置 rtp2httpd 支持使用 FFmpeg 来生成视频流的快照(snapshot)功能。如果播放器集成了此功能,将会获得极快的频道预览图加载速度。 > \[!IMPORTANT] > 此功能需要播放器支持,目前已知支持 rtp2httpd 视频快照的播放器只有 [mytv-android](https://github.com/mytv-android/mytv-android)。 ## 功能特点 * **快速生成**:配合 FCC 使用时,通常在 0.3 秒内返回快照 * **自动提取关键帧**:从视频流中截取 I 帧进行转码 * **JPEG 格式**:返回标准 JPEG 图片,兼容性好 * **降低播放端压力**:无需播放器解码视频流即可显示预览图 ## FFmpeg ### 安装 FFmpeg 视频快照功能依赖 FFmpeg 来提供解码能力,请先手动安装 FFmpeg。 > \[!CAUTION] > 不要使用 OpenWrt 官方源的 `ffmpeg` 包,它阉割了 h264/hevc 编解码器,将导致无法解码视频流。 > \[!TIP] > 对于飞牛 fnOS,一般已经内置了带硬件加速 ffmpeg,可以直接使用。 #### 推荐方法:下载静态编译版本 从 [johnvansickle.com](https://johnvansickle.com/ffmpeg/) 下载静态编译的 FFmpeg(注意此版本不支持硬件解码): ```bash # 下载 FFmpeg(以 amd64 为例) cd /tmp wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz tar xf ffmpeg-release-amd64-static.tar.xz # 复制到系统目录 sudo cp ffmpeg-*-static/ffmpeg /usr/local/bin/ sudo chmod +x /usr/local/bin/ffmpeg # 配置 rtp2httpd 使用此 FFmpeg # 在配置文件中设置: # ffmpeg-path = /usr/local/bin/ffmpeg ``` ## 启用视频快照 视频快照功能默认关闭,需要手动启用。 此功能对硬件有一定要求,请只考虑在性能强大的 x86 设备上启用。 ### 命令行方式 ```bash rtp2httpd --video-snapshot --ffmpeg-path /usr/bin/ffmpeg --ffmpeg-args "-hwaccel none" ``` ### 配置文件方式 ```ini [global] # 启用视频快照功能 video-snapshot = yes # FFmpeg 可执行文件路径(可选,默认: ffmpeg) ffmpeg-path = /usr/bin/ffmpeg # FFmpeg 额外参数(可选,默认: -hwaccel none) ffmpeg-args = -hwaccel none ``` ### ffmpeg-path 参数 指定 FFmpeg 可执行文件的路径。 * **默认值**:`ffmpeg`(使用系统 PATH 中的 ffmpeg) * **使用场景**: * FFmpeg 不在系统 PATH 中 * 需要使用特定版本的 FFmpeg * 使用自定义编译的 FFmpeg **示例**: ```ini [global] ffmpeg-path = /usr/local/bin/ffmpeg ``` ### ffmpeg-args 参数 指定传递给 FFmpeg 的额外参数,主要用于硬件加速配置。 * **默认值**:`-hwaccel none`(禁用硬件加速,兼容性最好) * **常用选项**: * `-hwaccel none`:禁用硬件加速 * `-hwaccel auto`:自动检测并使用硬件加速 * `-hwaccel vaapi`:使用 VA-API 硬件加速(Intel GPU) * `-hwaccel v4l2m2m`:使用 V4L2 硬件加速(嵌入式 SoC) * `-hwaccel qsv`:使用 Intel Quick Sync Video 加速 **示例**: ```ini [global] # 使用 VA-API 硬件加速(Intel GPU) ffmpeg-args = -hwaccel vaapi # 或使用自动检测 ffmpeg-args = -hwaccel auto ``` ## 硬件加速配置 ### Intel GPU (VA-API) 如果你的设备有 Intel 集成显卡,可以使用 VA-API 硬件加速: ```ini [global] video-snapshot = yes ffmpeg-args = -hwaccel vaapi ``` 针对 Intel GPU 的预编译 FFmpeg,请参考:[rtp2httpd#37](https://github.com/stackia/rtp2httpd/issues/37) ### 嵌入式设备 (V4L2) 某些嵌入式 SoC 支持 V4L2 硬件加速: ```ini [global] video-snapshot = yes ffmpeg-args = -hwaccel v4l2m2m ``` ### 性能提示 * 在 CPU 性能较低的设备上,如果没有硬件加速支持,生成快照可能产生较大 CPU 占用 * 建议先使用 `-hwaccel none` 测试功能是否正常 * 确认正常后,再尝试启用硬件加速以降低 CPU 占用 ## 响应时间 * **使用 FCC**:通常在 0.3 秒内返回快照(快速获取关键帧) * **不使用 FCC**:最长约 1 秒返回(等待下一个 IDR 帧) 大多数运营商组播流每秒发送一个 IDR 帧,因此不使用 FCC 时最长需要等待 1 秒。 ## 播放器集成建议 如果你是播放器开发者,建议按以下方式集成预览图功能: 1. **请求快照时带上自定义请求头**: ```http GET /rtp/239.253.64.120:5140 HTTP/1.1 X-Request-Snapshot: 1 ``` 2. **根据响应的 Content-Type 决定处理方式**: * 如果响应 `Content-Type: image/jpeg`:直接渲染 JPEG 图片 * 如果响应其他类型:说明服务器不支持快照,尝试解码媒体流 3. **兼容性**:这种方式可以同时兼容 rtp2httpd 和其他不支持快照的流媒体服务器 除了 `X-Request-Snapshot: 1`,也支持另外两种请求方式获取快照: ### URL 查询参数 在任意流媒体 URL 后添加 `snapshot=1` 参数: ```url http://192.168.1.1:5140/rtp/239.253.64.120:5140?snapshot=1 http://192.168.1.1:5140/CCTV-1?snapshot=1 ``` ### Accept 请求头 ```bash curl -H "Accept: image/jpeg" http://192.168.1.1:5140/rtp/239.253.64.120:5140 ``` ## 故障排查 ### 快照请求返回视频流而不是图片 可能的原因: 1. **未启用 video-snapshot**:检查配置文件或命令行参数 2. **FFmpeg 不可用**:检查 FFmpeg 是否正确安装 3. **FFmpeg 解码失败**:查看 rtp2httpd 日志 ### FFmpeg 解码失败 可能的原因: 1. **编解码器缺失**:OpenWrt 官方源的 FFmpeg 缺少 h264/hevc 编解码器 2. **硬件加速不支持**:尝试改用 `-hwaccel none` 3. **硬件忙**:有些硬件解码器,同时解码的媒体流有上限,并发请求过多时可能出现硬件忙碌错误。 ### CPU 占用过高 * 禁用硬件加速后 CPU 占用高是正常现象 * 解决方案: 1. 使用硬件加速(如果设备支持) 2. 减少同时请求快照的客户端数量 3. 在播放器设置中降低预览图请求并发数 ## 相关文档 * [URL 格式说明](./url-formats.md):快照 URL 格式 * [配置参数详解](../reference/configuration.md):视频快照相关配置 * [FCC 快速换台配置](./fcc-setup.md):配合 FCC 获得更快的快照速度 --- --- url: /guide/access-log.md --- # 访问日志 rtp2httpd 可以为媒体请求写入访问日志,便于审计客户端访问了哪些频道、排查反向代理后的客户端来源,以及对接外部日志系统。 ## 启用访问日志 访问日志默认关闭。只有配置 `access-log` 后才会写入日志。 ### 配置文件 ```ini [global] access-log = /var/log/rtp2httpd/access.log log-format = $client_addr [$time_iso8601] "$service_url" $service_type "$upstream_url" ``` ### 命令行 ```bash rtp2httpd --access-log /var/log/rtp2httpd/access.log \ --log-format '$client_addr [$time_iso8601] "$service_url" $service_type "$upstream_url"' ``` OpenWrt LuCI 页面中也可以配置访问日志路径和格式。 ## 默认格式 `log-format` 未配置或为空时,使用以下默认格式: ```text $client_addr [$time_iso8601] "$service_url" $service_type "$upstream_url" ``` 示例输出: ```text 192.0.2.10:53124 [2026-06-25T20:10:12+08:00] "/CCTV-1" rtp "rtp://239.0.0.1:1234" ``` ## 占位符 `log-format` 使用类似 nginx 的 `$变量` 形式。支持的占位符如下: | 占位符 | 说明 | | --- | --- | | `$time_iso8601` | 本地时间,ISO 8601 格式,例如 `2026-06-25T20:10:12+08:00` | | `$time_local` | 本地时间,nginx 风格格式,例如 `25/Jun/2026:20:10:12 +0800` | | `$msec` | Unix 时间戳,精确到毫秒,例如 `1782389412.123` | | `$client_addr` | 状态页面显示的客户端地址 | | `$remote_addr` | 从 `$client_addr` 拆出的客户端 IP 或地址 | | `$remote_port` | 从 `$client_addr` 拆出的客户端端口;没有端口时输出 `-` | | `$worker_pid` | 处理该请求的 worker 进程 PID | | `$request` | 请求方法和 Service URL,例如 `GET /rtp/239.0.0.1:1234` | | `$request_method` | HTTP 请求方法,例如 `GET` | | `$service_url` | 客户端访问的 Service URL | | `$host` | HTTP `Host` 头 | | `$http_user_agent` | HTTP `User-Agent` 头 | | `$http_x_forwarded_for` | HTTP `X-Forwarded-For` 头 | | `$service_type` | 服务类型:`rtp`、`rtsp` 或 `http` | | `$upstream_url` | 实际上游 URL | | `$$` | 输出字面量 `$` | 未知占位符会按原样输出。空值会输出为 `-`。日志值中的引号、反斜杠、换行和控制字符会被转义,单行日志最长 8192 字节。 ## 客户端地址与 X-Forwarded-For `$client_addr` 与状态页面显示的客户端地址一致。 启用 `xff` 后,如果请求中的 `X-Forwarded-For` 被接受,`$client_addr` 会使用 `X-Forwarded-For` 中的第一个地址。这种情况下通常没有客户端端口,因此 `$remote_port` 会输出 `-`。 ## 令牌隐藏 如果请求 URL 中包含 `r2h-token` 查询参数,访问日志中的 `$service_url` 和 `$upstream_url` 不会包含该参数。`$http_user_agent` 也会隐藏 `R2HTOKEN/...` 片段,避免令牌通过访问日志泄露。 ## 配合 logrotate rtp2httpd worker 会保持访问日志文件打开。轮转日志后,需要向 supervisor 进程发送 `SIGHUP`,让 worker 重新打开日志文件。 logrotate 配置示例: ```text /var/log/rtp2httpd/access.log { daily rotate 7 missingok notifempty compress create 0644 root root sharedscripts postrotate for pid in $(pidof rtp2httpd); do ppid="$(awk '/^PPid:/ { print $2 }' "/proc/$pid/status" 2>/dev/null)" [ "$(cat "/proc/$ppid/comm" 2>/dev/null)" = "rtp2httpd" ] && continue kill -HUP "$pid" 2>/dev/null || true done endscript } ``` 这里会跳过父进程同样是 `rtp2httpd` 的 worker 子进程,只向 supervisor 发送 `SIGHUP`。 --- --- url: /reference/configuration.md --- # 配置参数详解 rtp2httpd 支持通过命令行参数和配置文件两种方式进行配置。 > \[!TIP] > > 1. 命令行参数具有最高优先级 > 2. 配置文件参数次之 > 3. 内置默认值最低 ## 命令行参数 ```bash rtp2httpd [选项] ``` ### 网络配置 * `-l, --listen [地址:]端口|/path/to/rtp2httpd.sock` - 绑定 TCP 监听地址/端口,或监听 Unix domain socket (默认: \*:5140) * `-m, --maxclients <数量>` - 最大并发客户端数 (默认: 5) * `-w, --workers <数量>` - 工作进程数 (默认: 1) `--listen` 可以重复指定,用于同时监听多个 TCP 地址/端口或 Unix socket: ```bash rtp2httpd --listen 5140 --listen 192.168.1.1:8081 --listen '[::1]:5140' --listen /var/run/rtp2httpd.sock ``` Unix socket 监听路径必须是绝对路径,且路径中不能包含空白字符。启动时如果同路径已存在 socket 文件,rtp2httpd 会先探测该 socket 是否仍在使用:如果已有进程正在监听该路径,则拒绝启动;只有确认是残留 socket 文件时才会自动清理。如果同路径是普通文件、目录或符号链接,则会拒绝启动以避免误删数据。启用任意 Unix socket 监听时,`zerocopy-on-send` 会被全局关闭。 #### 上游网络接口配置 * `-i, --upstream-interface <接口>` - 默认上游接口(作用于所有流量类型,优先级最低) * `-f, --upstream-interface-fcc <接口>` - FCC 上游接口(覆盖 `-i` 设置) * `-t, --upstream-interface-rtsp <接口>` - RTSP 上游接口(覆盖 `-i` 设置) * `-r, --upstream-interface-multicast <接口>` - 组播上游接口(覆盖 `-i` 设置) * `-y, --upstream-interface-http <接口>` - HTTP 代理上游接口(覆盖 `-i` 设置) **优先级规则**:`upstream-interface-{fcc,rtsp,multicast,http}` > `upstream-interface` > 系统路由表 > \[!TIP] > 除了全局配置外,还可以在每个请求的 URL 中通过 `r2h-ifname` 和 `r2h-ifname-fcc` 参数指定上游接口,详见 [URL 格式说明](../guide/url-formats.md)。 > \[!TIP] > FreeBSD 系统下不支持指定除组播外的接口。 ### 性能优化 * `-b, --buffer-pool-max-size <数量>` - 缓冲池最大缓冲区数量 (默认: 16384) * 每个缓冲区 1536 字节,16384 个约占用 24MB 内存 * 增大此值以提高多客户端并发时的吞吐量 * `-B, --udp-rcvbuf-size <字节>` - UDP socket 接收缓冲区大小 (默认: 524288 = 512KB) * 作用于组播、FCC、RTSP RTP/RTCP 所有 UDP socket * 对于 30 Mbps 的 4K IPTV 流,512KB 可提供约 140ms 的缓冲 * 增大此值以减少高带宽流的丢包 * 实际缓冲区大小可能受内核参数 `net.core.rmem_max` 限制 * `-Z, --zerocopy-on-send` - 启用零拷贝发送以提升性能 (默认: 关闭) * 需要内核支持 MSG\_ZEROCOPY (Linux 4.14+) * 在支持的设备上提升吞吐量并降低 CPU 占用 * 如果你的 rtp2httpd 位于反向代理之后 (nginx/caddy/lucky 等),不建议开启这个选项 ### FCC 快速换台 * `-P, --fcc-listen-port-range <起始[-结束]>` - FCC UDP 监听端口范围 (默认: 随机端口) ### 服务控制 * `-c, --config <文件>` - 指定配置文件路径 (默认 `/etc/rtp2httpd.conf`) * `-C, --noconfig` - 不读取任何配置文件(避免读到默认的 `/etc/rtp2httpd.conf`) ### 日志控制 * `-v, --verbose` - 日志详细程度 (0=FATAL, 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG) * `-q, --quiet` - 仅显示致命错误 * `--access-log <路径>` - 将访问日志写入指定文件 (默认: 禁用) * `--log-format <格式>` - 访问日志格式,使用类似 nginx 的 `$变量` 占位符,详见 [访问日志](../guide/access-log.md) ### 安全控制 * `-H, --hostname <主机名>` - 检查 HTTP Host 头的主机名 * `-X, --xff` - 启用 X-Forwarded-For 解析 * `-T, --r2h-token <令牌>` - HTTP 请求认证令牌 (所有请求必须携带 r2h-token 查询参数) * `-O, --cors-allow-origin <值>` - 设置 CORS Access-Control-Allow-Origin 头 (默认: 禁用) * 设为 `*` 允许所有来源,或指定具体域名(如 `https://example.com`) * `-s, --status-page-path <路径>` - 状态页面与 API 根路径 (默认: /status) * `-p, --player-page-path <路径>` - 内置播放器页面路径 (默认: /player) * `--app-path-prefix <路径>` - 所有 HTTP 资源的公开访问前缀 (默认: 无) * `--use-relative-path-in-m3u` - 生成 playlist.m3u 或 HTTP 代理改写 M3U 时使用站点根相对 URL (默认: 关闭) ### 兼容性 * `-U, --noudpxy` - 禁用 UDPxy 兼容模式 (禁用后只能使用 `[services]` 或 `external-m3u` 中定义的服务) ### HTTP 代理相关 * `-g, --http-proxy-user-agent <值>` - 向 HTTP 上游请求时的 User-Agent 头 (默认: 透传客户端 User-Agent) * 作用于通过 `/http/...` 路径代理到上游 HTTP 服务器的请求 * 配置后会替换原本透传给上游的客户端 User-Agent ### RTSP 相关 * `-u, --rtsp-user-agent <值>` - 向 RTSP 上游请求时的 User-Agent 头 (默认: `rtp2httpd/`) * 作用于 OPTIONS、DESCRIBE、SETUP、PLAY、TEARDOWN、GET\_PARAMETER 等上游 RTSP 请求 * 某些上游 RTSP 服务器会校验或依赖特定 User-Agent,可通过此参数进行兼容 * `-N, --rtsp-stun-server ` - STUN 服务器地址 (默认: 禁用) * 当 RTSP 服务器仅支持 UDP 传输且客户端位于 NAT 后时,可尝试使用 STUN 进行 NAT 穿透(不保证成功) * 格式:`host:port` 或 `host`(默认端口 3478) * 示例:`stun.miwifi.com` 或 `stun.miwifi.com:3478` ### 其他 * `-S, --video-snapshot` - 启用视频快照功能 (默认: 关闭) * `-F, --ffmpeg-path <路径>` - FFmpeg 可执行文件路径 (默认: ffmpeg) * `-A, --ffmpeg-args <参数>` - FFmpeg 额外参数 (默认: -hwaccel none) * `-h, --help` - 显示帮助信息 ## 配置文件格式 配置文件路径:`/etc/rtp2httpd.conf`,每行如果使用 `#` 或 `;` 开头表示注释。 ```ini [global] # 日志详细程度: 0=FATAL 1=ERROR 2=WARN 3=INFO 4=DEBUG verbosity = 3 # 访问日志文件路径(留空或不配置时禁用) access-log = /var/log/rtp2httpd/access.log # 访问日志格式(可选,nginx 风格 $变量) # 默认: $client_addr [$time_iso8601] "$service_url" $service_type "$upstream_url" log-format = $client_addr [$time_iso8601] "$service_url" $service_type "$upstream_url" # 最大并发客户端数 maxclients = 20 # UDPxy 兼容性 udpxy = yes # 工作进程数(默认: 1) workers = 1 # 检查 HTTP 请求的 Host 头 (默认:无) hostname = somehost.example.com # 启用后,将使用 HTTP X-Forwarded-For 头作为客户端地址,用于显示在状态面板上 (默认:no) # 并接受 X-Forwarded-Host / X-Forwarded-Proto 头作为 playlist.m3u 中的地址前缀 # 建议仅在使用反向代理时启用 xff = no # HTTP 请求认证令牌(可选,默认: 无) # 设置后,所有 HTTP 请求必须携带 r2h-token 查询参数,且值与此配置匹配 # 例如: # http://server:5140/rtp/239.253.64.120:5140?fcc=10.255.14.152:15970&r2h-token=your-secret-token # http://server:5140/player?r2h-token=your-secret-token r2h-token = your-secret-token-here # 状态页应用内路径(默认: /status;配置 app-path-prefix 时会挂载在该前缀下) status-page-path = /status # 播放器页应用内路径(默认: /player;配置 app-path-prefix 时会挂载在该前缀下) player-page-path = /player # 所有 HTTP 资源的公开访问前缀(默认: 无) # 设置后,状态页、播放器、静态资源、playlist.m3u、epg.xml 和流媒体 URL # 都会在此前缀下提供,例如 /app/rtp2httpd/player。 app-path-prefix = /app/rtp2httpd # M3U 输出使用站点根相对路径(默认: no) # 开启后,playlist.m3u 和 HTTP 代理改写后的 M3U 中不会包含 http://host 前缀, # 只保留 / 或 app-path-prefix 开头的路径,例如 /app/rtp2httpd/rtp/... use-relative-path-in-m3u = no # 上游网络接口配置 (可选) # # 简单配置:只配置一个默认接口,所有流量类型都使用此接口 upstream-interface = eth0 # # 高级配置:为不同流量类型配置专用接口 # 注意:专用接口配置优先级高于默认接口 # upstream-interface-multicast = eth0 # 组播流量 (RTP/UDP) # upstream-interface-fcc = eth1 # FCC # upstream-interface-rtsp = eth2 # RTSP # upstream-interface-http = eth3 # HTTP 代理 # # 混合配置示例:默认使用 eth0,但 FCC 使用更快的 eth1 # upstream-interface = eth0 # upstream-interface-fcc = eth1 # # 优先级:upstream-interface-{multicast,fcc,rtsp,http} > upstream-interface > 系统路由表 # 对于 FreeBSD 系统,仅支持设置组播接口 # 外部 M3U 配置(支持 file://, http://, https://) # 注意:HTTP/HTTPS 需要安装 curl 或 uclient-fetch 或 wget 命令 external-m3u = https://example.com/iptv.m3u # 或使用本地文件 external-m3u = file:///path/to/playlist.m3u # 外部 M3U 更新间隔(秒) # 默认 7200(2 小时),设为 0 禁用自动更新 external-m3u-update-interval = 7200 # 组播周期性重新加入间隔(秒,默认: 0 禁用) # 设置为正值(如 60)以周期性重新加入组播组 # 这是针对以下网络环境的兼容性解决方案: # - 启用 IGMP snooping 的交换机在没有路由器 IGMP Query 时超时 # - 配置不当的网络设备会丢弃组播成员关系 # 推荐值: 30-120 秒(小于典型交换机超时 260 秒) # 注意:默认禁用(0),仅在遇到组播流中断时才需要启用 # 注意:不支持 IPv6 mcast-rejoin-interval = 0 # FCC 监听媒体流端口范围(可选,格式: 起始-结束,默认随机端口) fcc-listen-port-range = 40000-40100 # 缓冲池最大缓冲区数量(默认: 16384) # 每个缓冲区 1536 字节,16384 个约占用 24MB 内存 # 增大此值以提高多客户端并发时的吞吐量,例如设置为 32768 或更高 buffer-pool-max-size = 16384 # UDP socket 接收缓冲区大小(默认: 524288 = 512KB) # 作用于组播、FCC、RTSP RTP/RTCP 所有 UDP socket # 对于 30 Mbps 的 4K IPTV 流,512KB 可提供约 140ms 的缓冲 # 增大此值以减少高带宽流的丢包 # 实际缓冲区大小可能受内核参数 net.core.rmem_max 限制 udp-rcvbuf-size = 524288 # 启用零拷贝发送以提升性能(默认: no) # 设为 yes/true/on/1 以启用零拷贝 # 需要内核支持 MSG_ZEROCOPY (Linux 4.14+) # 在支持的设备上可提升吞吐量并降低 CPU 占用,特别是在高并发负载下 # 如果你的 rtp2httpd 位于反向代理之后 (nginx/caddy/lucky 等),不建议开启这个选项 zerocopy-on-send = no # 覆盖上游 HTTP 代理请求的 User-Agent(默认: 不覆盖) # 设置后将替换发送给 /http/ 上游服务器的客户端 User-Agent http-proxy-user-agent = rtp2httpd-http-proxy/1.0 # 上游 RTSP 请求的 User-Agent(默认: rtp2httpd/) # 当上游 RTSP 服务器要求特定 User-Agent 时可配置此项 rtsp-user-agent = rtp2httpd/custom # STUN 服务器用于 RTSP NAT 穿透(默认: 禁用) # 当 RTSP 服务器仅支持 UDP 传输且客户端位于 NAT 后时,可尝试使用 STUN 进行 NAT 穿透(不保证成功) # 格式: host:port 或 host(默认端口 3478) rtsp-stun-server = stun.miwifi.com # CORS 跨域请求配置(默认: 禁用) # 设置后启用 CORS # 设为 * 允许所有域名,或指定具体域名 ;cors-allow-origin = * # 启用视频快照功能(默认: no) # 启用后可通过 `snapshot=1` 查询参数获取视频流的实时快照 video-snapshot = no # FFmpeg 可执行文件路径(默认: ffmpeg,使用系统 PATH) # 如果 ffmpeg 不在 PATH 中或想使用特定版本,请指定完整路径 ffmpeg-path = /usr/bin/ffmpeg # FFmpeg 额外参数(默认: -hwaccel none) # 这些参数在生成快照时传递给 ffmpeg # 常用选项: -hwaccel none, -hwaccel auto, -hwaccel vaapi, -hwaccel qsv ffmpeg-args = -hwaccel none [bind] # 监听所有地址的 5140 端口 * 5140 # 监听特定 IP 的 8081 端口 192.168.1.1 8081 # 监听 IPv6 地址(可省略方括号) 2001:db8::1 5140 # 监听 Unix domain socket(路径必须是绝对路径) /var/run/rtp2httpd.sock # 支持多个监听地址 # [services] 内可以直接编写以 #EXTM3U 开头的 m3u 节目清单 # 和 external-m3u 功能类似,只是直接把 m3u 写在了配置文件内 [services] #EXTM3U x-tvg-url="https://example.com/epg.xml.gz" #EXTINF:-1 tvg-id="CCTV1" tvg-name="CCTV1" tvg-logo="https://example.com/logo/CCTV1.png" group-title="央视" catchup="default" catchup-source="rtsp://10.0.0.50:554/catchup?playseek={utc:YmdHMS}-{utcend:YmdHMS}",CCTV-1 rtp://239.253.64.120:5140 #EXTINF:-1 tvg-id="CCTV2" tvg-name="CCTV2" group-title="央视",CCTV-2 rtp://239.253.64.121:5140 ``` 访问日志的启用方式、格式占位符和 logrotate 配置见 [访问日志](../guide/access-log.md)。 ## 运行时配置管理 rtp2httpd 支持配置热重载:修改配置文件后,通过发送信号或状态页面触发重载,即可应用变更,无需重启整个进程。rtp2httpd 采用 supervisor + worker 多进程架构,信号应发送给 **supervisor 进程**(即主 `rtp2httpd` 进程,而非 worker 子进程)。 ### 信号说明 | 信号 | 作用 | | --- | --- | | `SIGHUP` | 热重载配置:从配置文件重新读取并应用 | | `SIGUSR1` | 重启所有工作进程 | **示例**(将 `12345` 替换为 supervisor 进程的 PID): ```bash # 热重载配置 kill -HUP 12345 # 重启所有工作进程 kill -USR1 12345 ``` ### SIGHUP 热重载行为 * 从配置文件(默认 `/etc/rtp2httpd.conf`,或通过 `--config` 指定的路径)重新读取配置 * 若 `[bind]` 监听地址发生变化,supervisor 会向所有工作进程发送 `SIGTERM` 并重新拉起,以应用新的监听地址 * 若 `workers` 数量发生变化,supervisor 会自动增减工作进程 * 其他配置变更会转发 `SIGHUP` 给各工作进程,由工作进程在运行时应用 * 工作进程会在重载时重新打开 [访问日志](../guide/access-log.md) 文件,便于配合 logrotate * 若配置文件解析失败,保留旧配置,不会中断现有连接 > \[!NOTE] > 使用 `--noconfig` 启动时,没有配置文件可供重载;此时 `SIGHUP` 仅触发 M3U/EPG 的重新加载。 ### SIGUSR1 重启工作进程 向 supervisor 发送 `SIGUSR1` 后,所有工作进程会被终止并由 supervisor 自动重新拉起。适用于需要刷新工作进程状态、但不修改配置文件的场景。进行中的客户端连接会被中断。 ### 通过状态页面操作 [状态页面](../guide/url-formats.md#状态页面) 提供了等效的管理功能,无需手动查找 PID: * **重载配置**:对应 `SIGHUP`(API:`POST /api/reload-config`) * **重启工作进程**:对应 `SIGUSR1`(API:`POST /api/restart-workers`)