找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
广告投放联系QQ68610888
查看: 3177|回复: 20

[iptv信源 资源分享或寻求] 江苏电信IPTV直播源(RTSP认证源)在tvbox上播放(技术分析)

[复制链接]
本帖最后由 op351 于 2023-12-5 17:46 编辑

接前两篇帖子
[iptv信源 资源分享或寻求] 江苏电信IPTV回看地址探究 (技术分析)
[iptv信源 资源分享或寻求] 江苏电信IPTV回看源在tvbox上进行播放 (技术分析)
在回看源搞定之后 我尝试将江苏电信的组播源也搬到tvbox来播放(原来在diyp播放)
但是搬过来以后发现换台速度极慢 起码要5秒
所以放弃udpxy转换的模式 转向直接使用江苏电信IPTV的RTSP源进行播放
经过验证 换台流畅度和原配机顶盒达到了差不多的程度 可以接受


本篇 我们就来看看如何使用tvbox来进行江苏电信IPTV RTSP源的抓取,存储和播放
顺带实现江苏电信IPTV原生EPG的抓取,存储和使用
tvbox配置文件存储,获取,全流程本地化也在本篇一并分析


tvbox版本:https://github.com/takagen99/Box takagen99版
路由器:斐讯K3
openwrt版本:23.05


接上回

我们打开jar爬虫项目
在iptvAuth方法的frameset_builder获取到返回报文后
使用正则剥离频道id和rstp源
  1. <font size="3">String tsurl = new String(response.body().bytes(), "UTF-8");
  2.         Pattern TimeShiftURLPattern = Pattern.compile("ChannelID="(.*)",ChannelName=".*",UserChannelID="\\d*",ChannelURL=".*",TimeShift="\\d*",ChannelSDP=".*",TimeShiftURL="(.*)",ChannelLogURL=");
  3.         Matcher TimeShiftURLMatch = TimeShiftURLPattern.matcher(tsurl);
  4.         try {
  5.             JSONArray timeShiftJsonTemp = new JSONArray();
  6.             while (TimeShiftURLMatch.find()) {
  7.                 JSONObject timet = new JSONObject();
  8.                 timet.put("chid", TimeShiftURLMatch.group(1));
  9.                 timet.put("rtspurl", TimeShiftURLMatch.group(2));
  10. //                tvlist += TimeShiftURLMatch.group(1) + ",";
  11. //                tvlist += TimeShiftURLMatch.group(2) + "\r\n";
  12.                 timeShiftJsonTemp.put(timet);
  13.             }
  14.             timeShiftJson = timeShiftJsonTemp;
  15.         } catch (Exception e) {

  16.         }</font>
复制代码
保存到timeShiftJson中备用


本地EPG实现:

新建方法setepg
1.获取/iptvepg/frame1194/play_channel.jsp的返回报文 (请在第一篇江苏电信IPTV回看地址探究中保存的wireshark文件中自行查找)
2.利用正则剥离江苏电信原生频道排序信息
  1. String chsl = new String(response.body().bytes(), "GB2312");
  2.                 Pattern channelListPattern = Pattern.compile("channelAllList":(.*),"mixnoAllList":");
  3.                 Matcher channelListMatch = channelListPattern.matcher(chsl);
  4.                 channelListMatch.find();
  5.                 JSONArray channelListJson = new JSONArray(channelListMatch.group(1));
复制代码
3.在openwrt上新建文件/cgi-bin/epgcheck

  1. #!/usr/bin/lua
  2. local EpgCheck = require 'EpgCheck'
  3. EpgCheck.Run()
复制代码
4.在openwrt上新建lua模块EpgCheck
  1. local EpgCheck = {}

  2. function EpgCheck.Run()
  3.     io.write("Content-type: text/html\nProgma: no-cache\n\n")
  4.     local time1f = io.popen("ls -l --full-time /www/CCTV1-HD.json")
  5.     local time1 = time1f:read()
  6.     if (time1 == nil)
  7.     then
  8.         print("false")
  9.     else
  10.         local time1date = string.match(time1, '%d+-%d+-%d+')
  11.         local time2f = io.popen("date +"%Y-%m-%d"")
  12.         local time2 = time2f:read()
  13.         if (time1date == time2)
  14.         then
  15.             print("true")
  16.         else
  17.             print("false")
  18.         end
  19.     end
  20. end

  21. return EpgCheck
复制代码
这个cgi的作用是减少epg的获取频次,仅在每天第一次启动tvbox时获取所有频道的EPG信息
5.建立频道分类数组
  1. Integer[] CCTV = new Integer[] {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,140,152};
  2.             List cctv = Arrays.asList(CCTV);
  3.             Integer[] JSTV = new Integer[] {17,18,19,20,21,22,23,24,25,26,83,107,108,109,110,111,113,115};
  4.             List jstv = Arrays.asList(JSTV);
  5.             Integer[] DFTV = new Integer[] {17,32,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,57,58,59,60,61,62,63,64,65,77,85,86,87,107,116,117,118,119,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,137,138,139,141,142};
  6.             List dftv = Arrays.asList(DFTV);
  7.             Integer[] GQTV = new Integer[] {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,25,26,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,52,54,57,58,59,66,67,68,69,70,71,72,73,74,75,76,77,79,80,81,82,105,106,120,140,142,143,155,156,157};
  8.             List gqtv = Arrays.asList(GQTV);
复制代码
6.遍历之前存储的channelListJson
6.1进行频道分类,并存储到变量tvlist中
  1. String channelidTemp = channelListJson.getJSONObject(i).get("channelcode").toString();
  2.                     String channelname = channelListJson.getJSONObject(i).get("channelname").toString();
  3.                     if (!channelname.contains("HD") || channelname.contains("购物")) {
  4.                         continue;
  5.                     }
  6.                     String columncode = channelListJson.getJSONObject(i).get("columncode").toString();
  7.                     String mixno = channelListJson.getJSONObject(i).get("mixno").toString();
  8.                     String realmixno = channelListJson.getJSONObject(i).get("realmixno").toString();
  9.                     for (int j = 0; j < timeShiftJson.length(); j++) {
  10.                         if (channelidTemp.equals(timeShiftJson.getJSONObject(j).get("chid"))) {
  11.                             if (cctv.contains(i)) {
  12.                                 tvlist += "CCTV,#genre#" + "\r\n";
  13.                             }else if (jstv.contains(i)) {
  14.                                 tvlist += "江苏,#genre#" + "\r\n";
  15.                             }else if (dftv.contains(i)) {
  16.                                 tvlist += "卫视,#genre#" + "\r\n";
  17.                             }else if (gqtv.contains(i)) {
  18.                                 tvlist += "高清,#genre#" + "\r\n";
  19.                             } else {
  20.                                 tvlist += "其他,#genre#" + "\r\n";
  21.                             }
  22.                             tvlist += channelname + ",";
  23.                             tvlist += timeShiftJson.getJSONObject(j).get("rtspurl") + "\r\n";
  24.                         }
  25.                     }
复制代码
6.2在进入epg爬取之前,判断路由器上是否已有epg信息,有则跳过下面的代码
  1. client = new OkHttpClient().newBuilder()
  2.                     .build();
  3.             request = new Request.Builder()
  4.                     .url("http://192.168.8.1/cgi-bin/epgcheck")
  5.                     .get()
  6.                     .build();
  7.             response = client.newCall(request).execute();
  8.             String egresult = response.body().string().trim();
  9. if (egresult.equals("true")) {
  10.                         continue;
  11.                     }
复制代码
6.3epg爬取
获取/iptvepg/frame1194/CHANNEL_PLAYER_UTILS/datas/prevue_list.jsp报文  (请在第一篇江苏电信IPTV回看地址探究中保存的wireshark文件中自行查找)
通过正则剥离原始epg信息,并转化为tvbox可用格式
  1. String epgjson = new String(response.body().bytes(), "GB2312");
  2.                     JSONObject epg = new JSONObject(epgjson);
  3.                     String epglist = epg.get("channelPrevue").toString();
  4.                     JSONArray epgJsonBefore = new JSONArray(epglist);
  5.                     JSONArray epgJsonAfter = new JSONArray();
  6.                     for (int k = 0; k < epgJsonBefore.length(); k++) {
  7.                         JSONObject epgitem = new JSONObject();
  8.                         String title = epgJsonBefore.getJSONObject(k).get("prevuename").toString();
  9.                         String begintimet = epgJsonBefore.getJSONObject(k).get("begintime").toString();
  10.                         Pattern timePattern = Pattern.compile("\\d{4}.\\d{2}.\\d{2} (\\d{2}:\\d{2}):\\d{2}");
  11.                         Matcher btimeMatch = timePattern.matcher(begintimet);
  12.                         btimeMatch.find();
  13.                         String begintime = btimeMatch.group(1);
  14.                         String endtimet = epgJsonBefore.getJSONObject(k).get("endtime").toString();
  15.                         Matcher endtimeMatch = timePattern.matcher(endtimet);
  16.                         endtimeMatch.find();
  17.                         String endtime = endtimeMatch.group(1);
  18.                         epgitem.put("start", begintime);
  19.                         epgitem.put("desc", "");
  20.                         epgitem.put("end", endtime);
  21.                         epgitem.put("title", title);
  22.                         epgJsonAfter.put(epgitem);
  23.                     }
  24.                     Date now = new Date();
  25.                     SimpleDateFormat ST = new SimpleDateFormat("yyyy-MM-dd");
  26.                     String nowdate = ST.format(now);
  27.                     JSONObject epgFinal = new JSONObject();
  28.                     epgFinal.put("date", nowdate);
  29.                     epgFinal.put("channel_name", channelname);
  30.                     epgFinal.put("url", "");
  31.                     epgFinal.put("epg_data", epgJsonAfter);
  32.                     String epgFinalstring = epgFinal.toString();
复制代码
6.4上传epg信息到路由器
  1. MediaType mediaType = MediaType.parse("text/plain");
  2.                     RequestBody body = RequestBody.create(mediaType, epgFinalstring);
  3.                     request = new Request.Builder()
  4.                             .url("http://192.168.8.1/cgi-bin/uploadepg")
  5.                             .method("POST", body)
  6.                             .addHeader("User-Agent", URLEncoder.encode(channelname))
  7.                             .addHeader("Content-Type", "text/plain")
  8.                             .build();
  9.                     client.newCall(request).execute();
复制代码
6.5 /cgi-bin/uploadepg内容
  1. #!/usr/bin/lua
  2. local EpgJson = require 'EpgJson'
  3. EpgJson.Run()
复制代码
6.6lua模块EpgJson内容
  1. local EpgJson = {}
  2. require "nixio"

  3. function EpgJson.Run()
  4.    io.write("Content-type: text/html\nProgma: no-cache\n\n")
  5.    local epgjsonbody = io.read("*all")
  6.       http_headers = nixio.getenv()
  7.       local channame = http_headers['HTTP_USER_AGENT']
  8.       file = io.open(channame .. ".json", "w")
  9.    file:write(epgjsonbody)
  10.    io.close(file)
  11. end

  12. return EpgJson
复制代码
通过使用user-agent来传输频道名,以简化lua程序
json放置在body中,以原始text传送
最终文件生成为/www/xxx.json


在huikan方法中调用setepg
在homeContent方法中上传分类好的频道列表
  1. OkHttpClient client = new OkHttpClient().newBuilder()
  2.                     .build();
  3.             MediaType mediaType = MediaType.parse("text/plain");
  4.             RequestBody body = RequestBody.create(mediaType, tvlist);
  5.             Request request = new Request.Builder()
  6.                     .url("http://192.168.8.1/cgi-bin/iptvfile")
  7.                     .method("POST", body)
  8.                     .addHeader("Content-Type", "text/plain")
  9.                     .build();
  10.             client.newCall(request).execute();
复制代码
/cgi-bin/iptvfile内容
  1. #!/usr/bin/lua
  2. local WebService = require 'WebService'
  3. WebService.Run()
复制代码
lua模块WebService内容
  1. local WebService = {}

  2. function WebService.Run()
  3.    io.write("Content-type: text/html\nProgma: no-cache\n\n")
  4.    local tvlist = io.read("*all")
  5.    print(tvlist)
  6.    file = io.open("tv.txt", "w")
  7.    file:write(tvlist)
  8.    io.close(file)
  9. end

  10. return WebService
复制代码
最终频道分类表储存在/www/tv.txt中

接下来我们把源配置文件iptv.json和jar放置在路由器的/www目录下

在iptv.json中我们修改直播源url为本地的tv.txt
epg修改为本地cgi-bin接口getepg

/cgi-bin/getepg内容
  1. #!/usr/bin/lua
  2. local GetEpg = require 'GetEpg'
  3. GetEpg.Run()
复制代码
lua模块GetEpg内容
  1. local GetEpg = {}
  2. require "nixio"

  3. function GetEpg.Run()
  4.    io.write("Content-type: application/json\nProgma: no-cache\n\n")
  5.    http_headers = nixio.getenv()
  6.    local qs = http_headers['QUERY_STRING']
  7.         local channame = string.match(qs, 'ch=(.*)&')
  8.        file = io.open(channame .. ".json", "r")
  9.        local content = file:read "*a"
  10.        print(content)
  11.        file:close()
  12. end

  13. return GetEpg
复制代码


接下来我们看看实际效果




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×

评分

参与人数 2恩山币 +2 收起 理由
玉宇*** + 1 大神,能告诉一下,Authenticator的具体是.
奔驰的*** + 1 感谢你的分享,无论怎样,你都是最无私的人.

查看全部评分

来自手机 | 显示全部楼层
?b,太厉害了。
回复

使用道具 举报

不明觉厉
回复

使用道具 举报

感谢分享,一看这行文就知道什么叫专业~
回复

使用道具 举报

厉害
回复

使用道具 举报

插眼,表示好多看不懂
回复

使用道具 举报

太深澳了,最好写一个转换软件,把m3u和txt直接转换成tvbox节目列表文件
回复

使用道具 举报

很好,就是有点看不懂
回复

使用道具 举报

厉害,就是看不懂
回复

使用道具 举报

大佬真厉害
回复

使用道具 举报

就是看不懂
回复

使用道具 举报

mark一下
回复

使用道具 举报

小白只有干瞪眼的份了 期待有一天能有插件
回复

使用道具 举报

需要好好思考一下
回复

使用道具 举报

太专业了,要是一键复制黏贴就好了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

欢迎大家光临恩山无线论坛上一条 /1 下一条

有疑问请添加管理员QQ86788181|手机版|小黑屋|Archiver|恩山无线论坛(常州市恩山计算机开发有限公司版权所有) ( 苏ICP备05084872号 )

GMT+8, 2024-5-16 01:43

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

| 江苏省互联网有害信息举报中心 举报信箱:js12377 | @jischina.com.cn 举报电话:025-88802724 本站不良内容举报信箱:68610888@qq.com 举报电话:0519-86695797

快速回复 返回顶部 返回列表