Features cloned from https://github.com/sixteenmillimeter/frameloom.git.
Take multiple audio files, slice them into small pieces and then re-assemble them into a single file. Made to work in concert with frameloom. Shells out to sox under the hood. Use commander and fs-extra as production dependencies, and pkg, jsdoc-to-markdown and qunit as dev dependencies
This commit is contained in:
parent
7babd06b60
commit
4b885e3562
|
@ -59,3 +59,9 @@ typings/
|
||||||
|
|
||||||
# next.js build output
|
# next.js build output
|
||||||
.next
|
.next
|
||||||
|
|
||||||
|
examples
|
||||||
|
dist
|
||||||
|
*.AppleDouble
|
||||||
|
*.Parent
|
||||||
|
*.DS_Store
|
|
@ -0,0 +1,564 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const execRaw = require('child_process').exec
|
||||||
|
const os = require('os')
|
||||||
|
const path = require('path')
|
||||||
|
const program = require('commander')
|
||||||
|
const fs = require('fs-extra')
|
||||||
|
const packageJson = require('./package.json')
|
||||||
|
|
||||||
|
let TMPDIR = os.tmpdir() || '/tmp'
|
||||||
|
let TMPPATH
|
||||||
|
|
||||||
|
let EXE = `sox`
|
||||||
|
let IDENTIFY = `soxi`
|
||||||
|
let SLICE = (1000 / 24) + ''
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shells out to execute a command with async/await.
|
||||||
|
* Async wrapper to exec module.
|
||||||
|
*
|
||||||
|
* @param {string} cmd Command to execute
|
||||||
|
*
|
||||||
|
* @returns {Promise} Promise containing the complete stdio
|
||||||
|
**/
|
||||||
|
async function exec (cmd) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
return execRaw(cmd, (err, stdio, stderr) => {
|
||||||
|
if (err) return reject(err)
|
||||||
|
return resolve(stdio)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Delays process for specified amount of time in milliseconds.
|
||||||
|
*
|
||||||
|
* @param {integer} ms Milliseconds to delay for
|
||||||
|
*
|
||||||
|
* @returns {Promise} Promise that resolves after set time
|
||||||
|
**/
|
||||||
|
async function delay (ms) {
|
||||||
|
return new Promise((resolve, reject) =>{
|
||||||
|
return setTimeout(resolve, ms)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Pads a numerical value with preceding zeros to make strings same length.
|
||||||
|
*
|
||||||
|
* @param {integer} i Number to pad
|
||||||
|
* @param {integer} max (optional) Maximum length of string to pad to
|
||||||
|
*
|
||||||
|
* @returns {string} Padded number as a string
|
||||||
|
**/
|
||||||
|
function zeroPad (i, max = 5) {
|
||||||
|
let len = (i + '').length
|
||||||
|
let str = i + ''
|
||||||
|
for (let x = 0; x < max - len; x++) {
|
||||||
|
str = '0' + str
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Shuffles an array into a random state.
|
||||||
|
*
|
||||||
|
* @param {array} a Array to randomize
|
||||||
|
**/
|
||||||
|
function shuffle (a) {
|
||||||
|
for (let i = a.length; i; i--) {
|
||||||
|
let j = Math.floor(Math.random() * i);
|
||||||
|
[a[i - 1], a[j]] = [a[j], a[i - 1]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Clears the temporary directory of all files.
|
||||||
|
* Establishes a directory if none exists.
|
||||||
|
**/
|
||||||
|
async function clear () {
|
||||||
|
let cmd = `rm -r "${TMPPATH}"`
|
||||||
|
let exists
|
||||||
|
|
||||||
|
try {
|
||||||
|
exists = await fs.exists(TMPPATH)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists) {
|
||||||
|
console.log(`Clearing temp directory "${TMPPATH}"`)
|
||||||
|
try {
|
||||||
|
await exec(cmd)
|
||||||
|
} catch (err) {
|
||||||
|
//suppress error
|
||||||
|
console.dir(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fs.mkdir(TMPPATH)
|
||||||
|
} catch (err) {
|
||||||
|
if (err.code !== 'EEXIST') {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parses timecode string to float of total seconds
|
||||||
|
*
|
||||||
|
* @param {string} str Timecode string to parse
|
||||||
|
*
|
||||||
|
* @returns {float} Seconds at float
|
||||||
|
**/
|
||||||
|
function parseTC (str) {
|
||||||
|
const parts = str.split(':')
|
||||||
|
let sec = 0
|
||||||
|
if (parts[0] != 0) sec += parseFloat(parts[0]) * 60 * 60
|
||||||
|
if (parts[1] != 0) sec += parseFloat(parts[1]) * 60
|
||||||
|
if (parts[2] != 0) sec += parseFloat(parts[2])
|
||||||
|
return sec
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns offset position of audio file to slice at.
|
||||||
|
*
|
||||||
|
* @param {integer} i Count of slice to make
|
||||||
|
* @param {float} slice Length of slice, might be str
|
||||||
|
*
|
||||||
|
* @returns {str} New position cast as string
|
||||||
|
**/
|
||||||
|
async function audioLength (filePath) {
|
||||||
|
const exe = IDENTIFY
|
||||||
|
const cmd = `${exe} -d "${filePath}"`
|
||||||
|
let str
|
||||||
|
|
||||||
|
try {
|
||||||
|
str = await exec(cmd)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
process.exit(11)
|
||||||
|
}
|
||||||
|
return parseTC(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns offset position of audio file to slice at.
|
||||||
|
*
|
||||||
|
* @param {integer} i Count of slice to make
|
||||||
|
* @param {float} slice Length of slice, might be str
|
||||||
|
*
|
||||||
|
* @returns {str} New position cast as string
|
||||||
|
**/
|
||||||
|
|
||||||
|
function offset (i, slice) {
|
||||||
|
return (i * (parseFloat(slice) / 1000)) + ''
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exports all slices from audio file. Appends number to the string
|
||||||
|
* to keep slices in alternating order to be quickly stitched together
|
||||||
|
* or re-sorted.
|
||||||
|
*
|
||||||
|
* @param {string} file String representing path to audio file
|
||||||
|
* @param {integer} order Integer to be appended to pathname of file
|
||||||
|
*
|
||||||
|
* @returns {string} String with the export order, not sure why I did this
|
||||||
|
**/
|
||||||
|
async function slices (file, len, order) {
|
||||||
|
let ext = 'wav'
|
||||||
|
let exe = EXE
|
||||||
|
let slice = SLICE
|
||||||
|
let tmpoutput
|
||||||
|
let cmd
|
||||||
|
let i = 0
|
||||||
|
let total = Math.floor((len * 1000) / parseFloat(slice))
|
||||||
|
console.log(`Exporting ${file} as ${total} slices ${SLICE}ms long...`)
|
||||||
|
|
||||||
|
for (i = 0; i < total; i++) {
|
||||||
|
tmpoutput = path.join(TMPPATH, `export-${zeroPad(i)}_${order}.${ext}`)
|
||||||
|
cmd = `${exe} "${file}" "${tmpoutput}" trim ${offset(i, slice)} ${parseFloat(slice) / 1000}`
|
||||||
|
try {
|
||||||
|
console.log(cmd)
|
||||||
|
await exec(cmd)
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error exporting file', err)
|
||||||
|
return process.exit(3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path.join(TMPPATH, `export-%05d_${order}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-arranges the slices into the order specified in the pattern.
|
||||||
|
* Calls `patternSort()` to perform the rename and unlink actions
|
||||||
|
*
|
||||||
|
* @param {array} pattern Pattern of the slices per input
|
||||||
|
* @param {boolean} realtime Flag to turn on or off realtime behavior (drop slice / number of files)
|
||||||
|
**/
|
||||||
|
async function weave (pattern, realtime, random) {
|
||||||
|
let slices
|
||||||
|
let old
|
||||||
|
let seqFile
|
||||||
|
let seq
|
||||||
|
let ext = '.wav'
|
||||||
|
let alt = false
|
||||||
|
|
||||||
|
console.log('Weaving slices...')
|
||||||
|
|
||||||
|
try {
|
||||||
|
slices = await fs.readdir(TMPPATH)
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error reading tmp directory', err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.dir(slices)
|
||||||
|
slices = slices.filter (file => {
|
||||||
|
if (file.indexOf(ext) !== -1) return true
|
||||||
|
})
|
||||||
|
|
||||||
|
for (let el of pattern) {
|
||||||
|
if (el !== 1) alt = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (random){
|
||||||
|
try {
|
||||||
|
seq = await randomSort(slices, realtime)
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error sorting slices')
|
||||||
|
}
|
||||||
|
} else if (!alt) {
|
||||||
|
try {
|
||||||
|
seq = await standardSort(slices, pattern, realtime)
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error sorting slices')
|
||||||
|
}
|
||||||
|
} else if (alt) {
|
||||||
|
console.warn('This feature is not ready, please check https://github.com/sixteenmillimeter/audioloom.git')
|
||||||
|
process.exit(10)
|
||||||
|
try {
|
||||||
|
seq = await altSort(slices, pattern, realtime)
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error sorting slices')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//console.dir(seq)
|
||||||
|
return seq
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* TODO
|
||||||
|
* Alternate slice sorting method.
|
||||||
|
*
|
||||||
|
* @param {array} list List of slices to group
|
||||||
|
* @param {array} pattern Array representing pattern
|
||||||
|
* @param {boolean} realtime Flag to group with "realtime" behavior
|
||||||
|
**/
|
||||||
|
async function altSort (list, pattern, realtime) {
|
||||||
|
let groups = []
|
||||||
|
let newList = []
|
||||||
|
let frameCount = 0
|
||||||
|
let oldPath
|
||||||
|
let newName
|
||||||
|
let newPath
|
||||||
|
let ext = path.extname(list[0])
|
||||||
|
|
||||||
|
for (let g of pattern) {
|
||||||
|
groups.push([])
|
||||||
|
}
|
||||||
|
for (let 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);
|
||||||
|
|
||||||
|
console.log(`Renaming ${list[i]} -> ${newName}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
//await fs.move(oldPath, newPath, { overwrite: true })
|
||||||
|
newList.push(newName);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
frameCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newList
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Standard frame sorting method.
|
||||||
|
*
|
||||||
|
* @param {array} list List of slices to group
|
||||||
|
* @param {array} pattern Array representing pattern
|
||||||
|
* @param {boolean} realtime Flag to group with "realtime" behavior
|
||||||
|
**/
|
||||||
|
async function standardSort (list, pattern, realtime) {
|
||||||
|
let sliceCount = 0
|
||||||
|
let stepCount
|
||||||
|
let step
|
||||||
|
let skipCount
|
||||||
|
let skip
|
||||||
|
let ext = path.extname(list[0])
|
||||||
|
let oldPath
|
||||||
|
let newName
|
||||||
|
let newPath
|
||||||
|
let newList = []
|
||||||
|
|
||||||
|
if (realtime) {
|
||||||
|
skip = false
|
||||||
|
skipCount = pattern.length + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
if (realtime) {
|
||||||
|
skipCount--;
|
||||||
|
if (skipCount === 0) {
|
||||||
|
skip = !skip;
|
||||||
|
skipCount = pattern.length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oldPath = path.join(TMPPATH, list[i])
|
||||||
|
|
||||||
|
if (skip) {
|
||||||
|
console.log(`Skipping ${list[i]}`)
|
||||||
|
try {
|
||||||
|
await fs.unlink(oldPath)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
newName = `./render_${zeroPad(sliceCount)}${ext}`
|
||||||
|
newPath = path.join(TMPPATH, newName)
|
||||||
|
console.log(`Renaming ${list[i]} -> ${newName}`)
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fs.move(oldPath, newPath)
|
||||||
|
newList.push(newName)
|
||||||
|
sliceCount++
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
return process.exit(10)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return newList
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Ramdomly sort frames for re-stitching.
|
||||||
|
*
|
||||||
|
* @param {array} list List of frames to group
|
||||||
|
* @param {array} pattern Array representing pattern
|
||||||
|
* @param {boolean} realtime Flag to group with "realtime" behavior
|
||||||
|
**/
|
||||||
|
async function randomSort (list, pattern, realtime) {
|
||||||
|
let sliceCount = 0
|
||||||
|
let ext = path.extname(list[0])
|
||||||
|
let oldPath
|
||||||
|
let newName
|
||||||
|
let newPath
|
||||||
|
let newList = []
|
||||||
|
let removeLen = 0
|
||||||
|
let remove = []
|
||||||
|
|
||||||
|
shuffle(list)
|
||||||
|
|
||||||
|
if (realtime) {
|
||||||
|
removeLen = Math.floor(list.length / pattern.length)
|
||||||
|
remove = list.slice(removeLen, list.length)
|
||||||
|
list = list.slice(0, removeLen)
|
||||||
|
|
||||||
|
console.log(`Skipping extra slices...`)
|
||||||
|
for (let i = 0; i < remove.length; i++) {
|
||||||
|
oldPath = path.join(TMPPATH, remove[i])
|
||||||
|
console.log(`Skipping ${list[i]}`)
|
||||||
|
try {
|
||||||
|
await fs.unlink(oldPath)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
oldPath = path.join(TMPPATH, list[i])
|
||||||
|
|
||||||
|
newName = `./render_${zeroPad(sliceCount)}${ext}`
|
||||||
|
newPath = path.join(TMPPATH, newName)
|
||||||
|
console.log(`Renaming ${list[i]} -> ${newName}`)
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fs.move(oldPath, newPath)
|
||||||
|
newList.push(newName)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sliceCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
return newList
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Render the frames into a video using ffmpeg.
|
||||||
|
*
|
||||||
|
* @param {string} output Path to export the video to
|
||||||
|
**/
|
||||||
|
async function render (allSlices, output) {
|
||||||
|
let exe = EXE
|
||||||
|
let cmd
|
||||||
|
|
||||||
|
allSlices = allSlices.map(file => {
|
||||||
|
return path.join(TMPPATH, file)
|
||||||
|
})
|
||||||
|
|
||||||
|
cmd = `${exe} ${allSlices.join(' ')} ${output}`
|
||||||
|
|
||||||
|
console.log(`Exporting audio ${output}`)
|
||||||
|
console.log(cmd)
|
||||||
|
|
||||||
|
/*try {
|
||||||
|
await exec(`ls "${TMPPATH}"`)
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
try {
|
||||||
|
await exec(cmd)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the arguments and runs the process of exporting, sorting and then
|
||||||
|
* "weaving" the slices back into an audio file
|
||||||
|
*
|
||||||
|
* @param {object} arg Object containing all arguments
|
||||||
|
**/
|
||||||
|
async function main (arg) {
|
||||||
|
let input = arg.input.split(':')
|
||||||
|
let output = arg.output
|
||||||
|
let pattern = []
|
||||||
|
let realtime = false
|
||||||
|
let random = false
|
||||||
|
let allSlices
|
||||||
|
let len
|
||||||
|
console.time('audioloom')
|
||||||
|
|
||||||
|
if (input.length < 2) {
|
||||||
|
console.error('Must provide more than 1 input')
|
||||||
|
return process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!output) {
|
||||||
|
console.error('Must provide audio output path')
|
||||||
|
return process.exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg.random) {
|
||||||
|
random = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg.tmp) {
|
||||||
|
TMPDIR = arg.tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg.fps) {
|
||||||
|
SLICE = (1000 / parseFloat(arg.fps)) + ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// ms overrides fps
|
||||||
|
if (arg.ms) {
|
||||||
|
SLICE = (1000 / parseFloat(arg.ms)) + ''
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg.pattern) {
|
||||||
|
pattern = arg.pattern.split(':')
|
||||||
|
pattern = pattern.map(el =>{
|
||||||
|
return parseInt(el);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i <input.length; i++) {
|
||||||
|
pattern.push(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg.realtime) realtime = true
|
||||||
|
|
||||||
|
TMPPATH = path.join(TMPDIR, 'audioloom')
|
||||||
|
|
||||||
|
try {
|
||||||
|
await clear()
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
return process.exit(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Processing audio files ${input.join(', ')} into ${output} with pattern ${pattern.join(':')}`)
|
||||||
|
|
||||||
|
for (let i = 0; i <input.length; i++) {
|
||||||
|
try {
|
||||||
|
len = await audioLength(input[i])
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
return process.exit(4)
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await slices(input[i], len, i)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
return process.exit(4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
allSlices = await weave(pattern, realtime, random)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
return process.exit(5)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await render(allSlices, output)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
return process.exit(6)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await clear()
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
return process.exit(7)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.timeEnd('audioloom')
|
||||||
|
}
|
||||||
|
|
||||||
|
program
|
||||||
|
.version(packageJson.version)
|
||||||
|
.option('-i, --input [files]', 'Specify input audio files with paths seperated by colon')
|
||||||
|
.option('-o, --output [file]', 'Specify output path of audio file')
|
||||||
|
.option('-p, --pattern [pattern]', 'Specify a pattern for the flicker 1:1 is standard')
|
||||||
|
.option('-r, --realtime', 'Specify if audio files should preserve realtime speed')
|
||||||
|
.option('-t, --tmp [dir]', 'Specify tmp directory for exporting slices')
|
||||||
|
|
||||||
|
.option('-f, --fps [fps]', 'Specify length of slices using an FPS value')
|
||||||
|
.option('-m, --ms [ms]', 'Specify length of slices using length in milliseconds')
|
||||||
|
|
||||||
|
.option('-R, --random', 'Randomize frames. Ignores pattern if included')
|
||||||
|
.parse(process.argv)
|
||||||
|
|
||||||
|
main(program)
|
|
@ -0,0 +1,51 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const { exec } = require('pkg')
|
||||||
|
const execRaw = require('child_process').exec
|
||||||
|
const os = require('os')
|
||||||
|
const fs = require('fs-extra')
|
||||||
|
const packageJson = require('./package.json')
|
||||||
|
|
||||||
|
const platform = os.platform()
|
||||||
|
const arch = os.arch()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shells out to execute a command with async/await.
|
||||||
|
* Async wrapper to exec module.
|
||||||
|
*
|
||||||
|
* @param {string} cmd Command to execute
|
||||||
|
*
|
||||||
|
* @returns {Promise} Promise containing the complete stdio
|
||||||
|
**/
|
||||||
|
async function shell_out (cmd) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
return execRaw(cmd, (err, stdio, stderr) => {
|
||||||
|
if (err) return reject(err)
|
||||||
|
return resolve(stdio)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//exec(args) takes an array of command line arguments and returns a promise. For example:
|
||||||
|
|
||||||
|
if (!fs.existsSync(`./dist/${platform}_${arch}`)) {
|
||||||
|
fs.mkdirSync(`./dist/${platform}_${arch}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Building audioloom and saving in dist/${platform}_${arch}...`)
|
||||||
|
console.time('audioloom')
|
||||||
|
exec([ 'audioloom', '--target', 'host', '--output', `./dist/${platform}_${arch}/audioloom` ]).then(async (res) => {
|
||||||
|
try {
|
||||||
|
await shell_out(`zip -r ./dist/audioloom_${platform}_${arch}_${packageJson.version}.zip ./dist/${platform}_${arch}/audioloom`)
|
||||||
|
console.log(`Compressed binary to dist/audioloom_${platform}_${arch}_${packageJson.version}.zip`)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
process.exit(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.timeEnd('audioloom')
|
||||||
|
console.log('built')
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
|
// do something with app.exe, run, test, upload, deploy, etc
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"name": "audioloom",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Node script for interweaving audio files together",
|
||||||
|
"main": "audioloom",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/sixteenmillimeter/audioloom.git"
|
||||||
|
},
|
||||||
|
"author": "sixteenmillimeter",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/sixteenmillimeter/audioloom/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/sixteenmillimeter/audioloom#readme",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^2.19.0",
|
||||||
|
"fs-extra": "^7.0.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"jsdoc-to-markdown": "^4.0.1",
|
||||||
|
"pkg": "^4.3.5",
|
||||||
|
"qunit": "^2.8.0"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue