diff --git a/README.md b/README.md index a10bb23..73446c5 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,5 @@ Options: ## TODO -* Fix alternate sort pattern features -* Check for ffmpeg or avconv before executing * Generate example videos automatically * Publish example videos \ No newline at end of file diff --git a/frameloom b/frameloom index 6e68bee..ad90cf6 100644 --- a/frameloom +++ b/frameloom @@ -219,6 +219,7 @@ async function weave(pattern, realtime, random) { alt = true; } if (random) { + log('Sorting frames randomly...'); try { seq = await randomSort(frames, pattern, realtime); } @@ -227,6 +228,7 @@ async function weave(pattern, realtime, random) { } } else if (!alt) { + log('Sorting frames normally...'); try { seq = await standardSort(frames, pattern, realtime); } @@ -235,8 +237,9 @@ async function weave(pattern, realtime, random) { } } else if (alt) { - log('This feature is not ready, please check https://github.com/sixteenmillimeter/frameloom.git', {}); - process.exit(10); + //log('This feature is not ready, please check https://github.com/sixteenmillimeter/frameloom.git', {}) + //process.exit(10) + log('Sorting frames with alternate pattern...'); try { seq = await altSort(frames, pattern, realtime); } @@ -256,34 +259,69 @@ async function weave(pattern, realtime, random) { async function altSort(list, pattern, realtime) { let groups = []; let newList = []; + let loops = 0; + let patternIndexes = []; let frameCount = 0; + let skipCount; + let skip; + let oldName; let oldPath; let newName; let newPath; let ext = path.extname(list[0]); - for (let g of pattern) { + let x; + let i; + for (x = 0; x < pattern.length; x++) { groups.push([]); + for (let i = 0; i < pattern[x]; i++) { + patternIndexes.push(x); + } } - for (let i = 0; i < list.length; i++) { + for (i = 0; i < list.length; i++) { groups[i % pattern.length].push(list[i]); } - for (let x = 0; x < list.length; x++) { - for (let g of pattern) { - for (let i = 0; i < g; i++) { - /*oldPath = path.join(TMPPATH, list[i]); - newName = `./render_${zeroPad(frameCount)}${ext}`; - newPath = path.join(TMPPATH, newName); - - log(`Renaming ${list[i]} -> ${newName}`); - + loops = Math.ceil(list.length / patternIndexes.length); + if (realtime) { + skip = false; + skipCount = patternIndexes.length + 1; + } + for (x = 0; x < loops; x++) { + for (i = 0; i < patternIndexes.length; i++) { + if (realtime) { + skipCount--; + if (skipCount === 0) { + skip = !skip; + skipCount = pattern.length; + } + } + if (typeof groups[patternIndexes[i]][0] === 'undefined') { + continue; + } + oldName = String(groups[patternIndexes[i]][0]); + oldPath = path.join(TMPPATH, oldName); + groups[patternIndexes[i]].shift(); + if (skip) { + log(`Skipping ${oldName}`); try { - //await fs.move(oldPath, newPath, { overwrite: true }) - newList.push(newName); - } catch (err) { - log(err); - }*/ + await fs.unlink(oldPath); + } + catch (err) { + log('Error deleting frame', err); + } + continue; + } + newName = `./render_${zeroPad(frameCount)}${ext}`; + newPath = path.join(TMPPATH, newName); + log(`Renaming ${oldName} -> ${newName}`); + try { + await fs.move(oldPath, newPath); + newList.push(newName); frameCount++; } + catch (err) { + log('Error renaming frame', err); + return process.exit(10); + } } } return newList; @@ -483,6 +521,8 @@ async function main(arg) { let avconv = false; let random = false; let e = false; + let exe = arg.avconv ? 'avconv' : 'ffmpeg'; + let exists; console.time('frameloom'); if (input.length < 2) { log('Must provide more than 1 input', {}); @@ -518,6 +558,21 @@ async function main(arg) { pattern.push(1); } } + try { + exists = await exec(`which ${exe}`); + } + catch (err) { + log(`Error checking for ${exe}`); + process.exit(11); + } + if (!exists || exists === '' || exists.indexOf(exe) === -1) { + log(`${exe} is required and is not installed. Please install ${exe} to use frameloom.`); + process.exit(12); + } + if (pattern.length !== input.length) { + log(`Number of inputs (${input.length}) doesn't match the pattern length (${pattern.length})`); + process.exit(10); + } if (arg.realtime) realtime = true; TMPPATH = path.join(TMPDIR, 'frameloom'); @@ -538,7 +593,6 @@ async function main(arg) { return process.exit(4); } } - log('Weaving frames'); try { await weave(pattern, realtime, random); } diff --git a/package-lock.json b/package-lock.json index 6352adb..4398406 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "frameloom", - "version": "1.0.2", + "version": "1.0.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index cf34dec..80dc685 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "frameloom", - "version": "1.0.2", + "version": "1.0.3", "description": "Node script to generate flicker videos by interweaving frames from multiple videos", "main": "frameloom", "scripts": { diff --git a/src/frameloom.ts b/src/frameloom.ts index db51713..25a0361 100755 --- a/src/frameloom.ts +++ b/src/frameloom.ts @@ -231,20 +231,23 @@ async function weave (pattern : number[], realtime : boolean, random : boolean) } if (random){ + log('Sorting frames randomly...') try { seq = await randomSort(frames, pattern, realtime) } catch (err) { log('Error sorting frames', err) } } else if (!alt) { + log('Sorting frames normally...') try { seq = await standardSort(frames, pattern, realtime) } catch (err) { log('Error sorting frames', err) } } else if (alt) { - log('This feature is not ready, please check https://github.com/sixteenmillimeter/frameloom.git', {}) - process.exit(10) + //log('This feature is not ready, please check https://github.com/sixteenmillimeter/frameloom.git', {}) + //process.exit(10) + log('Sorting frames with alternate pattern...') try { seq = await altSort(frames, pattern, realtime) } catch (err) { @@ -263,39 +266,82 @@ async function weave (pattern : number[], realtime : boolean, random : boolean) async function altSort (list : string[], pattern : number[], realtime : boolean) { let groups : any[] = [] let newList : string[] = [] + let loops : number = 0 + let patternIndexes : number[] = [] let frameCount : number = 0 + let skipCount : number + let skip : boolean + let oldName : string let oldPath : string let newName : string let newPath : string let ext : string = path.extname(list[0]) + let x : number + let i : number - for (let g of pattern) { + for (x = 0; x < pattern.length; x++) { groups.push([]) + for (let i : number = 0; i < pattern[x]; i++) { + patternIndexes.push(x) + } } - for (let i : number = 0; i < list.length; i++) { + + for (i = 0; i < list.length; i++) { groups[i % pattern.length].push(list[i]) } - for (let x : number = 0; x < list.length; x++) { - for (let g of pattern) { - for (let i : number = 0; i < g; i++) { - /*oldPath = path.join(TMPPATH, list[i]); - newName = `./render_${zeroPad(frameCount)}${ext}`; - newPath = path.join(TMPPATH, newName); + loops = Math.ceil(list.length / patternIndexes.length) - log(`Renaming ${list[i]} -> ${newName}`); + if (realtime) { + skip = false + skipCount = patternIndexes.length + 1 + } + for (x = 0; x < loops; x++) { + for (i = 0; i < patternIndexes.length; i++) { + + if (realtime) { + skipCount--; + if (skipCount === 0) { + skip = !skip; + skipCount = pattern.length + } + } + + if (typeof groups[patternIndexes[i]][0] === 'undefined') { + continue + } + + oldName = String(groups[patternIndexes[i]][0]) + oldPath = path.join(TMPPATH, oldName) + + groups[patternIndexes[i]].shift() + + if (skip) { + log(`Skipping ${oldName}`) try { - //await fs.move(oldPath, newPath, { overwrite: true }) - newList.push(newName); + await fs.unlink(oldPath) } catch (err) { - log(err); - }*/ + log('Error deleting frame', err) + } + continue + } + newName = `./render_${zeroPad(frameCount)}${ext}` + newPath = path.join(TMPPATH, newName) + log(`Renaming ${oldName} -> ${newName}`) + + try { + await fs.move(oldPath, newPath) + newList.push(newName) frameCount++ + } catch (err) { + log('Error renaming frame', err) + return process.exit(10) } } } + return newList } /** @@ -485,12 +531,6 @@ async function render (output : string, avconv : boolean) { log(`Exporting video ${output}`) log(cmd) - /*try { - await exec(`ls "${TMPPATH}"`) - } catch (err) { - log(err) - }*/ - try { await exec(cmd) } catch (err) { @@ -511,6 +551,8 @@ async function main (arg : any) { let avconv : boolean = false let random : boolean = false let e : any = false + let exe : string = arg.avconv ? 'avconv' : 'ffmpeg' + let exists : any console.time('frameloom') @@ -555,6 +597,23 @@ async function main (arg : any) { } } + try { + exists = await exec(`which ${exe}`) + } catch (err) { + log(`Error checking for ${exe}`) + process.exit(11) + } + + if (!exists || exists === '' || exists.indexOf(exe) === -1) { + log(`${exe} is required and is not installed. Please install ${exe} to use frameloom.`) + process.exit(12) + } + + if (pattern.length !== input.length) { + log(`Number of inputs (${input.length}) doesn't match the pattern length (${pattern.length})`) + process.exit(10) + } + if (arg.realtime) realtime = true; TMPPATH = path.join(TMPDIR, 'frameloom'); @@ -577,7 +636,6 @@ async function main (arg : any) { } } - log('Weaving frames') try { await weave(pattern, realtime, random) } catch (err) {