M3U8下载器
By
jerryxjr1220
at 2021-11-07 • 0人收藏 • 1199人看过
最近网络突然变卡了,看在线视频断断续续的,没办法只能把m3u8下载下来看了.
写了个多线程下载器,有需要的可以拿去用。
PS:只针对一般未加密的m3u8视频
import win.ui;
/*DSG{{*/
mainForm = win.form(text="M3U8下载器";right=793;bottom=308;border="dialog frame";max=false)
mainForm.add(
btnAnalyze={cls="button";text="解析视频地址";left=670;top=18;right=764;bottom=46;z=12};
btnCombine={cls="button";text="合并ts";left=696;top=136;right=764;bottom=164;z=9};
btnMovieUrl={cls="button";text="视频地址:";left=28;top=20;right=129;bottom=46;z=10};
btnRClip={cls="button";text="M3U8地址:";left=27;top=59;right=128;bottom=85;z=1};
btnRun={cls="button";text="开始解析";left=607;top=136;right=675;bottom=164;z=7};
btnSaveDir={cls="button";text="保存目录";left=27;top=101;right=128;bottom=127;z=3};
edtLog={cls="edit";left=27;top=180;right=764;bottom=295;edge=1;hscroll=1;multiline=1;vscroll=1;z=8};
edtM3U8url={cls="edit";left=149;top=57;right=764;bottom=85;edge=1;multiline=1;z=2};
edtMovieUrl={cls="edit";left=150;top=18;right=658;bottom=46;edge=1;multiline=1;z=11};
edtName={cls="edit";left=149;top=136;right=584;bottom=164;edge=1;multiline=1;z=6};
edtSaveDir={cls="edit";left=149;top=97;right=764;bottom=125;edge=1;multiline=1;z=4};
static={cls="static";text="电影名称(可选)";left=27;top=143;right=145;bottom=164;transparent=1;z=5}
)
/*}}*/
import fsys;
import fsys.ini;
import fsys.file;
import fsys.dlg;
import win.clip;
import inet.http;
import thread;
import thread.command;
listener = thread.command();
listener.res_print = function(...){
mainForm.edtLog.print(...);
}
ini = fsys.ini("/m3u8.ini");
cfg = ini.getSection("M3U8");
var url = cfg.url;
if url {
mainForm.edtM3U8url.text = url;
};
var savedir = cfg.savedir;
if savedir {
mainForm.edtSaveDir.text = savedir;
}
var movie = cfg.movie;
if movie {
mainForm.edtName.text = movie;
}
var movieurl = cfg.movieurl;
if movieurl {
mainForm.edtMovieUrl.text = movieurl;
}
mainForm.running = false;
mainForm.btnRClip.oncommand = function(id,event){
var url = win.clip.read();
if url {
import inet.url;
if inet.url.is(url,0x0/*_URLIS_URL*/) and ..string.endWith(url, "m3u8") {
mainForm.edtM3U8url.text = url;
mainForm.edtLog.print("粘贴M3U8文件URL")
} else {
mainForm.edtLog.print("剪切板中的文字不是有效的M3U8文件的URL!")
}
} else {
mainForm.edtLog.print("请先复制M3U8文件URL至剪切板!")
}
}
mainForm.btnSaveDir.oncommand = function(id,event){
var fs = fsys.dlg.opendir();
if fs {
mainForm.edtSaveDir.text = fs;
mainForm.edtLog.print("设置保存目录成功!")
}
}
mainForm.btnRun.oncommand = function(id,event){
if ..string.len(mainForm.edtM3U8url.text)<1 {
mainForm.edtLog.print("请先复制M3U8文件URL至剪切板!")
return;
}
if !inet.url.is(mainForm.edtM3U8url.text,0x0/*_URLIS_URL*/) {
mainForm.edtLog.print("此index.m3u8的URL无效!")
return;
}
if ..string.len(mainForm.edtSaveDir.text)<1 {
var fs = ..io.fullpath("/")
mainForm.edtSaveDir.text = fs;
mainForm.edtLog.print("保存目录默认设置为:",fs);
}
if ..string.len(mainForm.edtName.text)<1 {
import time.ole;
var tm = ..math.floor(tonumber(time.ole())*1000000);
mainForm.edtName.text = tm;
mainForm.edtLog.print("默认名称为:",tm);
}
tsdir = ..string.trim(mainForm.edtSaveDir.text,"\")++"\"++mainForm.edtName.text;
http = inet.http("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3877.400 QQBrowser/10.8.4506.400",false)
var res = http.get(mainForm.edtM3U8url.text);
if res and ..string.startWith(res, "#EXTM3U") {
..string.save(..string.trim(tsdir,"\")++"\"++"index.m3u8", res);
mainForm.edtLog.print("下载M3U8文件成功!");
} else {
mainForm.edtLog.print("下载M3U8文件失败,请重新尝试!");
return;
}
host = ..string.join(..table.slice(..string.splitEx(mainForm.edtM3U8url.text,"/"),1,#..string.splitEx(mainForm.edtM3U8url.text,"/")-1),"/")
tslist = {};
for line in ..string.lines(res) {
if ..string.startWith(line, "#EXT") {
continue;
} else {
if !..string.startWith(line, "http") {
line = host ++ "/" ++ line;
}
if ..string.endWith(line, "ts") {
..table.push(tslist, line);
} else {
mainForm.edtLog.print("不是ts文件,视频可能被加密");
return;
}
}
}
mainForm.edtLog.printf("M3U8文件解析成功,共有%d个片段", #tslist);
cfg.url = mainForm.edtM3U8url.text;
cfg.savedir = mainForm.edtSaveDir.text;
cfg.movie = mainForm.edtName.text;
cfg.movieurl = mainForm.edtMovieUrl.text;
cfg.save();
fsys.createDir(tsdir);
mainForm.edtLog.print("创建目录:", tsdir);
mainForm.edtLog.print("下载开始......");
//创建下载线程管理器
import thread.dlManager;
dlmgr = thread.dlManager(5/*最多允许五个线程同时下载*/);
mainForm.running = true;
for i,url in tslist {
if !mainForm.running {
break;
}
//响应下载事件
dlmgr.onReceiveBegin = function(id,url,filename,statusText,httpStatusCode,totalSize,downSize){
//mainForm.edtLog.print( "片段"++id,statusText,url,"->",filename,fsys.formatSize(totalSize) )
}
dlmgr.onReceive = function(id,sizePs,downSize){
//mainForm.edtLog.print( "片段"++id, fsys.formatSize(downSize),fsys.formatSize(sizePs) + "/s");
}
dlmgr.onEnd = function(id,savepath,resumePath,contentLength){
if( savepath ){
var rpt = ..math.floor(id/#tslist*70);
mainForm.edtLog.text="|"++..string.repeat(rpt, ">")++..string.repeat(70-rpt, "#")++"| 片段"++id++".ts已完成";
}
else {
mainForm.edtLog.text="|"++..string.repeat(rpt, ">")++..string.repeat(70-rpt, "#")++"| 片段"++id++".ts已停止";
}
//fsys.delete(resumePath)
}
dlmgr.onError = function(id,err){
mainForm.edtLog.print("片段"++id,err);
}
if ..io.exist(tsdir++"\"++i++".ts") {
var rpt = ..math.floor(i/#tslist*70);
mainForm.edtLog.text="|"++..string.repeat(rpt, ">")++..string.repeat(70-rpt, "#")++"| 片段"++i++".ts 已存在";
win.delay(30)
continue;
}
//添加下载任务非常简单,push下载参数就可以了
dlmgr.push(
id = i;
url = url;
filename=i++".ts"; //文件名可以省略
savedir = tsdir;
)
win.delay(50);
}
}
import thread.event;
mainForm.onClose = function(hwnd,message,wParam,lParam){
mainForm.text = "正在等待关闭";
mainForm.running = false;
if dlmgr {
dlmgr.quit();
}
}
mainForm.btnCombine.oncommand = function(id,event){
if ..string.len(mainForm.edtSaveDir.text)<1 {
var fs = ..io.fullpath("/")
mainForm.edtSaveDir.text = fs;
mainForm.edtLog.print("保存目录默认设置为:",fs);
}
if ..string.len(mainForm.edtName.text)<1 {
import time.ole;
var tm = ..math.floor(tonumber(time.ole())*1000000);
mainForm.edtName.text = tm;
mainForm.edtLog.print("默认名称为:",tm);
}
tsdir = ..string.trim(mainForm.edtSaveDir.text,"\")++"\"++mainForm.edtName.text;
if !..io.exist(..string.trim(tsdir,"\")++"\"++"index.m3u8") {
mainForm.edtLog.print("index.m3u8下载未完成,无法合并!")
return;
}
res = ..string.load(..string.trim(tsdir,"\")++"\"++"index.m3u8");
tslist = {};
for line in ..string.lines(res) {
if ..string.startWith(line, "#EXT") {
continue;
} else {
if ..string.endWith(line, "ts") {
..table.push(tslist, line);
}
}
}
if !..io.exist(tsdir++"\"++#tslist++".ts") {
mainForm.edtLog.print("下载未完成,无法合并!")
return;
}
mainForm.edtLog.print("开始合并ts文件:", tsdir++"\"++mainForm.edtName.text++".mp4");
f = fsys.file(tsdir++"\"++mainForm.edtName.text++".mp4","a+b");
for i=1;#tslist {
try {
tf = fsys.file(tsdir++"\"++i++".ts", "rb");
f.write(tf.readAll());
tf.close();
} catch (e) {
mainForm.edtLog.print(e);
}
var rpt = ..math.floor(i/#tslist*70);
mainForm.edtLog.text="|"++..string.repeat(rpt, ">")++..string.repeat(70-rpt, "#")++"| 片段"++i++".ts 已写入";
win.delay(20);
}
f.close();
mainForm.edtLog.print("ts文件合并完成!",tsdir++"\"++mainForm.edtName.text++".mp4")
}
mainForm.btnMovieUrl.oncommand = function(id,event){
var url = win.clip.read();
if url {
import inet.url;
if inet.url.is(url,0x0/*_URLIS_URL*/) {
mainForm.edtMovieUrl.text = url;
mainForm.edtLog.print("粘贴视频URL")
} else {
mainForm.edtLog.print("剪切板中的文字不是有效的视频URL!")
}
} else {
mainForm.edtLog.print("请先复制视频URL至剪切板!")
}
}
mainForm.btnAnalyze.oncommand = function(id,event){
if ..string.len(mainForm.edtMovieUrl.text)<1 {
mainForm.edtLog.print("请先复制视频URL至剪切板!")
return;
}
if !inet.url.is(mainForm.edtMovieUrl.text,0x0/*_URLIS_URL*/) {
mainForm.edtLog.print("此视频URL无效!")
return;
}
mainForm.edtLog.print("开始解析视频URL...")
cfg.movieurl = mainForm.edtMovieUrl.text;
cfg.save();
var mhttp = inet.http("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3877.400 QQBrowser/10.8.4506.400",false)
var res = mhttp.get(mainForm.edtMovieUrl.text);
var m3u8s = ..string.matches(res, `(https*\:[^\"]+?index\.m3u8)`);
var moviename = ..string.match(res, `vod_name\'\s*\:\s*\"([^\"]+?)\"`);
if moviename {
mainForm.edtLog.print("视频名称:",moviename)
mainForm.edtName.text = ..string.replace(moviename, "\s","");
}
if ..table.len(m3u8s)>=1 {
mainForm.edtLog.print("找到如下index.m3u8的URL:")
mainForm.edtM3U8url.text = ..string.replace(m3u8s[1][1],"\\","");
}
for k,v in m3u8s {
var s = ..string.replace(v[1],"\\","")
mainForm.edtLog.print(s);
}
}
mainForm.show();
return win.loopMessage();
4 个回复 | 最后更新于 2021-11-08
2021-11-08
#2
改进了一下,现在可以自动识别是否是aes加密,并自动进行解密。
import win.ui;
/*DSG{{*/
mainForm = win.form(text="M3U8下载器";right=793;bottom=308;border="dialog frame";max=false)
mainForm.add(
btnAnalyze={cls="button";text="解析视频地址";left=670;top=18;right=764;bottom=46;z=12};
btnCombine={cls="button";text="合并ts";left=696;top=136;right=764;bottom=164;z=9};
btnMovieUrl={cls="button";text="视频地址:";left=28;top=20;right=129;bottom=46;z=10};
btnRClip={cls="button";text="M3U8地址:";left=27;top=59;right=128;bottom=85;z=1};
btnRun={cls="button";text="开始解析";left=607;top=136;right=675;bottom=164;z=7};
btnSaveDir={cls="button";text="保存目录";left=27;top=101;right=128;bottom=127;z=3};
edtLog={cls="edit";left=27;top=180;right=764;bottom=295;edge=1;hscroll=1;multiline=1;vscroll=1;z=8};
edtM3U8url={cls="edit";left=149;top=57;right=764;bottom=85;edge=1;multiline=1;z=2};
edtMovieUrl={cls="edit";left=150;top=18;right=658;bottom=46;edge=1;multiline=1;z=11};
edtName={cls="edit";left=149;top=136;right=584;bottom=164;edge=1;multiline=1;z=6};
edtSaveDir={cls="edit";left=149;top=97;right=764;bottom=125;edge=1;multiline=1;z=4};
static={cls="static";text="电影名称(可选)";left=27;top=143;right=145;bottom=164;transparent=1;z=5}
)
/*}}*/
import fsys;
import fsys.ini;
import fsys.file;
import fsys.dlg;
import win.clip;
import inet.http;
import thread;
import thread.command;
listener = thread.command();
listener.res_print = function(...){
mainForm.edtLog.print(...);
}
ini = fsys.ini("/m3u8.ini");
cfg = ini.getSection("M3U8");
var url = cfg.url;
if url {
mainForm.edtM3U8url.text = url;
};
var savedir = cfg.savedir;
if savedir {
mainForm.edtSaveDir.text = savedir;
}
var movie = cfg.movie;
if movie {
mainForm.edtName.text = movie;
}
var movieurl = cfg.movieurl;
if movieurl {
mainForm.edtMovieUrl.text = movieurl;
}
mainForm.running = false;
mainForm.btnRClip.oncommand = function(id,event){
var url = win.clip.read();
if url {
import inet.url;
if inet.url.is(url,0x0/*_URLIS_URL*/) and ..string.endWith(url, "m3u8") {
mainForm.edtM3U8url.text = url;
mainForm.edtLog.print("粘贴M3U8文件URL")
} else {
mainForm.edtLog.print("剪切板中的文字不是有效的M3U8文件的URL!")
}
} else {
mainForm.edtLog.print("请先复制M3U8文件URL至剪切板!")
}
}
mainForm.btnSaveDir.oncommand = function(id,event){
var fs = fsys.dlg.opendir();
if fs {
mainForm.edtSaveDir.text = fs;
mainForm.edtLog.print("设置保存目录成功!")
}
}
mainForm.btnRun.oncommand = function(id,event){
if ..string.len(mainForm.edtM3U8url.text)<1 {
mainForm.edtLog.print("请先复制M3U8文件URL至剪切板!")
return;
}
if !inet.url.is(mainForm.edtM3U8url.text,0x0/*_URLIS_URL*/) {
mainForm.edtLog.print("此index.m3u8的URL无效!")
return;
}
if ..string.len(mainForm.edtSaveDir.text)<1 {
var fs = ..io.fullpath("/")
mainForm.edtSaveDir.text = fs;
mainForm.edtLog.print("保存目录默认设置为:",fs);
}
if ..string.len(mainForm.edtName.text)<1 {
import time.ole;
var tm = ..math.floor(tonumber(time.ole())*1000000);
mainForm.edtName.text = tm;
mainForm.edtLog.print("默认名称为:",tm);
}
tsdir = ..string.trim(mainForm.edtSaveDir.text,"\")++"\"++mainForm.edtName.text;
http = inet.http("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3877.400 QQBrowser/10.8.4506.400",false)
var res = http.get(mainForm.edtM3U8url.text);
if res and ..string.startWith(res, "#EXTM3U") {
..string.save(..string.trim(tsdir,"\")++"\"++"index.m3u8", res);
mainForm.edtLog.print("下载M3U8文件成功!");
} else {
mainForm.edtLog.print("下载M3U8文件失败,请重新尝试!");
return;
}
tslist = {};
for line in ..string.lines(res) {
if ..string.startWith(line, "#EXT") {
var keyurl = ..string.match(line, `URI\s*\=\s*\"(http.*?key\.key)`);
if keyurl {
var key = http.get(keyurl);
..string.save(..string.trim(tsdir,"\")++"\"++"key.key", key);
}
continue;
} else {
if ..string.endWith(line, "ts") {
..table.push(tslist, line);
} else {
if ..string.len(line)<1 {
continue;
}
mainForm.edtLog.print(line);
mainForm.edtLog.print("不是ts文件,视频可能被加密");
return;
}
}
}
mainForm.edtLog.printf("M3U8文件解析成功,共有%d个片段", #tslist);
cfg.url = mainForm.edtM3U8url.text;
cfg.savedir = mainForm.edtSaveDir.text;
cfg.movie = mainForm.edtName.text;
cfg.movieurl = mainForm.edtMovieUrl.text;
cfg.save();
fsys.createDir(tsdir);
mainForm.edtLog.print("创建目录:", tsdir);
mainForm.edtLog.print("下载开始......");
//创建下载线程管理器
import thread.dlManager;
dlmgr = thread.dlManager(5/*最多允许五个线程同时下载*/);
mainForm.running = true;
for i,url in tslist {
if !mainForm.running {
break;
}
//响应下载事件
dlmgr.onReceiveBegin = function(id,url,filename,statusText,httpStatusCode,totalSize,downSize){
//mainForm.edtLog.print( "片段"++id,statusText,url,"->",filename,fsys.formatSize(totalSize) )
}
dlmgr.onReceive = function(id,sizePs,downSize){
//mainForm.edtLog.print( "片段"++id, fsys.formatSize(downSize),fsys.formatSize(sizePs) + "/s");
}
dlmgr.onEnd = function(id,savepath,resumePath,contentLength){
if( savepath ){
var rpt = ..math.floor(id/#tslist*70);
mainForm.edtLog.text="|"++..string.repeat(rpt, ">")++..string.repeat(70-rpt, "#")++"| 片段"++id++".ts已完成";
}
else {
mainForm.edtLog.text="|"++..string.repeat(rpt, ">")++..string.repeat(70-rpt, "#")++"| 片段"++id++".ts已停止";
}
//fsys.delete(resumePath)
}
dlmgr.onError = function(id,err){
mainForm.edtLog.print("片段"++id,err);
}
if ..io.exist(tsdir++"\"++i++".ts") {
var rpt = ..math.floor(i/#tslist*70);
mainForm.edtLog.text="|"++..string.repeat(rpt, ">")++..string.repeat(70-rpt, "#")++"| 片段"++i++".ts 已存在";
win.delay(30)
continue;
}
//添加下载任务非常简单,push下载参数就可以了
dlmgr.push(
id = i;
url = url;
filename=i++".ts"; //文件名可以省略
savedir = tsdir;
)
win.delay(50);
}
}
import thread.event;
mainForm.onClose = function(hwnd,message,wParam,lParam){
mainForm.text = "正在等待关闭";
mainForm.running = false;
if dlmgr {
dlmgr.quit();
}
}
mainForm.btnCombine.oncommand = function(id,event){
http = inet.http("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3877.400 QQBrowser/10.8.4506.400",false)
if ..string.len(mainForm.edtSaveDir.text)<1 {
var fs = ..io.fullpath("/")
mainForm.edtSaveDir.text = fs;
mainForm.edtLog.print("保存目录默认设置为:",fs);
}
if ..string.len(mainForm.edtName.text)<1 {
import time.ole;
var tm = ..math.floor(tonumber(time.ole())*1000000);
mainForm.edtName.text = tm;
mainForm.edtLog.print("默认名称为:",tm);
}
tsdir = ..string.trim(mainForm.edtSaveDir.text,"\")++"\"++mainForm.edtName.text;
if !..io.exist(..string.trim(tsdir,"\")++"\"++"index.m3u8") {
mainForm.edtLog.print("index.m3u8下载未完成,无法合并!")
return;
}
res = ..string.load(..string.trim(tsdir,"\")++"\"++"index.m3u8");
tslist = {};
for line in ..string.lines(res) {
if ..string.startWith(line, "#EXT") {
var keyurl = ..string.match(line, `URI\s*\=\s*\"(http.*?key\.key)`);
if keyurl {
var key = http.get(keyurl);
..string.save(..string.trim(tsdir,"\")++"\"++"key.key", key);
}
continue;
} else {
if ..string.endWith(line, "ts") {
..table.push(tslist, line);
}
}
}
if !..io.exist(tsdir++"\"++#tslist++".ts") {
mainForm.edtLog.print("下载未完成,无法合并!")
return;
}
mainForm.edtLog.print("开始合并ts文件:", tsdir++"\"++mainForm.edtName.text++".mp4");
f = fsys.file(tsdir++"\"++mainForm.edtName.text++".mp4","a+b");
if ..io.exist(..string.trim(tsdir,"\")++"\"++"key.key") {
import crypt.aes;
aes = crypt.aes();
var fkey = ..io.open(..string.trim(tsdir,"\")++"\"++"key.key","r");
aes.setPassword(fkey.read(-1));
fkey.close();
for i=1;#tslist {
try {
tf = fsys.file(tsdir++"\"++i++".ts", "rb");
f.write(aes.decrypt(tf.readAll()));
tf.close();
} catch (e) {
mainForm.edtLog.print(e);
}
var rpt = ..math.floor(i/#tslist*70);
mainForm.edtLog.text="|"++..string.repeat(rpt, ">")++..string.repeat(70-rpt, "#")++"| 片段"++i++".ts 已写入";
win.delay(20);
}
} else {
for i=1;#tslist {
try {
tf = fsys.file(tsdir++"\"++i++".ts", "rb");
f.write(tf.readAll());
tf.close();
} catch (e) {
mainForm.edtLog.print(e);
}
var rpt = ..math.floor(i/#tslist*70);
mainForm.edtLog.text="|"++..string.repeat(rpt, ">")++..string.repeat(70-rpt, "#")++"| 片段"++i++".ts 已写入";
win.delay(20);
}
}
f.close();
mainForm.edtLog.text = null;
mainForm.edtLog.print("ts文件合并完成!",tsdir++"\"++mainForm.edtName.text++".mp4")
}
mainForm.btnMovieUrl.oncommand = function(id,event){
var url = win.clip.read();
if url {
import inet.url;
if inet.url.is(url,0x0/*_URLIS_URL*/) {
mainForm.edtMovieUrl.text = url;
mainForm.edtLog.print("粘贴视频URL")
} else {
mainForm.edtLog.print("剪切板中的文字不是有效的视频URL!")
}
} else {
mainForm.edtLog.print("请先复制视频URL至剪切板!")
}
}
mainForm.btnAnalyze.oncommand = function(id,event){
if ..string.len(mainForm.edtMovieUrl.text)<1 {
mainForm.edtLog.print("请先复制视频URL至剪切板!")
return;
}
if !inet.url.is(mainForm.edtMovieUrl.text,0x0/*_URLIS_URL*/) {
mainForm.edtLog.print("此视频URL无效!")
return;
}
mainForm.edtLog.print("开始解析视频URL...")
cfg.movieurl = mainForm.edtMovieUrl.text;
cfg.save();
var mhttp = inet.http("Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3877.400 QQBrowser/10.8.4506.400",false)
var res = mhttp.get(mainForm.edtMovieUrl.text);
var m3u8s = ..string.matches(res, `(https*\:[^\"]+?index\.m3u8)`);
var moviename = ..string.match(res, `vod_name\'\s*\:\s*\"([^\"]+?)\"`);
if moviename {
mainForm.edtLog.print("视频名称:",moviename)
mainForm.edtName.text = ..string.replace(moviename, "\s","");
}
if ..table.len(m3u8s)>=1 {
mainForm.edtLog.print("找到如下index.m3u8的URL:")
mainForm.edtM3U8url.text = ..string.replace(m3u8s[1][1],"\\","");
} else {
mainForm.edtLog.print("未找到index.m3u8,请确认是否是有效的URL!")
}
for k,v in m3u8s {
var s = ..string.replace(v[1],"\\","")
mainForm.edtLog.print(s);
}
}
mainForm.show();
return win.loopMessage();登录后方可回帖


我是主要针对 https://www.bk520.com/ 上面的视频进行解析,不保证适用所有的m3u8文件