Get version from package.json

This commit is contained in:
mmcwilliams 2019-02-23 22:38:20 -05:00
parent b1370447bf
commit cf39232d70
2 changed files with 114 additions and 38 deletions

150
frameloom
View File

@ -8,6 +8,12 @@ const path = require('path')
const program = require('commander') const program = require('commander')
const fs = require('fs-extra') const fs = require('fs-extra')
const pkg = require('./package.json')
const OUTPUT_RE = new RegExp('{{o}}', 'g')
const INPUT_RE = new RegExp('{{i}}', 'g')
let QUIET = false
let TMPDIR = os.tmpdir() || '/tmp' let TMPDIR = os.tmpdir() || '/tmp'
let TMPPATH let TMPPATH
@ -39,6 +45,19 @@ async function delay (ms) {
return setTimeout(resolve, ms) return setTimeout(resolve, ms)
}) })
} }
/**
* Log function wrapper that can silences logs when
* QUIET == true
*/
function log (msg, err) {
if (QUIET) return false
if (err) {
console.error(msg, err)
} else {
console.log(msg)
}
return true
}
/** /**
* Pads a numerical value with preceding zeros to make strings same length. * Pads a numerical value with preceding zeros to make strings same length.
* *
@ -77,11 +96,11 @@ async function clear () {
try { try {
exists = await fs.exists(TMPPATH) exists = await fs.exists(TMPPATH)
} catch (err) { } catch (err) {
console.error(err) log('Error checking if file exists', err)
} }
if (exists) { if (exists) {
console.log(`Clearing temp directory "${TMPPATH}"`) log(`Clearing temp directory "${TMPPATH}"`)
try { try {
await exec(cmd) await exec(cmd)
} catch (err) { } catch (err) {
@ -94,7 +113,7 @@ async function clear () {
await fs.mkdir(TMPPATH) await fs.mkdir(TMPPATH)
} catch (err) { } catch (err) {
if (err.code !== 'EEXIST') { if (err.code !== 'EEXIST') {
console.error(err) log('Error making directory', err)
} }
} }
@ -110,7 +129,7 @@ async function clear () {
* *
* @returns {string} String with the export order, not sure why I did this * @returns {string} String with the export order, not sure why I did this
**/ **/
async function frames (video, order, avconv) { async function frames (video, order, avconv, e) {
let ext = 'tif' let ext = 'tif'
let exe = avconv ? 'avconv' : 'ffmpeg' let exe = avconv ? 'avconv' : 'ffmpeg'
let tmpoutput let tmpoutput
@ -120,17 +139,53 @@ async function frames (video, order, avconv) {
cmd = `${exe} -i "${video}" -compression_algo raw -pix_fmt rgb24 "${tmpoutput}"` cmd = `${exe} -i "${video}" -compression_algo raw -pix_fmt rgb24 "${tmpoutput}"`
console.log(`Exporting ${video} as single frames...`) log(`Exporting ${video} as single frames...`)
try { try {
await exec(cmd) await exec(cmd)
} catch (err) { } catch (err) {
console.error('Error exporting video', err) log('Error exporting video', err)
return process.exit(3) return process.exit(3)
} }
return path.join(TMPPATH, `export-%05d_${order}`) return path.join(TMPPATH, `export-%05d_${order}`)
} }
/**
* Shells out to run a sub command on every frame to perform effects
*
**/
async function subExec (cmd) {
let frames
let frameCmd
let framePath
try {
frames = await fs.readdir(TMPPATH)
} catch (err) {
log('Error reading tmp directory', err)
}
frames = frames.filter (file =>{
if (file.indexOf('.tif') !== -1) return true
})
for (let frame of frames) {
framePath = path.join(TMPPATH, frame)
if (cmd.indexOf('{{i}}') !== -1 || cmd.indexOf('{{o}}')) {
frameCmd = cmd.replace(INPUT_RE, framePath)
.replace(OUTPUT_RE, framePath)
} else {
frameCmd = `${cmd} ${framePath}`
}
try {
await exec(frameCmd)
} catch (err) {
log('Error executing sub command on frame', err)
return process.exit(10)
}
}
}
/** /**
* Re-arranges the frames into the order specified in the pattern. * Re-arranges the frames into the order specified in the pattern.
* Calls `patternSort()` to perform the rename and unlink actions * Calls `patternSort()` to perform the rename and unlink actions
@ -145,12 +200,12 @@ async function weave (pattern, realtime, random) {
let seq let seq
let alt = false let alt = false
console.log('Weaving frames...') log('Weaving frames...')
try { try {
frames = await fs.readdir(TMPPATH) frames = await fs.readdir(TMPPATH)
} catch (err) { } catch (err) {
console.error('Error reading tmp directory', err) log('Error reading tmp directory', err)
} }
//console.dir(frames) //console.dir(frames)
@ -166,21 +221,21 @@ async function weave (pattern, realtime, random) {
try { try {
seq = await randomSort(frames, realtime) seq = await randomSort(frames, realtime)
} catch (err) { } catch (err) {
console.error('Error sorting frames') log('Error sorting frames', err)
} }
} else if (!alt) { } else if (!alt) {
try { try {
seq = await standardSort(frames, pattern, realtime) seq = await standardSort(frames, pattern, realtime)
} catch (err) { } catch (err) {
console.error('Error sorting frames') log('Error sorting frames', err)
} }
} else if (alt) { } else if (alt) {
console.warn('This feature is not ready, please check https://github.com/sixteenmillimeter/frameloom.git') log('This feature is not ready, please check https://github.com/sixteenmillimeter/frameloom.git', {})
process.exit(10) process.exit(10)
try { try {
seq = await altSort(frames, pattern, realtime) seq = await altSort(frames, pattern, realtime)
} catch (err) { } catch (err) {
console.error('Error sorting frames') log('Error sorting frames', err)
} }
} }
//console.dir(seq) //console.dir(seq)
@ -215,13 +270,13 @@ async function altSort (list, pattern, realtime) {
newName = `./render_${zeroPad(frameCount)}${ext}`; newName = `./render_${zeroPad(frameCount)}${ext}`;
newPath = path.join(TMPPATH, newName); newPath = path.join(TMPPATH, newName);
console.log(`Renaming ${list[i]} -> ${newName}`); log(`Renaming ${list[i]} -> ${newName}`);
try { try {
//await fs.move(oldPath, newPath, { overwrite: true }) //await fs.move(oldPath, newPath, { overwrite: true })
newList.push(newName); newList.push(newName);
} catch (err) { } catch (err) {
console.error(err); log(err);
}*/ }*/
frameCount++ frameCount++
@ -266,25 +321,25 @@ async function standardSort (list, pattern, realtime) {
oldPath = path.join(TMPPATH, list[i]) oldPath = path.join(TMPPATH, list[i])
if (skip) { if (skip) {
console.log(`Skipping ${list[i]}`) log(`Skipping ${list[i]}`)
try { try {
await fs.unlink(oldPath) await fs.unlink(oldPath)
} catch (err) { } catch (err) {
console.error(err) log('Error deleting frame', err)
} }
continue continue
} }
newName = `./render_${zeroPad(frameCount)}${ext}` newName = `./render_${zeroPad(frameCount)}${ext}`
newPath = path.join(TMPPATH, newName) newPath = path.join(TMPPATH, newName)
console.log(`Renaming ${list[i]} -> ${newName}`) log(`Renaming ${list[i]} -> ${newName}`)
try { try {
await fs.move(oldPath, newPath) await fs.move(oldPath, newPath)
newList.push(newName) newList.push(newName)
frameCount++ frameCount++
} catch (err) { } catch (err) {
console.error(err) log('Error renaming frame', err)
return process.exit(10) return process.exit(10)
} }
@ -317,14 +372,14 @@ async function randomSort (list, pattern, realtime) {
remove = list.slice(removeLen, list.length) remove = list.slice(removeLen, list.length)
list = list.slice(0, removeLen) list = list.slice(0, removeLen)
console.log(`Skipping extra frames...`) log(`Skipping extra frames...`)
for (let i = 0; i < remove.length; i++) { for (let i = 0; i < remove.length; i++) {
oldPath = path.join(TMPPATH, remove[i]) oldPath = path.join(TMPPATH, remove[i])
console.log(`Skipping ${list[i]}`) log(`Skipping ${list[i]}`)
try { try {
await fs.unlink(oldPath) await fs.unlink(oldPath)
} catch (err) { } catch (err) {
console.error(err) log('Error deleting frame', err)
} }
} }
} }
@ -334,13 +389,13 @@ async function randomSort (list, pattern, realtime) {
newName = `./render_${zeroPad(frameCount)}${ext}` newName = `./render_${zeroPad(frameCount)}${ext}`
newPath = path.join(TMPPATH, newName) newPath = path.join(TMPPATH, newName)
console.log(`Renaming ${list[i]} -> ${newName}`) log(`Renaming ${list[i]} -> ${newName}`)
try { try {
await fs.move(oldPath, newPath) await fs.move(oldPath, newPath)
newList.push(newName) newList.push(newName)
} catch (err) { } catch (err) {
console.error(err) log('Error moving frame', err)
} }
frameCount++ frameCount++
@ -364,19 +419,19 @@ async function render (output, avconv) {
let framerate = `24` let framerate = `24`
const cmd = `${exe} -r ${framerate} -f image2 -s ${resolution} -i ${frames} ${format} -y ${output}` const cmd = `${exe} -r ${framerate} -f image2 -s ${resolution} -i ${frames} ${format} -y ${output}`
console.log(`Exporting video ${output}`) log(`Exporting video ${output}`)
console.log(cmd) log(cmd)
/*try { /*try {
await exec(`ls "${TMPPATH}"`) await exec(`ls "${TMPPATH}"`)
} catch (err) { } catch (err) {
console.log(err) log(err)
}*/ }*/
try { try {
await exec(cmd) await exec(cmd)
} catch (err) { } catch (err) {
console.error(err) log('Error rendering video with ffmpeg', err)
} }
} }
/** /**
@ -392,15 +447,16 @@ async function main (arg) {
let realtime = false let realtime = false
let avconv = false let avconv = false
let random = false let random = false
let e = false
console.time('frameloom') console.time('frameloom')
if (input.length < 2) { if (input.length < 2) {
console.error('Must provide more than 1 input') log('Must provide more than 1 input', {})
return process.exit(1) return process.exit(1)
} }
if (!output) { if (!output) {
console.error('Must provide video output path') log('Must provide video output path', {})
return process.exit(2) return process.exit(2)
} }
@ -416,6 +472,14 @@ async function main (arg) {
TMPDIR = arg.tmp TMPDIR = arg.tmp
} }
if (arg.exec) {
e = arg.exec
}
if (arg.quiet) {
QUIET = true
}
if (arg.pattern) { if (arg.pattern) {
pattern = arg.pattern.split(':') pattern = arg.pattern.split(':')
pattern = pattern.map(el =>{ pattern = pattern.map(el =>{
@ -434,39 +498,49 @@ async function main (arg) {
try { try {
await clear() await clear()
} catch (err) { } catch (err) {
console.error(err) log('Error clearing temp directory', err)
return process.exit(3) return process.exit(3)
} }
console.log(`Processing video files ${input.join(', ')} into ${output} with pattern ${pattern.join(':')}`) log(`Processing video files ${input.join(', ')} into ${output} with pattern ${pattern.join(':')}`)
for (let i = 0; i <input.length; i++) { for (let i = 0; i < input.length; i++) {
try { try {
await frames(input[i], i, avconv) await frames(input[i], i, avconv)
} catch (err) { } catch (err) {
console.error(err) log('Error exporting video fie to image sequence', err)
return process.exit(4) return process.exit(4)
} }
} }
log('Weaving frames')
try { try {
await weave(pattern, realtime, random) await weave(pattern, realtime, random)
} catch (err) { } catch (err) {
console.error(err) log('Error weaving', err)
return process.exit(5) return process.exit(5)
} }
if (e) {
try {
await subExec(e)
} catch (err) {
log('Error performing subcommand', err)
return process.exit(7)
}
}
try { try {
await render(output, avconv) await render(output, avconv)
} catch (err) { } catch (err) {
console.error(err) log('Error rendering', err)
return process.exit(6) return process.exit(6)
} }
try { try {
await clear() await clear()
} catch (err) { } catch (err) {
console.error(err) log('Error clearing files', err)
return process.exit(7) return process.exit(7)
} }
@ -474,7 +548,7 @@ async function main (arg) {
} }
program program
.version('1.0.0') .version(pkg.version)
.option('-i, --input [files]', 'Specify input videos with paths seperated by colon') .option('-i, --input [files]', 'Specify input videos with paths seperated by colon')
.option('-o, --output [file]', 'Specify output path of video') .option('-o, --output [file]', 'Specify output path of video')
.option('-p, --pattern [pattern]', 'Specify a pattern for the flicker 1:1 is standard') .option('-p, --pattern [pattern]', 'Specify a pattern for the flicker 1:1 is standard')
@ -482,6 +556,8 @@ program
.option('-t, --tmp [dir]', 'Specify tmp directory for exporting frames') .option('-t, --tmp [dir]', 'Specify tmp directory for exporting frames')
.option('-a, --avconv', 'Specify avconv if preferred to ffmpeg') .option('-a, --avconv', 'Specify avconv if preferred to ffmpeg')
.option('-R, --random', 'Randomize frames. Ignores pattern if included') .option('-R, --random', 'Randomize frames. Ignores pattern if included')
.option('-e, --exec', 'Command to execute on every frame. Specify {{i}} and {{o}} if the command requires it, otherwise frame path will be appended to command')
.option('-q, --quiet', 'Suppresses all log messages')
.parse(process.argv) .parse(process.argv)
main(program) main(program)

View File

@ -6,7 +6,7 @@
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"version": "npm --no-git-tag-version version patch", "version": "npm --no-git-tag-version version patch",
"docs" : "sh docs.sh" "docs": "sh docs.sh"
}, },
"author": "sixteenmillimeter", "author": "sixteenmillimeter",
"license": "MIT", "license": "MIT",