江苏电信IPTV直播源(RTSP认证源)在tvbox上播放(技术分析)
本帖最后由 op351 于 2023-12-5 17:46 编辑接前两篇帖子
江苏电信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源
<font size="3">String tsurl = new String(response.body().bytes(), "UTF-8");
Pattern TimeShiftURLPattern = Pattern.compile("ChannelID=\"(.*)\",ChannelName=\".*\",UserChannelID=\"\\d*\",ChannelURL=\".*\",TimeShift=\"\\d*\",ChannelSDP=\".*\",TimeShiftURL=\"(.*)\",ChannelLogURL=");
Matcher TimeShiftURLMatch = TimeShiftURLPattern.matcher(tsurl);
try {
JSONArray timeShiftJsonTemp = new JSONArray();
while (TimeShiftURLMatch.find()) {
JSONObject timet = new JSONObject();
timet.put("chid", TimeShiftURLMatch.group(1));
timet.put("rtspurl", TimeShiftURLMatch.group(2));
// tvlist += TimeShiftURLMatch.group(1) + ",";
// tvlist += TimeShiftURLMatch.group(2) + "\r\n";
timeShiftJsonTemp.put(timet);
}
timeShiftJson = timeShiftJsonTemp;
} catch (Exception e) {
}</font>保存到timeShiftJson中备用
本地EPG实现:
新建方法setepg
1.获取/iptvepg/frame1194/play_channel.jsp的返回报文 (请在第一篇江苏电信IPTV回看地址探究中保存的wireshark文件中自行查找)
2.利用正则剥离江苏电信原生频道排序信息
String chsl = new String(response.body().bytes(), "GB2312");
Pattern channelListPattern = Pattern.compile("channelAllList\":(.*),\"mixnoAllList\":");
Matcher channelListMatch = channelListPattern.matcher(chsl);
channelListMatch.find();
JSONArray channelListJson = new JSONArray(channelListMatch.group(1));3.在openwrt上新建文件/cgi-bin/epgcheck
#!/usr/bin/lua
local EpgCheck = require 'EpgCheck'
EpgCheck.Run()
4.在openwrt上新建lua模块EpgCheck
local EpgCheck = {}
function EpgCheck.Run()
io.write("Content-type: text/html\nProgma: no-cache\n\n")
local time1f = io.popen("ls -l --full-time /www/CCTV1-HD.json")
local time1 = time1f:read()
if (time1 == nil)
then
print("false")
else
local time1date = string.match(time1, '%d+-%d+-%d+')
local time2f = io.popen("date +\"%Y-%m-%d\"")
local time2 = time2f:read()
if (time1date == time2)
then
print("true")
else
print("false")
end
end
end
return EpgCheck
这个cgi的作用是减少epg的获取频次,仅在每天第一次启动tvbox时获取所有频道的EPG信息
5.建立频道分类数组
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};
List cctv = Arrays.asList(CCTV);
Integer[] JSTV = new Integer[] {17,18,19,20,21,22,23,24,25,26,83,107,108,109,110,111,113,115};
List jstv = Arrays.asList(JSTV);
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};
List dftv = Arrays.asList(DFTV);
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};
List gqtv = Arrays.asList(GQTV);6.遍历之前存储的channelListJson
6.1进行频道分类,并存储到变量tvlist中
String channelidTemp = channelListJson.getJSONObject(i).get("channelcode").toString();
String channelname = channelListJson.getJSONObject(i).get("channelname").toString();
if (!channelname.contains("HD") || channelname.contains("购物")) {
continue;
}
String columncode = channelListJson.getJSONObject(i).get("columncode").toString();
String mixno = channelListJson.getJSONObject(i).get("mixno").toString();
String realmixno = channelListJson.getJSONObject(i).get("realmixno").toString();
for (int j = 0; j < timeShiftJson.length(); j++) {
if (channelidTemp.equals(timeShiftJson.getJSONObject(j).get("chid"))) {
if (cctv.contains(i)) {
tvlist += "CCTV,#genre#" + "\r\n";
}else if (jstv.contains(i)) {
tvlist += "江苏,#genre#" + "\r\n";
}else if (dftv.contains(i)) {
tvlist += "卫视,#genre#" + "\r\n";
}else if (gqtv.contains(i)) {
tvlist += "高清,#genre#" + "\r\n";
} else {
tvlist += "其他,#genre#" + "\r\n";
}
tvlist += channelname + ",";
tvlist += timeShiftJson.getJSONObject(j).get("rtspurl") + "\r\n";
}
}6.2在进入epg爬取之前,判断路由器上是否已有epg信息,有则跳过下面的代码
client = new OkHttpClient().newBuilder()
.build();
request = new Request.Builder()
.url("http://192.168.8.1/cgi-bin/epgcheck")
.get()
.build();
response = client.newCall(request).execute();
String egresult = response.body().string().trim();
if (egresult.equals("true")) {
continue;
}6.3epg爬取
获取/iptvepg/frame1194/CHANNEL_PLAYER_UTILS/datas/prevue_list.jsp报文(请在第一篇江苏电信IPTV回看地址探究中保存的wireshark文件中自行查找)
通过正则剥离原始epg信息,并转化为tvbox可用格式
String epgjson = new String(response.body().bytes(), "GB2312");
JSONObject epg = new JSONObject(epgjson);
String epglist = epg.get("channelPrevue").toString();
JSONArray epgJsonBefore = new JSONArray(epglist);
JSONArray epgJsonAfter = new JSONArray();
for (int k = 0; k < epgJsonBefore.length(); k++) {
JSONObject epgitem = new JSONObject();
String title = epgJsonBefore.getJSONObject(k).get("prevuename").toString();
String begintimet = epgJsonBefore.getJSONObject(k).get("begintime").toString();
Pattern timePattern = Pattern.compile("\\d{4}.\\d{2}.\\d{2} (\\d{2}:\\d{2}):\\d{2}");
Matcher btimeMatch = timePattern.matcher(begintimet);
btimeMatch.find();
String begintime = btimeMatch.group(1);
String endtimet = epgJsonBefore.getJSONObject(k).get("endtime").toString();
Matcher endtimeMatch = timePattern.matcher(endtimet);
endtimeMatch.find();
String endtime = endtimeMatch.group(1);
epgitem.put("start", begintime);
epgitem.put("desc", "");
epgitem.put("end", endtime);
epgitem.put("title", title);
epgJsonAfter.put(epgitem);
}
Date now = new Date();
SimpleDateFormat ST = new SimpleDateFormat("yyyy-MM-dd");
String nowdate = ST.format(now);
JSONObject epgFinal = new JSONObject();
epgFinal.put("date", nowdate);
epgFinal.put("channel_name", channelname);
epgFinal.put("url", "");
epgFinal.put("epg_data", epgJsonAfter);
String epgFinalstring = epgFinal.toString();6.4上传epg信息到路由器
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, epgFinalstring);
request = new Request.Builder()
.url("http://192.168.8.1/cgi-bin/uploadepg")
.method("POST", body)
.addHeader("User-Agent", URLEncoder.encode(channelname))
.addHeader("Content-Type", "text/plain")
.build();
client.newCall(request).execute();6.5 /cgi-bin/uploadepg内容
#!/usr/bin/lua
local EpgJson = require 'EpgJson'
EpgJson.Run()
6.6lua模块EpgJson内容
local EpgJson = {}
require "nixio"
function EpgJson.Run()
io.write("Content-type: text/html\nProgma: no-cache\n\n")
local epgjsonbody = io.read("*all")
http_headers = nixio.getenv()
local channame = http_headers['HTTP_USER_AGENT']
file = io.open(channame .. ".json", "w")
file:write(epgjsonbody)
io.close(file)
end
return EpgJson
通过使用user-agent来传输频道名,以简化lua程序
json放置在body中,以原始text传送
最终文件生成为/www/xxx.json
在huikan方法中调用setepg
在homeContent方法中上传分类好的频道列表
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, tvlist);
Request request = new Request.Builder()
.url("http://192.168.8.1/cgi-bin/iptvfile")
.method("POST", body)
.addHeader("Content-Type", "text/plain")
.build();
client.newCall(request).execute();/cgi-bin/iptvfile内容
#!/usr/bin/lua
local WebService = require 'WebService'
WebService.Run()lua模块WebService内容
local WebService = {}
function WebService.Run()
io.write("Content-type: text/html\nProgma: no-cache\n\n")
local tvlist = io.read("*all")
print(tvlist)
file = io.open("tv.txt", "w")
file:write(tvlist)
io.close(file)
end
return WebService
最终频道分类表储存在/www/tv.txt中
接下来我们把源配置文件iptv.json和jar放置在路由器的/www目录下
在iptv.json中我们修改直播源url为本地的tv.txt
epg修改为本地cgi-bin接口getepg
/cgi-bin/getepg内容
#!/usr/bin/lua
local GetEpg = require 'GetEpg'
GetEpg.Run()
lua模块GetEpg内容
local GetEpg = {}
require "nixio"
function GetEpg.Run()
io.write("Content-type: application/json\nProgma: no-cache\n\n")
http_headers = nixio.getenv()
local qs = http_headers['QUERY_STRING']
local channame = string.match(qs, 'ch=(.*)&')
file = io.open(channame .. ".json", "r")
local content = file:read "*a"
print(content)
file:close()
end
return GetEpg
接下来我们看看实际效果
?b,太厉害了。 不明觉厉 感谢分享,一看这行文就知道什么叫专业~:lol 厉害
插眼,表示好多看不懂https://www.right.com.cn/forum//mobcent//app/data/phiz/default/13.png
太深澳了,最好写一个转换软件,把m3u和txt直接转换成tvbox节目列表文件 很好,就是有点看不懂 厉害,就是看不懂:lol 大佬真厉害 就是看不懂 mark一下 小白只有干瞪眼的份了 期待有一天能有插件 需要好好思考一下 :'( 太专业了,要是一键复制黏贴就好了
页:
[1]
2