From 57255405b5a630678e42f20565da4287d7910694 Mon Sep 17 00:00:00 2001 From: M McWilliams <hi@mmcwilliams.com> Date: Wed, 11 Oct 2017 13:18:14 -0700 Subject: [PATCH 01/10] Ignore nexe files from building --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7e51146..a0b655f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ tmp/* temp/* +.nexe \ No newline at end of file From c65f08d86c57839589d581435fe8225d5fa88712 Mon Sep 17 00:00:00 2001 From: M McWilliams <hi@mmcwilliams.com> Date: Wed, 11 Oct 2017 13:58:37 -0700 Subject: [PATCH 02/10] Use latest node version with nexe and add lcok file --- package-lock.json | 5 +++++ package.json | 16 ++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c529078 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5 @@ +{ + "name": "v2f", + "version": "1.0.0", + "lockfileVersion": 1 +} diff --git a/package.json b/package.json index d57d4d2..f221e0c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "v2f", - "version": "1.0.0", + "version": "1.0.1", "description": "Turn a video into strips of precise 16mm-size stills", "main": "v2f.js", "scripts": { @@ -8,12 +8,12 @@ }, "author": "mmcwilliams", "license": "MIT", - "nexe" : { - "output" : "../video_to_page_nexe/v2f", - "runtime": { - "ignoreFlags": true, - "framework" : "nodejs", - "version" : "5.0.0" - } + "nexe": { + "output": "../video_to_page_nexe/v2f", + "runtime": { + "ignoreFlags": true, + "framework": "nodejs", + "version": "8.6.0" + } } } From 36c4875d1b664700e36ea8c594d62e76801a9467 Mon Sep 17 00:00:00 2001 From: M McWilliams <hi@mmcwilliams.com> Date: Wed, 11 Oct 2017 14:00:12 -0700 Subject: [PATCH 03/10] Update project readme and a readme file for explaining the source. --- Readme.md | 7 +++++-- docs/Readme.md | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 docs/Readme.md diff --git a/Readme.md b/Readme.md index e3a5c59..23c196f 100644 --- a/Readme.md +++ b/Readme.md @@ -3,7 +3,7 @@ v2f Convert video to 16mm-sized strips of frames. For transferring to acetate and other experimental needs. -Look how easy it is to use: +Use the distributed binary ./v2f ./path_to_video.mov 300 @@ -22,7 +22,7 @@ Releases Dependencies ------------ -- node.js (or use a compiled version) +- node.js (or use a [released version](https://github.com/sixteenmillimeter/v2f/releases/)) - libav - ImageMagick @@ -37,11 +37,14 @@ Ubuntu apt-get install libav imagemagick + + Contribute ---------- - Issue Tracker: https://github.com/sixteenmillimeter/v2f/issues - Source Code: https://github.com/sixteenmillimeter/v2f +- Home Page: https://sixteenmillimeter.com/projects/v2f Support ------- diff --git a/docs/Readme.md b/docs/Readme.md new file mode 100644 index 0000000..e1e1c82 --- /dev/null +++ b/docs/Readme.md @@ -0,0 +1,36 @@ +## Functions + +<dl> +<dt><a href="#convert">convert(path, dpi, length)</a></dt> +<dd><p>Turn video into sheet of images</p> +</dd> +<dt><a href="#stitch">stitch(loc, dim)</a></dt> +<dd><p>Stitch rendered frames into strips</p> +</dd> +</dl> + +<a name="convert"></a> + +## convert(path, dpi, length) +Turn video into sheet of images + +**Kind**: global function + +| Param | Type | Description | +| --- | --- | --- | +| path | <code>String</code> | file path (absolute) | +| dpi | <code>Integer</code> | target printing dpi | +| length | <code>Integer</code> | strip length in frames | + +<a name="stitch"></a> + +## stitch(loc, dim) +Stitch rendered frames into strips + +**Kind**: global function + +| Param | Type | Description | +| --- | --- | --- | +| loc | <code>String</code> | Path of folder containing frames | +| dim | <code>Object</code> | Dimensions object | + From ff8d0a5f93720db66a9aae75b895b1f298e30efd Mon Sep 17 00:00:00 2001 From: M McWilliams <hi@mmcwilliams.com> Date: Wed, 11 Oct 2017 14:01:25 -0700 Subject: [PATCH 04/10] Es6 refactor, more to come. Will be re-structuring v2f.js to handle multiple formats and better manage files in different locations. --- v2f.js | 166 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 91 insertions(+), 75 deletions(-) diff --git a/v2f.js b/v2f.js index d85a056..e1b7983 100755 --- a/v2f.js +++ b/v2f.js @@ -1,103 +1,119 @@ -var exec = require('child_process').exec, - fs = require('fs'), - _tmp = './temp'; +/*jshint strict: true, esversion:6, node: true, asi: true*/ -//var frame_height = 7.61; -//var frame_height = 7.49; -var frame_height = 7.62; -var frame_padding = 0; +'use strict' +const exec = require('child_process').exec +const fs = require('fs') +const _tmp = './temp' -var frame_dimensions = function (dpi) { - var h = Math.round(frame_height * (dpi / 25.4)), - w = Math.round(10.5 * (dpi / 25.4)), - o = Math.round(16 * (dpi / 25.4)); - return {h: h, w: w, o: o, dpi: dpi}; -}; +//var frame_height = 7.61 +//var frame_height = 7.49 +let frame_height = 7.62 +let frame_padding = 0 -/* -convert() - Turn video into sheet of images +class Dimensions{ + constructor (film, dpi) { + const IN = dpi / 25.4 + this.h = Math.round(film.frame_height * IN) + this.w = Math.round(film.a * IN) + this.o = Math.round(film.b * IN) + this.dpi = dpi + this.film = film + } +} -@param: path - file path (absolute) -@param: dpi - target printing dpi -@param: length - strip length in frames +/** * + * Turn video into sheet of images + * @function + * @param {String} path file path (absolute) + * @param {Integer} dpi target printing dpi + * @param {Integer} length strip length in frames + * */ -var convert = function (path, dpi) { - 'use strict'; - var dim = frame_dimensions(dpi), - file = path.split('/').pop(), - loc = _tmp + '/', - execStr = 'avconv -i "' + path + '" -s ' + dim.w + 'x' + dim.h + ' -qscale 1 "' + loc + 'sequence_%04d.jpg"'; +function convert (path, dpi) { + const film = { frame_height: frame_height, a : 10.5, b : 16} + const dim = new Dimensions(film, dpi) + const file = path.split('/').pop() + const loc = _tmp + '/' + const execStr = `avconv -i "${path}" -s ${dim.w}x${dim.h} -qscale 1 "${loc}sequence_%04d.jpg"` - console.log('Converting ' + file + '...'); - console.log('Exporting all frames with aspect ratio: ' + (dim.w / dim.h) + '...'); + console.log(`Converting ${file}...`) + console.log(`Exporting all frames with aspect ratio: ${dim.w / dim.h} ...`) - fs.mkdirSync(_tmp); + fs.mkdirSync(_tmp) - exec(execStr, function (ste, std) { + exec(execStr, (ste, std) => { if (ste) { - return errorHandle(ste); + return errorHandle(ste) } - console.log('Frames exported successfully!'); - stitch(loc.substring(0, loc.length - 1), dim); - }); -}; + console.log('Frames exported successfully!') + stitch(loc.substring(0, loc.length - 1), dim) + }) +} -var stitch = function (loc, dim) { - 'use strict'; - var length = Math.floor((11 * dim.dpi) / dim.h) - 1, - width = Math.floor((8.5 * dim.dpi / dim.o)) - 1, - page = 0, - pageCount = 0, - cmd = 'find "' + loc + '" -type f -name "sequence_*.jpg"', - find_cb = function (ste, std) { +/** * + * Stitch rendered frames into strips + + * @function + * @param {String} loc Path of folder containing frames + * @param {Object} dim Dimensions object + * +*/ + +function stitch (loc, dim) { + const length = Math.floor((11 * dim.dpi) / dim.h) - 1 + const width = Math.floor((8.5 * dim.dpi / dim.o)) - 1 + let page = 0 + let pageCount = 0 + let cmd = `find "${loc}" -type f -name "sequence_*.jpg"` + function find_cb (ste, std) { if (ste) { - return errorHandle(ste); + return errorHandle(ste) } - var frames = std.split('\n'), - execStr = 'montage ', - montage_cb = function (stee, stdd) { + const frames = std.split('\n') + let execStr = 'montage ' + function montage_cb (stee, stdd) { if (stee) { - return errorHandle(ste); + return errorHandle(ste) } - console.log('Created page_' + pageCount + '.jpg!'); - pageCount++; + console.log(`Created page_${pageCount}.jpg!`) + pageCount++ if (pageCount === page) { console.log('Cleaning up...'); - setTimeout(function () { - exec('find "' + loc + '" -type f -name "sequence_*.jpg" -delete', function () { - fs.rmdirSync(_tmp); - console.log('Done!'); - }); - }, 1000); + setTimeout(() => { + exec(`find "${loc}" -type f -name "sequence_*.jpg" -delete`, () => { + fs.rmdirSync(_tmp) + console.log('Done!') + }) + }, 1000) } }; - for (var i = 0; i < frames.length; i++) { - execStr += frames[i] + ' '; + for (let i = 0; i < frames.length; i++) { + execStr += frames[i] + ' ' if ((i + 1) % (width * length) === 0 || i === frames.length - 1) { - execStr += '\ -tile 1x' + length + ' -geometry ' + dim.w + 'x' + dim.h + '+' + Math.round((dim.o - dim.w) / 2) + '+0 miff:- |\ \nmontage - -geometry +0+0 -tile ' + width + 'x1 -density ' + dim.dpi + ' "./page_' + page + '.jpg"'; - exec(execStr, montage_cb); - execStr = 'montage '; - page++; + execStr += '\ -tile 1x' + length + ' -geometry ' + dim.w + 'x' + dim.h + '+' + Math.round((dim.o - dim.w) / 2) + '+0 miff:- |\ \nmontage - -geometry +0+0 -tile ' + width + 'x1 -density ' + dim.dpi + ' "./page_' + page + '.jpg"' + exec(execStr, montage_cb) + execStr = 'montage ' + page++ } } - }; - - loc = _tmp; - - console.log('Stitching frames into sheets...'); - console.log('Sheets will contain ' + width + 'x' + length + ' frames...'); - exec(cmd, find_cb); -}; -var errorHandle = function (err) { - 'use strict'; - if (process.argv.indexOf('-v') !== -1 || process.argv.indexOf('--verbose') !== -1){ - console.error(err); - } else { - console.error('Error running program. Run in verbose mode for more info (-v,--verbose)'); } - process.exit(1); + + loc = _tmp + + console.log('Stitching frames into sheets...') + console.log(`Sheets will contain ${width}x${length} frames...`) + exec(cmd, find_cb) +}; + +var errorHandle = function (err) { + if (process.argv.indexOf('-v') !== -1 || process.argv.indexOf('--verbose') !== -1){ + console.error(err) + } else { + console.error('Error running program. Run in verbose mode for more info (-v,--verbose)') + } + process.exit(1) }; process.on('uncaughtException', function (err) { From 79b099b05891f48e906a82c427a84317826cfe43 Mon Sep 17 00:00:00 2001 From: mmcwilliams <hi@mmcwilliams.com> Date: Wed, 11 Oct 2017 17:21:38 -0400 Subject: [PATCH 05/10] Update version in package-lock --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index c529078..db68590 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { "name": "v2f", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 1 } From 20930513f9df8a6674cd265c92350a192247fc25 Mon Sep 17 00:00:00 2001 From: mmcwilliams <hi@mmcwilliams.com> Date: Wed, 11 Oct 2017 19:58:21 -0400 Subject: [PATCH 06/10] Check if local temp file, if not, make one --- v2f.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2f.js b/v2f.js index e1b7983..68766cb 100755 --- a/v2f.js +++ b/v2f.js @@ -40,7 +40,7 @@ function convert (path, dpi) { console.log(`Converting ${file}...`) console.log(`Exporting all frames with aspect ratio: ${dim.w / dim.h} ...`) - fs.mkdirSync(_tmp) + if (!fs.existsSync(_tmp)) fs.mkdirSync(_tmp) exec(execStr, (ste, std) => { if (ste) { From 5cdd191f35a014a9f9a8fbdf71ee9854e5192c6d Mon Sep 17 00:00:00 2001 From: mmcwilliams <hi@mmcwilliams.com> Date: Wed, 11 Oct 2017 20:06:27 -0400 Subject: [PATCH 07/10] Use system tmp, to prevent files from accumulating in the local directory --- v2f.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/v2f.js b/v2f.js index 68766cb..b91d356 100755 --- a/v2f.js +++ b/v2f.js @@ -3,7 +3,7 @@ 'use strict' const exec = require('child_process').exec const fs = require('fs') -const _tmp = './temp' +const _tmp = '/tmp' //var frame_height = 7.61 //var frame_height = 7.49 @@ -88,7 +88,7 @@ function stitch (loc, dim) { }) }, 1000) } - }; + } for (let i = 0; i < frames.length; i++) { execStr += frames[i] + ' ' if ((i + 1) % (width * length) === 0 || i === frames.length - 1) { @@ -105,7 +105,7 @@ function stitch (loc, dim) { console.log('Stitching frames into sheets...') console.log(`Sheets will contain ${width}x${length} frames...`) exec(cmd, find_cb) -}; +} var errorHandle = function (err) { if (process.argv.indexOf('-v') !== -1 || process.argv.indexOf('--verbose') !== -1){ @@ -116,22 +116,22 @@ var errorHandle = function (err) { process.exit(1) }; -process.on('uncaughtException', function (err) { - errorHandle(err); -}); +process.on('uncaughtException', err => { + errorHandle(err) +}) if (typeof process.argv[2] === 'undefined') { - console.error('No path to video defined'); - process.exit(1); + console.error('No path to video defined') + process.exit(1) } if (typeof process.argv[3] === 'undefined') { - process.argv[3] = 300; - console.log('Using default 300dpi'); + process.argv[3] = 300 + console.log('Using default 300dpi') } -convert(process.argv[2], process.argv[3]); +convert(process.argv[2], process.argv[3]) /* From 7cb27e7bea18c4bbf39bd69c1e1e766f2d4b9a30 Mon Sep 17 00:00:00 2001 From: mmcw-dev <hi@mmcwilliams.com> Date: Fri, 27 Oct 2017 13:28:06 -0400 Subject: [PATCH 08/10] Install async and commander --- package-lock.json | 23 ++++++++++++++++++++++- package.json | 6 +++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index db68590..6845444 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,26 @@ { "name": "v2f", "version": "1.0.1", - "lockfileVersion": 1 + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "async": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", + "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", + "requires": { + "lodash": "4.17.4" + } + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + } + } } diff --git a/package.json b/package.json index f221e0c..bc91983 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,11 @@ "runtime": { "ignoreFlags": true, "framework": "nodejs", - "version": "8.6.0" + "version": "8.7.0" } + }, + "dependencies": { + "async": "^2.5.0", + "commander": "^2.11.0" } } From 73775da9d1282bad184a03c6e99ff767013433d5 Mon Sep 17 00:00:00 2001 From: mmcw-dev <hi@mmcwilliams.com> Date: Sun, 29 Oct 2017 23:52:14 -0400 Subject: [PATCH 09/10] Finished changes required to resolve issue #1 and issue #2. Added super16 and 35mm (4 perf) image sizes --- .gitignore | 1 + v2f.js | 266 +++++++++++++++++++++++++++++++---------------------- 2 files changed, 157 insertions(+), 110 deletions(-) diff --git a/.gitignore b/.gitignore index a0b655f..aa4b8ea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +node_modules tmp/* temp/* .nexe \ No newline at end of file diff --git a/v2f.js b/v2f.js index b91d356..0ef9b9c 100755 --- a/v2f.js +++ b/v2f.js @@ -1,53 +1,103 @@ /*jshint strict: true, esversion:6, node: true, asi: true*/ 'use strict' +const cmd = require('commander') +const async = require('async') const exec = require('child_process').exec const fs = require('fs') -const _tmp = '/tmp' +const path = require('path') -//var frame_height = 7.61 -//var frame_height = 7.49 -let frame_height = 7.62 -let frame_padding = 0 +const TMP = '/tmp/v2f/' class Dimensions{ - constructor (film, dpi) { + constructor (filmStr, dpi) { const IN = dpi / 25.4 - this.h = Math.round(film.frame_height * IN) - this.w = Math.round(film.a * IN) - this.o = Math.round(film.b * IN) + const film = this._gauge(filmStr) + + this.h = Math.round(film.h * IN) //frame height + this.w = Math.round(film.w * IN) //frame width + this.o = Math.round(film.o * IN) //space between columns this.dpi = dpi this.film = film } + + _gauge (film) { + if (film === '16mm') { + return { + h: 7.62, + w : 10.5, + o : 16 + } + } else if (film === 'super16'){ + return { + h: 7.62, + w : 12.75, + o : 16 + } + } else if (film === '35mm') { + return { + h : 19.05, + w : 22, + o : 35 + } + } else { + error('Film type not found, see --help for more info') + } + } +} + +/** + * + * + * @function + * @param {Object} Commander object + */ +function initialize (command) { + const dpi = command.dpi || 300 + const film = command.film || '16mm' + const input = command.input || command.args[0] || error('No input file, see --help for more info') + const output = command.output || command.args[1] || error('No ouput directory, see --help for more info') + const dim = new Dimensions(film, dpi) + + if (!fs.existsSync(input)) error(`Video "${input}" cannot be found`) + + async.series([ + next => { + convert(input, dim, next) + }, + next => { + stitch(output, dim, next) + }, + cleanup + ], () => { + console.log(`Finished creating pages`) + }) } /** * - * Turn video into sheet of images - + * Create image sequence from source video, using + * * @function - * @param {String} path file path (absolute) - * @param {Integer} dpi target printing dpi - * @param {Integer} length strip length in frames + * @param {String} input file path (absolute) + * @param {Integer} dpi target printing dpi + * @param {Integer} length strip length in frames * */ -function convert (path, dpi) { - const film = { frame_height: frame_height, a : 10.5, b : 16} - const dim = new Dimensions(film, dpi) - const file = path.split('/').pop() - const loc = _tmp + '/' - const execStr = `avconv -i "${path}" -s ${dim.w}x${dim.h} -qscale 1 "${loc}sequence_%04d.jpg"` +function convert (input, dim, next) { + const file = input.split('/').pop() + const execStr = `avconv -i "${input}" -s ${dim.w}x${dim.h} -qscale 1 "${TMP}v2f_sequence_%04d.jpg"` console.log(`Converting ${file}...`) - console.log(`Exporting all frames with aspect ratio: ${dim.w / dim.h} ...`) + console.log(`Exporting all frames with aspect ratio: ${dim.w / dim.h}...`) - if (!fs.existsSync(_tmp)) fs.mkdirSync(_tmp) + if (!fs.existsSync(TMP)) fs.mkdirSync(TMP) exec(execStr, (ste, std) => { if (ste) { - return errorHandle(ste) + return error(ste) } console.log('Frames exported successfully!') - stitch(loc.substring(0, loc.length - 1), dim) + next() }) } @@ -55,114 +105,110 @@ function convert (path, dpi) { * Stitch rendered frames into strips * @function - * @param {String} loc Path of folder containing frames - * @param {Object} dim Dimensions object + * @param {String} output Path of folder containing frames + * @param {Object} dim Dimensions object + * @param {Function} next Async lib callback function * */ - -function stitch (loc, dim) { +function stitch (output, dim, next) { const length = Math.floor((11 * dim.dpi) / dim.h) - 1 const width = Math.floor((8.5 * dim.dpi / dim.o)) - 1 + const loc = TMP.substring(0, TMP.length - 1) + const diff = Math.round((dim.o - dim.w) / 2) let page = 0 let pageCount = 0 - let cmd = `find "${loc}" -type f -name "sequence_*.jpg"` - function find_cb (ste, std) { - if (ste) { - return errorHandle(ste) - } - const frames = std.split('\n') - let execStr = 'montage ' - function montage_cb (stee, stdd) { - if (stee) { - return errorHandle(ste) - } - - console.log(`Created page_${pageCount}.jpg!`) - pageCount++ - if (pageCount === page) { - console.log('Cleaning up...'); - setTimeout(() => { - exec(`find "${loc}" -type f -name "sequence_*.jpg" -delete`, () => { - fs.rmdirSync(_tmp) - console.log('Done!') - }) - }, 1000) - } - } - for (let i = 0; i < frames.length; i++) { - execStr += frames[i] + ' ' - if ((i + 1) % (width * length) === 0 || i === frames.length - 1) { - execStr += '\ -tile 1x' + length + ' -geometry ' + dim.w + 'x' + dim.h + '+' + Math.round((dim.o - dim.w) / 2) + '+0 miff:- |\ \nmontage - -geometry +0+0 -tile ' + width + 'x1 -density ' + dim.dpi + ' "./page_' + page + '.jpg"' - exec(execStr, montage_cb) - execStr = 'montage ' - page++ - } - } - } - - loc = _tmp + let cmd = `find "${loc}" -type f -name "v2f_sequence_*.jpg"` console.log('Stitching frames into sheets...') console.log(`Sheets will contain ${width}x${length} frames...`) - exec(cmd, find_cb) + + exec(cmd, (ste, std) => { + if (ste) { + return error(ste) + } + let jobs = [] + let cmds = [] + let frames = std.split('\n') + let execStr = 'montage ' + let pagePath = `` + let i = 0 + + frames = frames.filter(elem => { + if (elem.indexOf('find: ') === -1) { + return elem + } + }) + frames.sort() + for (let frame of frames) { + execStr += `${frame} ` + if ((i + 1) % (width * length) === 0 || i === frames.length - 1) { + pagePath = path.join(output, `./page_${pad(page)}.jpg`) + execStr += `\ -tile 1x${length} -geometry ${dim.w}x${dim.h}+${diff}+0 miff:- |\ \nmontage - -geometry +0+0 -tile ${width}x1 -density ${dim.dpi} "${pagePath}"` + console.log(execStr) + process.exit() + cmds.push(execStr) + execStr = 'montage ' + page++ + } + i++ + } + jobs = cmds.map(cmd => { + return cb => { + exec(cmd, (err, std, ste) => { + if (err) { + return error(err) + } + console.log(`Created page of ${width}x${length} frames!`) + cb() + }) + } + }) + async.series(jobs, next) + }) } -var errorHandle = function (err) { +function cleanup (next) { + console.log('Cleaning up...'); + exec(`rm -r "${TMP}"`, (err) => { + if (err) console.error(err) + if (next) next() + }) +} + +function pad (n) { + return ('00000' + n).slice(-5) +} + +var error = function (err) { if (process.argv.indexOf('-v') !== -1 || process.argv.indexOf('--verbose') !== -1){ console.error(err) } else { console.error('Error running program. Run in verbose mode for more info (-v,--verbose)') } process.exit(1) -}; +} process.on('uncaughtException', err => { - errorHandle(err) + error(err) }) +//convert(process.argv[2], process.argv[3]) -if (typeof process.argv[2] === 'undefined') { - console.error('No path to video defined') - process.exit(1) +//fix for nexe +let args = [].concat(process.argv) +if (args[1].indexOf('v2f.js') === -1) { + args.reverse() + args.push('node') + args.reverse() } -if (typeof process.argv[3] === 'undefined') { - process.argv[3] = 300 - console.log('Using default 300dpi') -} +cmd.arguments('<input> <output>') + .version('1.1.0') + .option('-i, --input <path>', 'Video source to print to film strip, anything that avconv can read') + .option('-o, --output <path>', 'Output directory, will print images on A4 standard paper file') + .option('-d, --dpi <dpi>', 'DPI output pages') + .option('-f, --film <gauge>', 'Choose film gauge: 16mm, super16, 35mm') + .option('-v, --verbose', 'Run in verbose mode') + .parse(args) -convert(process.argv[2], process.argv[3]) - -/* - - INSTALLATION AND RUNNING - -*/ - -//Install in this order to satisfy requirements: GCC required by MacPorts, etc. - -//Install Node http://nodejs.org/dist/v0.10.22/node-v0.10.22.pkg -//Install GCC https://github.com/kennethreitz/osx-gcc-installer#option-1-downloading-pre-built-binaries -//Install MacPorts http://www.macports.org/install.php -//Install ImageMagick in terminal type "sudo port install ImageMagick" -//Install avconv -see below - -/* -Download and unzip http://libav.org/releases/libav-9.6.tar.gz -in terminal type "cd " and drag in unzipped folder and hit enter -in terminal copy "sudo port install yasm zlib bzip2 faac lame speex libogg libvorbis libtheora libvpx x264 XviD openjpeg15 opencore-amr freetype" (without quotes) hit enter -in terminal copy "./configure \ --enable-gpl --enable-libx264 --enable-libxvid \ --enable-version3 --enable-libopencore-amrnb --enable-libopencore-amrwb \ --enable-nonfree --enable-libfaac \ --enable-libmp3lame --enable-libspeex --enable-libvorbis --enable-libtheora --enable-libvpx \ --enable-libopenjpeg --enable-libfreetype --enable-doc --enable-gnutls --enable-shared" hit enter -(if that gives errors just use "./configure" and hit enter) -in terminal copy "make && sudo make install" hit enter - - that will install it -*/ - -//run by going to terminal typing "node " dragging this script into the terminal, dragging the video into the terminal and adding a DPI value and hitting enter -//the command should look something like this: -//node /Users/stenzel/Desktop/video_to_page.js /Users/stenzel/Desktop/PaulRobeson/Paul\ Robeson\ discusses\ Othello.mp4 600 - - -//Get the absolute path of any file by dragging it into terminal and copying the results -//Must be enclosed by '' -//Will generate pages and frames in same folder as source video +initialize(cmd) \ No newline at end of file From 65b89efa2eef49c64eaf3bc62f8b0533e46b4ce4 Mon Sep 17 00:00:00 2001 From: mmcw-dev <hi@mmcwilliams.com> Date: Sun, 29 Oct 2017 23:56:35 -0400 Subject: [PATCH 10/10] Update project to version 1.1 for release. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bc91983..b080177 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "v2f", - "version": "1.0.1", + "version": "1.1.0", "description": "Turn a video into strips of precise 16mm-size stills", "main": "v2f.js", "scripts": {