Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const crypto = require('crypto');
- const fs = require('fs');
- const path = require('path');
- const {execSync} = require('child_process');
- const shortHash = (str) => crypto.createHash('sha256').update(str).digest('hex').substr(0, 16);
- const run = (cmd, output) => {
- if (fs.existsSync(output)) {
- return;
- }
- cmd = `ffmpeg ${cmd.trim().replace(/\s*\n\s*/g, ' ')} ${output}`;
- console.log(cmd);
- execSync(cmd, {'stdio': 'pipe'});
- };
- const configPathname = path.join(__dirname, 'config.json');
- const defaultConfig = {
- source: '',
- destination: '',
- format: '',
- ranges: [
- '00:01:00.000 --> 00:02:00.000'
- ],
- };
- const cacheSrc = path.join(__dirname, 'cache');
- if (!fs.existsSync(cacheSrc)) {
- fs.mkdirSync(cacheSrc);
- }
- const loadConfig = () => {
- if (!fs.existsSync(configPathname)) {
- const json = JSON.stringify(defaultConfig, 'null', '\t');
- fs.writeFileSync(configPathname, json);
- process.exit(0);
- }
- const json = fs.readFileSync(configPathname)
- .toString()
- .replace(/("([^\\"]|\\.)*")|(\/\/[^\n]*)|\/\*.*?\*\//g, '$1');
- return JSON.parse(json);
- };
- const {
- source,
- destination,
- format,
- ranges
- } = loadConfig();
- const parseTime = (time) => {
- let scales = [1, 60, 60*60];
- return time
- .replace(/,/g, '.')
- .split(':')
- .map(Number)
- .reverse()
- .map((x,i) => x*scales[i])
- .reduce((a,b) => a+b)*1000;
- };
- const stringifyTime = (time) => {
- let scales = [60000, 60, 100];
- let pads = [5, 2, 2];
- return scales
- .map(s => {
- let res = time%s;
- time = Math.round((time - res)/s);
- return res;
- })
- .map((x,i) => (x+'').padStart(pads[i], '0'))
- .reverse()
- .join(':')
- .replace(/(\d{3})$/, '.$1');
- };
- const parseRange = (range) => range
- .replace(/\s/g, '')
- .split('-->')
- .map(parseTime);
- const hashRange = (range) => range
- .map(x => x.toString().padStart(8, '0'))
- .join('');
- const targets = ranges
- .map((item) => hashRange(parseRange(item)));
- const checksum = shortHash(targets.join('-'));
- const mergedPathname = path.join(cacheSrc, `merged-${checksum}.${format}`);
- const fastPathname = path.join(cacheSrc, `fast-${checksum}.${format}`);
- const parseHash = (hash) => hash
- .match(/(\d{8})(\d{8})/)
- .slice(1)
- .map((x) => parseInt(x));
- const hashToCutName = (hash) => `${hash}.${format}`;
- const isCutName = (name) => /^\d{16}\.\w+$/.test(name);
- const cutNameToHash = (name) => name.replace(/^(\d+).*$/, '$1');
- const exist = fs
- .readdirSync(destination)
- .filter(isCutName)
- .map(cutNameToHash);
- const hashToPathname = (hash) => path.join(cacheSrc, hashToCutName(hash));
- // exist.forEach((hash) => {
- // if (targets.includes(hash)) {
- // return
- // }
- // console.log(`deleting ${hash}`);
- // fs.unlinkSync(hashToPathname(hash));
- // });
- targets.forEach((hash) => {
- let range = parseHash(hash);
- let [a, b] = range;
- let start = stringifyTime(a);
- let duration = stringifyTime(b - a);
- let output = hashToPathname(hash);
- run(`
- -ss ${start}
- -t ${duration}
- -i ${source}
- -vf scale=640:272
- `, output);
- });
- const remove = (pathname) => {
- if (fs.existsSync(pathname)) {
- fs.unlinkSync(pathname);
- }
- };
- fs.writeFileSync('./merged.txt', targets.map((hash) => 'file ' + hashToPathname(hash)).join('\n') + '\n');
- run(`
- -f concat
- -safe 0
- -i ./merged.txt
- -c copy
- -an
- `, mergedPathname);
- run(`
- -itsscale 0.5
- -i ${mergedPathname}
- -c copy
- `, fastPathname);
Add Comment
Please, Sign In to add comment