Merge branch 'master' into master
This commit is contained in:
commit
370cff37e3
14 changed files with 880 additions and 649 deletions
|
|
@ -1,2 +1,2 @@
|
|||
ffmpeg: "./bin/ffmpeg"
|
||||
mkvmerge: "./bin/mkvmerge"
|
||||
ffmpeg: "C:\\Program Files\\ffmpeg\\bin\\ffmpeg.exe"
|
||||
mkvmerge: "./bin/mkvtoolnix/mkvmerge.exe"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
releaseGroup: Funimation
|
||||
videoLayer: 7
|
||||
fileSuffix: SIZEp
|
||||
nServer: 1
|
||||
mp4mux: false
|
||||
muxSubs: false
|
||||
|
|
|
|||
|
|
@ -1,2 +1 @@
|
|||
content: ./videos/
|
||||
trash: ./videos/_trash/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
## Change Log
|
||||
|
||||
This changelog is out of date and wont be continued. Please see the releases comments, or if not present the commit comments.
|
||||
|
||||
### 4.7.0 (unreleased)
|
||||
- Change subtitles parser from ttml to vtt
|
||||
- Improve help command
|
||||
|
|
|
|||
|
|
@ -42,15 +42,20 @@ After installing NodeJS with NPM go to directory with `package.json` file and ty
|
|||
|
||||
* `-s <i> -e <s>` sets the show id and episode ids (comma-separated, hyphen-sequence)
|
||||
* `-q <i>` sets the video layer quality [1...10] (optional, 0 is max)
|
||||
* `--all` download all videos at once
|
||||
* `--alt` alternative episode listing (if available)
|
||||
* `--sub` switch from English dub to Japanese dub with subtitles
|
||||
* `--sub` select one or more subtile language
|
||||
* `--dub` select one or more dub languages
|
||||
* `--simul` force select simulcast version instead of uncut version
|
||||
* `-x` select server
|
||||
* `--novids` skip download videos (for downloading subtitles only)
|
||||
* `--novids` skip download videos
|
||||
* `--nosubs` skip download subtitles for Dub (if available)
|
||||
* `--noaudio` skip downloading audio
|
||||
|
||||
### Proxy
|
||||
|
||||
The proxy is currently unmainted. Use at your on risk.
|
||||
|
||||
* `--proxy <s>` http(s)/socks proxy WHATWG url (ex. https://myproxyhost:1080)
|
||||
* `--proxy-auth <s>` Colon-separated username and password for proxy
|
||||
* `--ssp` don't use proxy for stream downloading
|
||||
|
|
@ -63,19 +68,17 @@ After installing NodeJS with NPM go to directory with `package.json` file and ty
|
|||
|
||||
### Filenaming (optional)
|
||||
|
||||
* `-a <s>` release group ("Funimation" by default)
|
||||
* `-t <s>` show title override
|
||||
* `--ep <s>` episode number override (ignored in batch mode)
|
||||
* `--suffix <s>` filename suffix override (first "SIZEp" will be replaced with actual video size, "SIZEp" by default)
|
||||
* `--fileName` Set the filename template. Use ${variable_name} to insert variables.
|
||||
You may use 'title', 'episode', 'showTitle', 'season', 'width', 'height' as variables.
|
||||
|
||||
### Utility
|
||||
|
||||
* `--nocleanup` move unnecessary files to trash folder after completion instead of deleting
|
||||
* `--nocleanup` don't delete the input files after the muxing
|
||||
* `-h`, `--help` show all options
|
||||
|
||||
## Filename Template
|
||||
|
||||
[`release group`] `title` - `episode` [`suffix`].`extension`
|
||||
[Funimation] ${showTitle} - ${episode} [${height}p]"]
|
||||
|
||||
## CLI Examples
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ const nodeVer = 'node14-';
|
|||
fs.mkdirSync(`${buildDir}/bin`);
|
||||
fs.mkdirSync(`${buildDir}/config`);
|
||||
fs.mkdirSync(`${buildDir}/videos`);
|
||||
fs.mkdirSync(`${buildDir}/videos/_trash`);
|
||||
fs.copySync('./bin/', `${buildDir}/bin/`);
|
||||
fs.copySync('./config/bin-path.yml', `${buildDir}/config/bin-path.yml`);
|
||||
fs.copySync('./config/cli-defaults.yml', `${buildDir}/config/cli-defaults.yml`);
|
||||
|
|
|
|||
155
modules/merger.js
Normal file
155
modules/merger.js
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
const iso639 = require('iso-639');
|
||||
const argv = require('../funi').argv;
|
||||
|
||||
/**
|
||||
* @param {Array<object>} videoAndAudio
|
||||
* @param {Array<object>} onlyVid
|
||||
* @param {Array<object>} onlyAudio
|
||||
* @param {Array<object>} subtitles
|
||||
* @param {string} output
|
||||
* @returns {string}
|
||||
*/
|
||||
const buildCommandFFmpeg = (videoAndAudio, onlyVid, onlyAudio, subtitles, output) => {
|
||||
let args = [];
|
||||
let metaData = [];
|
||||
|
||||
let index = 0;
|
||||
let hasVideo = false;
|
||||
for (let vid of videoAndAudio) {
|
||||
args.push(`-i "${vid.path}"`);
|
||||
if (!hasVideo) {
|
||||
metaData.push(`-map ${index}`);
|
||||
metaData.push(`-metadata:s:a:${index} language=${getLanguageCode(vid.lang, vid.lang)}`);
|
||||
metaData.push(`-metadata:s:v:${index} title="[Funimation]"`);
|
||||
hasVideo = true;
|
||||
} else {
|
||||
metaData.push(`-map ${index}:a`);
|
||||
metaData.push(`-metadata:s:a:${index} language=${getLanguageCode(vid.lang, vid.lang)}`);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
for (let vid of onlyVid) {
|
||||
if (!hasVideo) {
|
||||
args.push(`-i "${vid.path}"`);
|
||||
metaData.push(`-map ${index}`);
|
||||
metaData.push(`-metadata:s:a:${index} language=${getLanguageCode(vid.lang, vid.lang)}`);
|
||||
metaData.push(`-metadata:s:v:${index} title="[Funimation]"`);
|
||||
hasVideo = true;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
for (let aud of onlyAudio) {
|
||||
args.push(`-i "${aud.path}"`);
|
||||
metaData.push(`-map ${index}`);
|
||||
metaData.push(`-metadata:s:a:${index} language=${getLanguageCode(aud.lang, aud.lang)}`);
|
||||
index++;
|
||||
}
|
||||
|
||||
for (let index in subtitles) {
|
||||
let sub = subtitles[index];
|
||||
args.push(`-i "${sub.file}"`);
|
||||
}
|
||||
|
||||
args.push(...metaData);
|
||||
args.push(...subtitles.map((_, subIndex) => `-map ${subIndex + index}`));
|
||||
args.push(
|
||||
'-c:v copy',
|
||||
'-c:a copy'
|
||||
);
|
||||
args.push(output.split('.').pop().toLowerCase() === 'mp4' ? '-c:s mov_text' : '-c:s ass');
|
||||
args.push(...subtitles.map((sub, index) => `-metadata:s:${index + 2} language=${getLanguageCode(sub.language)}`));
|
||||
args.push(`"${output}"`);
|
||||
return args.join(' ');
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} videoFile
|
||||
* @param {object} audioFile
|
||||
* @param {Array<object>} subtitles
|
||||
* @returns {string}
|
||||
*/
|
||||
const buildCommandMkvMerge = (videoAndAudio, onlyVid, onlyAudio, subtitles, output) => {
|
||||
let args = [];
|
||||
|
||||
let hasVideo = false;
|
||||
|
||||
args.push(`-o "${output}"`);
|
||||
args.push(
|
||||
'--no-date',
|
||||
'--disable-track-statistics-tags',
|
||||
'--engage no_variable_data',
|
||||
);
|
||||
|
||||
for (let vid of onlyVid) {
|
||||
if (!hasVideo) {
|
||||
args.push(
|
||||
'--video-tracks 0',
|
||||
'--no-audio'
|
||||
);
|
||||
args.push('--track-name 0:[Funimation]');
|
||||
hasVideo = true;
|
||||
args.push(`"${vid.path}"`);
|
||||
}
|
||||
}
|
||||
|
||||
for (let vid of videoAndAudio) {
|
||||
console.log(vid, vid.lang);
|
||||
if (!hasVideo) {
|
||||
args.push(
|
||||
'--video-tracks 0',
|
||||
'--audio-tracks 1'
|
||||
);
|
||||
args.push('--track-name 0:[Funimation]');
|
||||
args.push(`--language 1:${getLanguageCode(vid.lang, vid.lang)}`);
|
||||
hasVideo = true;
|
||||
} else {
|
||||
args.push(
|
||||
'--no-video',
|
||||
'--audio-tracks 1'
|
||||
);
|
||||
args.push(`--language 1:${getLanguageCode(vid.lang, vid.lang)}`);
|
||||
}
|
||||
args.push(`"${vid.path}"`);
|
||||
}
|
||||
|
||||
for (let aud of onlyAudio) {
|
||||
args.push(`--language 0:${getLanguageCode(aud.lang, aud.lang)}`);
|
||||
args.push(
|
||||
'--no-video',
|
||||
'--audio-tracks 0'
|
||||
);
|
||||
args.push(`"${aud.path}"`);
|
||||
}
|
||||
|
||||
if(subtitles.length > 0){
|
||||
for (let subObj of subtitles) {
|
||||
args.push('--language',`0:${getLanguageCode(subObj.language)}`);
|
||||
args.push(`"${subObj.file}"`);
|
||||
}
|
||||
} else {
|
||||
args.push(
|
||||
'--no-subtitles',
|
||||
'--no-attachments'
|
||||
);
|
||||
}
|
||||
|
||||
return args.join(' ');
|
||||
};
|
||||
|
||||
const getLanguageCode = (from, _default = 'eng') => {
|
||||
for (let lang in iso639.iso_639_2) {
|
||||
let langObj = iso639.iso_639_2[lang];
|
||||
if (Object.prototype.hasOwnProperty.call(langObj, '639-1') && langObj['639-1'] === from) {
|
||||
return langObj['639-2'];
|
||||
}
|
||||
}
|
||||
return _default;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
buildCommandFFmpeg,
|
||||
getLanguageCode,
|
||||
buildCommandMkvMerge
|
||||
};
|
||||
|
|
@ -1,193 +1,214 @@
|
|||
const yargs = require('yargs');
|
||||
|
||||
const appArgv = (cfg, langsData) => {
|
||||
const availableFilenameVars = [
|
||||
'title',
|
||||
'episode',
|
||||
'showTitle',
|
||||
'season',
|
||||
'width',
|
||||
'height'
|
||||
];
|
||||
|
||||
const appArgv = (cfg) => {
|
||||
// init
|
||||
return yargs.parserConfiguration({
|
||||
"duplicate-arguments-array": false,
|
||||
const argv = yargs.parserConfiguration({
|
||||
'duplicate-arguments-array': true,
|
||||
'camel-case-expansion': false
|
||||
})
|
||||
// main
|
||||
.wrap(Math.min(120)) // yargs.terminalWidth()
|
||||
.help(false).version(false)
|
||||
.usage('Usage: $0 [options]')
|
||||
.wrap(Math.min(120)) // yargs.terminalWidth()
|
||||
.help(false).version(false)
|
||||
.usage('Usage: $0 [options]')
|
||||
// auth
|
||||
.option('auth', {
|
||||
group: 'Authentication:',
|
||||
describe: 'Enter authentication mode',
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('auth', {
|
||||
group: 'Authentication:',
|
||||
describe: 'Enter authentication mode',
|
||||
type: 'boolean',
|
||||
})
|
||||
// search
|
||||
.option('search', {
|
||||
alias: 'f',
|
||||
group: 'Search:',
|
||||
describe: 'Search show ids',
|
||||
type: 'string',
|
||||
})
|
||||
.option('search', {
|
||||
alias: 'f',
|
||||
group: 'Search:',
|
||||
describe: 'Search show ids',
|
||||
type: 'string',
|
||||
})
|
||||
// select show and eps
|
||||
.option('s', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Sets the show id',
|
||||
type: 'number',
|
||||
})
|
||||
.option('e', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Select episode ids (comma-separated, hyphen-sequence)',
|
||||
type: 'string',
|
||||
})
|
||||
.option('s', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Sets the show id',
|
||||
type: 'number',
|
||||
})
|
||||
.option('e', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Select episode ids (comma-separated, hyphen-sequence)',
|
||||
type: 'string',
|
||||
})
|
||||
.option('all', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Used to download all episodes from the show',
|
||||
type: 'boolean',
|
||||
default: cfg.all || false
|
||||
})
|
||||
.option('partsize', {
|
||||
group: 'Downloading:',
|
||||
describe: 'The amount of parts that should be downloaded in paralell',
|
||||
type: 'number',
|
||||
default: cfg.partsize || 10
|
||||
})
|
||||
// quality
|
||||
.option('q', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Select video layer (0 is max)',
|
||||
choices: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
||||
default: cfg.videoLayer || 7,
|
||||
type: 'number',
|
||||
})
|
||||
.option('q', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Select video layer (0 is max)',
|
||||
choices: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
||||
default: cfg.videoLayer || 7,
|
||||
type: 'number',
|
||||
})
|
||||
// alt listing
|
||||
.option('alt', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Alternative episode listing (if available)',
|
||||
default: cfg.altList || false,
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('alt', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Alternative episode listing (if available)',
|
||||
default: cfg.altList || false,
|
||||
type: 'boolean',
|
||||
})
|
||||
// switch to subs
|
||||
.option('dub', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Download non-Japanese Dub (English Dub mode by default)',
|
||||
choices: [ 'enUS', 'esLA', 'ptBR' ],
|
||||
default: cfg.dub || 'enUS',
|
||||
type: 'string',
|
||||
})
|
||||
.option('sub', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Japanese Dub with subtitles mode (English Dub mode by default)',
|
||||
default: cfg.subsMode || false,
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('dub', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Download non-Japanese Dub (English Dub mode by default)',
|
||||
choices: [ 'enUS', 'esLA', 'ptBR', 'zhMN', 'jaJP' ],
|
||||
default: cfg.dub || 'enUS',
|
||||
type: 'array',
|
||||
})
|
||||
.option('subLang', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Set the subtitle language (English is default and fallback)',
|
||||
default: cfg.subLang || 'enUS',
|
||||
choices: [ 'enUS', 'esLA', 'ptBR' ],
|
||||
type: 'array'
|
||||
})
|
||||
.option('fontSize', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Used to set the fontsize of the subtitles',
|
||||
default: cfg.fontSize || 55,
|
||||
type: 'number'
|
||||
})
|
||||
// simulcast
|
||||
.option('simul', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Force downloading simulcast ver. instead of uncut ver. (if uncut ver. available)',
|
||||
default: cfg.forceSimul || false,
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('simul', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Force downloading simulcast ver. instead of uncut ver. (if uncut ver. available)',
|
||||
default: cfg.forceSimul || false,
|
||||
type: 'boolean',
|
||||
})
|
||||
// server number
|
||||
.option('x', {
|
||||
alias: 'server',
|
||||
group: 'Downloading:',
|
||||
describe: 'Select server',
|
||||
choices: [1, 2, 3, 4],
|
||||
default: cfg.nServer || 1,
|
||||
type: 'number',
|
||||
})
|
||||
.option('x', {
|
||||
alias: 'server',
|
||||
group: 'Downloading:',
|
||||
describe: 'Select server',
|
||||
choices: [1, 2, 3, 4],
|
||||
default: cfg.nServer || 1,
|
||||
type: 'number',
|
||||
})
|
||||
// skip
|
||||
.option('novids', {
|
||||
group: 'Downloading:',
|
||||
alias: 'skipdl',
|
||||
describe: 'Skip downloading video (for downloading subtitles only)',
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('nosubs', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Skip downloading subtitles for English Dub (if available)',
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('noaudio', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Skip downloading audio',
|
||||
type: 'boolean'
|
||||
})
|
||||
.option('novids', {
|
||||
group: 'Downloading:',
|
||||
alias: 'skipdl',
|
||||
describe: 'Skip downloading video',
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('nosubs', {
|
||||
group: 'Downloading:',
|
||||
describe: 'Skip downloading subtitles for English Dub (if available)',
|
||||
type: 'boolean',
|
||||
default: false
|
||||
})
|
||||
// proxy
|
||||
.option('proxy', {
|
||||
group: 'Proxy:',
|
||||
describe: 'Set http(s)/socks proxy WHATWG url',
|
||||
default: cfg.proxy || false,
|
||||
hidden: true,
|
||||
})
|
||||
.option('proxy-auth', {
|
||||
group: 'Proxy:',
|
||||
describe: 'Colon-separated username and password for proxy',
|
||||
default: cfg.proxy_auth || false,
|
||||
hidden: true,
|
||||
})
|
||||
.option('ssp', {
|
||||
group: 'Proxy:',
|
||||
describe: 'Don\'t use proxy for stream and subtitles downloading',
|
||||
default: cfg.proxy_ssp || false,
|
||||
hidden: true,
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('proxy', {
|
||||
group: 'Proxy:',
|
||||
describe: 'Set http(s)/socks proxy WHATWG url',
|
||||
default: cfg.proxy || false,
|
||||
hidden: true,
|
||||
})
|
||||
.option('proxy-auth', {
|
||||
group: 'Proxy:',
|
||||
describe: 'Colon-separated username and password for proxy',
|
||||
default: cfg.proxy_auth || false,
|
||||
hidden: true,
|
||||
})
|
||||
.option('ssp', {
|
||||
group: 'Proxy:',
|
||||
describe: 'Don\'t use proxy for stream and subtitles downloading',
|
||||
default: cfg.proxy_ssp || false,
|
||||
hidden: true,
|
||||
type: 'boolean',
|
||||
})
|
||||
// muxing
|
||||
.option('skipmux', {
|
||||
group: 'Muxing:',
|
||||
describe: 'Skip muxing video and subtitles',
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('mp4', {
|
||||
group: 'Muxing:',
|
||||
describe: 'Mux into mp4',
|
||||
default: cfg.mp4mux || false,
|
||||
type: 'boolean'
|
||||
})
|
||||
.option('mks', {
|
||||
group: 'Muxing:',
|
||||
describe: 'Add subtitles to mkv/mp4 (if available)',
|
||||
default: cfg.muxSubs || false,
|
||||
type: 'boolean'
|
||||
})
|
||||
.option('skipmux', {
|
||||
group: 'Muxing:',
|
||||
describe: 'Skip muxing video and subtitles',
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('mp4', {
|
||||
group: 'Muxing:',
|
||||
describe: 'Mux into mp4',
|
||||
default: cfg.mp4mux || false,
|
||||
type: 'boolean'
|
||||
})
|
||||
// filenaming
|
||||
.option('a', {
|
||||
alias: 'grouptag',
|
||||
group: 'Filename Template:',
|
||||
describe: 'Release group',
|
||||
default: cfg.releaseGroup || 'Funimation',
|
||||
type: 'string'
|
||||
})
|
||||
.option('t', {
|
||||
alias: 'title',
|
||||
group: 'Filename Template:',
|
||||
describe: 'Series title override',
|
||||
type: 'string'
|
||||
})
|
||||
.option('ep', {
|
||||
group: 'Filename Template:',
|
||||
describe: 'Episode number override (ignored in batch mode)',
|
||||
type: 'string'
|
||||
})
|
||||
.option('suffix', {
|
||||
group: 'Filename Template:',
|
||||
describe: 'Filename suffix override (first "SIZEp" will be replaced with actual video size)',
|
||||
default: cfg.fileSuffix || 'SIZEp',
|
||||
type: 'string'
|
||||
})
|
||||
.option('fileName', {
|
||||
group: 'Filename Template:',
|
||||
describe: `Set the filename template. Use \${variable_name} to insert variables.\nYou may use ${availableFilenameVars
|
||||
.map(a => `'${a}'`).join(', ')} as variables.`,
|
||||
type: 'string',
|
||||
default: cfg.fileName || '[Funimation] ${showTitle} - ${episode} [${height}p]'
|
||||
})
|
||||
.option('numbers', {
|
||||
group: 'Filename Template:',
|
||||
describe: `Set how long a number in the title should be at least.\n${[[3, 5, '005'], [2, 1, '01'], [1, 20, '20']]
|
||||
.map(val => `Set in config: ${val[0]}; Episode number: ${val[1]}; Output: ${val[2]}`).join('\n')}`,
|
||||
type: 'number',
|
||||
default: cfg.numbers || 2
|
||||
})
|
||||
// util
|
||||
.option('nocleanup', {
|
||||
group: 'Utilities:',
|
||||
describe: 'Move temporary files to trash folder instead of deleting',
|
||||
default: cfg.noCleanUp || false,
|
||||
type: 'boolean'
|
||||
})
|
||||
.option('notrashfolder', {
|
||||
implies: ['nocleanup'],
|
||||
group: 'Utilities:',
|
||||
describe: 'Don\'t move temporary files to trash folder (Used with --nocleanup)',
|
||||
default: cfg.noTrashFolder || false,
|
||||
type: 'boolean'
|
||||
})
|
||||
.option('nocleanup', {
|
||||
group: 'Utilities:',
|
||||
describe: 'Dont\'t delete the input files after muxing',
|
||||
default: cfg.noCleanUp || false,
|
||||
type: 'boolean'
|
||||
})
|
||||
// help
|
||||
.option('help', {
|
||||
alias: 'h',
|
||||
group: 'Help:',
|
||||
describe: 'Show this help',
|
||||
type: 'boolean'
|
||||
})
|
||||
.option('help', {
|
||||
alias: 'h',
|
||||
group: 'Help:',
|
||||
describe: 'Show this help',
|
||||
type: 'boolean'
|
||||
})
|
||||
// usage
|
||||
.example([
|
||||
['$0 --search "My Hero"', 'search "My Hero" in title'],
|
||||
['$0 -s 124389 -e 1,2,3', 'download episodes 1-3 from show with id 124389'],
|
||||
['$0 -s 124389 -e 1-3,2-7,s1-2', 'download episodes 1-7 and "S"-episodes 1-2 from show with id 124389'],
|
||||
])
|
||||
.example([
|
||||
['$0 --search "My Hero"', 'search "My Hero" in title'],
|
||||
['$0 -s 124389 -e 1,2,3', 'download episodes 1-3 from show with id 124389'],
|
||||
['$0 -s 124389 -e 1-3,2-7,s1-2', 'download episodes 1-7 and "S"-episodes 1-2 from show with id 124389'],
|
||||
])
|
||||
|
||||
// --
|
||||
.argv;
|
||||
}
|
||||
.argv;
|
||||
|
||||
// Resolve unwanted arrays
|
||||
for (let key in argv) {
|
||||
if (argv[key] instanceof Array && !(key === 'subLang' || key === 'dub')) {
|
||||
argv[key] = argv[key].pop();
|
||||
}
|
||||
}
|
||||
return argv;
|
||||
};
|
||||
|
||||
const showHelp = yargs.showHelp;
|
||||
|
||||
module.exports = {
|
||||
appArgv,
|
||||
showHelp
|
||||
showHelp,
|
||||
availableFilenameVars
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ const existsFile = fs.existsSync;
|
|||
|
||||
const loadYamlFile = (file) => {
|
||||
return yaml.parse(fs.readFileSync(file, 'utf8'));
|
||||
}
|
||||
};
|
||||
|
||||
const loadYamlCfg = (file) => {
|
||||
if(existsFile(`${file}.user.yml`)){
|
||||
|
|
@ -21,6 +21,6 @@ const loadYamlCfg = (file) => {
|
|||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = loadYamlCfg;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const getData = async (options) => {
|
|||
}
|
||||
};
|
||||
if(options.responseType) {
|
||||
gOptions.responseType = options.responseType
|
||||
gOptions.responseType = options.responseType;
|
||||
}
|
||||
if(options.baseUrl){
|
||||
gOptions.prefixUrl = options.baseUrl;
|
||||
|
|
@ -71,6 +71,6 @@ const getData = async (options) => {
|
|||
error,
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = getData;
|
||||
|
|
|
|||
|
|
@ -35,10 +35,10 @@ function loadVtt(vttStr) {
|
|||
}
|
||||
|
||||
// ass specific
|
||||
function convertToAss(vttStr){
|
||||
function convertToAss(vttStr, lang, fontSize){
|
||||
let ass = [
|
||||
'\ufeff[Script Info]',
|
||||
'Title: English',
|
||||
`Title: ${lang}`,
|
||||
'ScriptType: v4.00+',
|
||||
'PlayResX: 1280',
|
||||
'PlayResY: 720',
|
||||
|
|
@ -49,8 +49,8 @@ function convertToAss(vttStr){
|
|||
'Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, '
|
||||
+ 'Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, '
|
||||
+ 'BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding',
|
||||
'Style: Main,Noto Sans,55,&H00FFFFFF,&H000000FF,&H00020713,&H00000000,0,0,0,0,100,100,0,0,1,3,0,2,10,10,10,1',
|
||||
'Style: MainTop,Noto Sans,55,&H00FFFFFF,&H000000FF,&H00020713,&H00000000,0,0,0,0,100,100,0,0,1,3,0,8,10,10,10,1',
|
||||
`Style: Main,Noto Sans,${fontSize},&H00FFFFFF,&H000000FF,&H00020713,&H00000000,0,0,0,0,100,100,0,0,1,3,0,2,10,10,10,1`,
|
||||
`Style: MainTop,Noto Sans,${fontSize},&H00FFFFFF,&H000000FF,&H00020713,&H00000000,0,0,0,0,100,100,0,0,1,3,0,8,10,10,10`,
|
||||
'',
|
||||
'[Events]',
|
||||
'Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text',
|
||||
|
|
@ -141,7 +141,7 @@ function toSubsTime(str, srtFormat) {
|
|||
let hLen = srtFormat ? 2 : 1;
|
||||
|
||||
x[3] = '0.' + ('' + x[3]).padStart(3, '0');
|
||||
sx = x[0]*60*60 + x[1]*60 + x[2] + Number(x[3])
|
||||
sx = x[0]*60*60 + x[1]*60 + x[2] + Number(x[3]);
|
||||
sx = sx.toFixed(msLen).split('.');
|
||||
|
||||
|
||||
|
|
@ -160,7 +160,7 @@ function padTimeNum(sep, input, pad){
|
|||
}
|
||||
|
||||
// export module
|
||||
module.exports = (vttStr, toSrt) => {
|
||||
module.exports = (vttStr, toSrt, lang = 'English', fontSize) => {
|
||||
const convert = toSrt ? convertToSrt : convertToAss;
|
||||
return convert(vttStr);
|
||||
return convert(vttStr, lang, fontSize);
|
||||
};
|
||||
|
|
|
|||
12
package.json
12
package.json
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "funimation-downloader-nx",
|
||||
"short_name": "funi",
|
||||
"version": "4.8.0-beta.1",
|
||||
"version": "4.9.1",
|
||||
"description": "Download videos from Funimation via cli.",
|
||||
"keywords": [
|
||||
"download",
|
||||
|
|
@ -12,21 +12,21 @@
|
|||
"utility",
|
||||
"cli"
|
||||
],
|
||||
"author": "AniDL",
|
||||
"homepage": "https://github.com/anidl/funimation-downloader-nx",
|
||||
"author": "AniDL/Izu-co",
|
||||
"homepage": "https://github.com/izu-co/funimation-downloader-nx",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/anidl/funimation-downloader-nx.git"
|
||||
"url": "https://github.com/izu-co/funimation-downloader-nx.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/anidl/funimation-downloader-nx/issues"
|
||||
"url": "https://github.com/izu-co/funimation-downloader-nx/issues"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "funi.js",
|
||||
"dependencies": {
|
||||
"form-data": "^3.0.0",
|
||||
"got": "^11.7.0",
|
||||
"hls-download": "^2.5.3",
|
||||
"iso-639": "^0.2.2",
|
||||
"lookpath": "^1.1.0",
|
||||
"m3u8-parsed": "^1.3.0",
|
||||
"sei-helper": "^3.3.0",
|
||||
|
|
|
|||
Loading…
Reference in a new issue