Fixed Downloading
This commit is contained in:
parent
96944392d7
commit
63a1f5913d
2 changed files with 132 additions and 60 deletions
187
funi.js
187
funi.js
|
|
@ -17,6 +17,8 @@ const shlp = require('sei-helper');
|
||||||
const { lookpath } = require('lookpath');
|
const { lookpath } = require('lookpath');
|
||||||
const m3u8 = require('m3u8-parsed');
|
const m3u8 = require('m3u8-parsed');
|
||||||
const streamdl = require('hls-download');
|
const streamdl = require('hls-download');
|
||||||
|
const crypto = require("crypto");
|
||||||
|
const got = require('got');
|
||||||
|
|
||||||
// extra
|
// extra
|
||||||
const modulesFolder = __dirname + '/modules';
|
const modulesFolder = __dirname + '/modules';
|
||||||
|
|
@ -524,6 +526,7 @@ async function downloadStreams(){
|
||||||
let dlFailed = false;
|
let dlFailed = false;
|
||||||
let dlFailedA = false;
|
let dlFailedA = false;
|
||||||
|
|
||||||
|
|
||||||
if (!argv.novids) {
|
if (!argv.novids) {
|
||||||
// download video
|
// download video
|
||||||
let reqVideo = await getData({
|
let reqVideo = await getData({
|
||||||
|
|
@ -536,37 +539,86 @@ async function downloadStreams(){
|
||||||
let chunkList = m3u8(reqVideo.res.body);
|
let chunkList = m3u8(reqVideo.res.body);
|
||||||
chunkList.baseUrl = videoUrl.split('/').slice(0, -1).join('/') + '/';
|
chunkList.baseUrl = videoUrl.split('/').slice(0, -1).join('/') + '/';
|
||||||
|
|
||||||
let proxyHLS = false;
|
|
||||||
if (argv.proxy && !argv.ssp) {
|
|
||||||
try {
|
|
||||||
proxyHLS = {};
|
|
||||||
proxyHLS.url = buildProxyUrl(argv.proxy, argv['proxy-auth']);
|
|
||||||
}
|
|
||||||
catch(e){
|
|
||||||
console.log(`\n[WARN] Not valid proxy URL${e.input?' ('+e.input+')':''}!`);
|
|
||||||
console.log('[WARN] Skiping...');
|
|
||||||
proxyHLS = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let tsFile = path.join(cfg.dir.content, fnOutput);
|
let tsFile = path.join(cfg.dir.content, fnOutput);
|
||||||
|
|
||||||
let streamdlParams = {
|
if (chunkList.segments[0].uri.match(/streaming_video_(\d+)_(\d+)_(\d+)\.ts/)) {
|
||||||
fn: tsFile + '.ts',
|
if (fs.existsSync(tsFile + '.ts')) {
|
||||||
m3u8json: chunkList,
|
let rwts = await shlp.question(`[Q] File «${tsFile + '.ts'}» already exists! Rewrite? (y/N)`);
|
||||||
baseurl: chunkList.baseUrl,
|
rwts = rwts || 'N';
|
||||||
pcount: 10,
|
if (!['Y', 'y'].includes(rwts[0])) {
|
||||||
proxy: (proxyHLS ? proxyHLS : false)
|
return;
|
||||||
};
|
}
|
||||||
|
fs.unlinkSync(tsFile + '.ts')
|
||||||
let dldata = await new streamdl(streamdlParams).download();
|
}
|
||||||
if(!dldata.ok){
|
|
||||||
fs.writeFileSync(`${tsFile}.ts.resume`, JSON.stringify(dldata.parts));
|
let chunk = chunkList.segments[0]
|
||||||
console.log(`[ERROR] DL Stats: ${JSON.stringify(dldata.parts)}\n`);
|
|
||||||
dlFailed = true;
|
let reqKey = await getData({
|
||||||
}
|
url: chunk.key.uri,
|
||||||
else if(fs.existsSync(`${tsFile}.ts.resume`) && dldata.ok){
|
responseType: 'buffer'
|
||||||
fs.unlinkSync(`${tsFile}.ts.resume`);
|
})
|
||||||
|
if (!reqKey.ok) { return; }
|
||||||
|
let key = reqKey.res.body;
|
||||||
|
let iv = Buffer.alloc(16);
|
||||||
|
let ivs = chunk.key.iv ? chunk.key.iv : [0, 0, 0, 1];
|
||||||
|
for (let i in ivs) {
|
||||||
|
iv.writeUInt32BE(ivs[i], i * 4);
|
||||||
|
}
|
||||||
|
key = crypto.createDecipheriv('aes-128-cbc', key, iv);
|
||||||
|
|
||||||
|
let last = 0;
|
||||||
|
|
||||||
|
let res = (await got({
|
||||||
|
url: chunk.uri,
|
||||||
|
headers: {
|
||||||
|
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:70.0) Gecko/20100101 Firefox/70.0',
|
||||||
|
},
|
||||||
|
responseType: 'buffer'
|
||||||
|
}).on("downloadProgress", (pro) => {
|
||||||
|
if (pro.percent.toFixed(2) * 100 > last + 5) {
|
||||||
|
console.log(`[INFO] Downloaded ${pro.percent.toFixed(2) * 100}%`);
|
||||||
|
last = pro.percent.toFixed(2) * 100;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => console.log(`[ERROR] ${error.name}: ${error.code||error.message}`)))
|
||||||
|
|
||||||
|
if (!res.body) { return; }
|
||||||
|
let dec = key.update(res.body);
|
||||||
|
dec = Buffer.concat([dec, key.final()]);
|
||||||
|
fs.writeFileSync(tsFile + '.ts', dec)
|
||||||
|
|
||||||
|
console.log(`[INFO] Finished ${tsFile}`)
|
||||||
|
} else {
|
||||||
|
let proxyHLS = false;
|
||||||
|
if (argv.proxy && !argv.ssp) {
|
||||||
|
try {
|
||||||
|
proxyHLS = {};
|
||||||
|
proxyHLS.url = buildProxyUrl(argv.proxy, argv['proxy-auth']);
|
||||||
|
}
|
||||||
|
catch(e){
|
||||||
|
console.log(`\n[WARN] Not valid proxy URL${e.input?' ('+e.input+')':''}!`);
|
||||||
|
console.log('[WARN] Skiping...');
|
||||||
|
proxyHLS = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let streamdlParams = {
|
||||||
|
fn: tsFile + '.ts',
|
||||||
|
m3u8json: chunkList,
|
||||||
|
baseurl: chunkList.baseUrl,
|
||||||
|
pcount: 10,
|
||||||
|
proxy: (proxyHLS ? proxyHLS : false)
|
||||||
|
};
|
||||||
|
|
||||||
|
let dldata = await new streamdl(streamdlParams).download();
|
||||||
|
if(!dldata.ok){
|
||||||
|
fs.writeFileSync(`${tsFile}.ts.resume`, JSON.stringify(dldata.parts));
|
||||||
|
console.log(`[ERROR] DL Stats: ${JSON.stringify(dldata.parts)}\n`);
|
||||||
|
dlFailed = true;
|
||||||
|
}
|
||||||
|
else if(fs.existsSync(`${tsFile}.ts.resume`) && dldata.ok){
|
||||||
|
fs.unlinkSync(`${tsFile}.ts.resume`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
|
@ -584,39 +636,56 @@ async function downloadStreams(){
|
||||||
|
|
||||||
let chunkListA = m3u8(reqAudio.res.body);
|
let chunkListA = m3u8(reqAudio.res.body);
|
||||||
chunkListA.baseUrl = plAud.uri.split('/').slice(0, -1).join('/') + '/';
|
chunkListA.baseUrl = plAud.uri.split('/').slice(0, -1).join('/') + '/';
|
||||||
|
|
||||||
let proxyHLS = false;
|
|
||||||
if (argv.proxy && !argv.ssp) {
|
|
||||||
try {
|
|
||||||
proxyHLS = {};
|
|
||||||
proxyHLS.url = buildProxyUrl(argv.proxy, argv['proxy-auth']);
|
|
||||||
}
|
|
||||||
catch(e){
|
|
||||||
console.log(`\n[WARN] Not valid proxy URL${e.input?' ('+e.input+')':''}!`);
|
|
||||||
console.log('[WARN] Skiping...');
|
|
||||||
proxyHLS = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let tsFileA = path.join(cfg.dir.content, fnOutput + `.${plAud.language}`);
|
let tsFileA = path.join(cfg.dir.content, fnOutput + `.${plAud.language}`);
|
||||||
|
|
||||||
let streamdlParamsA = {
|
if (fs.existsSync(tsFileA + '.ts')) {
|
||||||
fn: tsFileA + '.ts',
|
let rwts = await shlp.question(`[Q] File «${tsFileA + '.ts'}» already exists! Rewrite? (y/N)`);
|
||||||
m3u8json: chunkListA,
|
rwts = rwts || 'N';
|
||||||
baseurl: chunkListA.baseUrl,
|
if (!['Y', 'y'].includes(rwts[0])) {
|
||||||
pcount: 10,
|
return;
|
||||||
proxy: (proxyHLS ? proxyHLS : false)
|
}
|
||||||
};
|
fs.unlinkSync(tsFileA + '.ts')
|
||||||
|
|
||||||
let dldataA = await new streamdl(streamdlParamsA).download();
|
|
||||||
if(!dldataA.ok){
|
|
||||||
fs.writeFileSync(`${tsFileA}.ts.resume`, JSON.stringify(dldataA.parts));
|
|
||||||
console.log(`[ERROR] DL Stats: ${JSON.stringify(dldataA.parts)}\n`);
|
|
||||||
dlFailedA = true;
|
|
||||||
}
|
}
|
||||||
else if(fs.existsSync(`${tsFileA}.ts.resume`) && dldataA.ok){
|
|
||||||
fs.unlinkSync(`${tsFileA}.ts.resume`);
|
let chunk = chunkListA.segments[0]
|
||||||
|
|
||||||
|
let reqKey = await getData({
|
||||||
|
url: chunk.key.uri,
|
||||||
|
responseType: 'buffer'
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!reqKey.ok) { return; }
|
||||||
|
let key = reqKey.res.body;
|
||||||
|
let iv = Buffer.alloc(16);
|
||||||
|
let ivs = chunk.key.iv ? chunk.key.iv : [0, 0, 0, 1];
|
||||||
|
for (let i in ivs) {
|
||||||
|
iv.writeUInt32BE(ivs[i], i * 4);
|
||||||
}
|
}
|
||||||
|
key = crypto.createDecipheriv('aes-128-cbc', key, iv);
|
||||||
|
|
||||||
|
let last = 0;
|
||||||
|
|
||||||
|
let res = (await got({
|
||||||
|
url: chunk.uri,
|
||||||
|
headers: {
|
||||||
|
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:70.0) Gecko/20100101 Firefox/70.0',
|
||||||
|
},
|
||||||
|
responseType: 'buffer'
|
||||||
|
}).on("downloadProgress", (pro) => {
|
||||||
|
if (pro.percent.toFixed(2) * 100 > last + 5) {
|
||||||
|
console.log(`[INFO] Downloaded ${pro.percent.toFixed(2) * 100}%`);
|
||||||
|
last = pro.percent.toFixed(2) * 100;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => console.log(`[ERROR] ${error.name}: ${error.code||error.message}`)))
|
||||||
|
|
||||||
|
if (!res.body) { return; }
|
||||||
|
let dec = key.update(res.body);
|
||||||
|
dec = Buffer.concat([dec, key.final()]);
|
||||||
|
fs.writeFileSync(tsFileA + '.ts', dec)
|
||||||
|
|
||||||
|
console.log(`[INFO] Finished ${tsFileA}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add subs
|
// add subs
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,9 @@ const getData = async (options) => {
|
||||||
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:70.0) Gecko/20100101 Firefox/70.0',
|
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:70.0) Gecko/20100101 Firefox/70.0',
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
if(options.responseType) {
|
||||||
|
gOptions.responseType = options.responseType
|
||||||
|
}
|
||||||
if(options.baseUrl){
|
if(options.baseUrl){
|
||||||
gOptions.prefixUrl = options.baseUrl;
|
gOptions.prefixUrl = options.baseUrl;
|
||||||
gOptions.url = gOptions.url.replace(/^\//,'');
|
gOptions.url = gOptions.url.replace(/^\//,'');
|
||||||
|
|
@ -41,7 +44,7 @@ const getData = async (options) => {
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
let res = await got(gOptions);
|
let res = await got(gOptions);
|
||||||
if(res.body && res.body.match(/^</)){
|
if(res.body && (options.responseType !== 'buffer' && res.body.match(/^</))){
|
||||||
throw { name: 'HTMLError', res };
|
throw { name: 'HTMLError', res };
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue