forked from mmckegg/loop-drop-app
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcompress-project.js
157 lines (145 loc) · 4.13 KB
/
compress-project.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
var execFile = require('child_process').execFile
var each = require('async-each')
var fs = require('fs')
var extend = require('xtend/immutable')
var mkdirp = require('mkdirp')
var join = require('path').join
var dirname = require('path').dirname
var basename = require('path').basename
var extname = require('path').extname
// compress and trim all audio files
// requires ffmpeg to be in path and built with libvorbis support
compressProject(
'/Users/matt/Projects/Destroy With Science/New Drop',
'/Users/matt/Projects/Destroy With Science/Compressed Drop',
function(err) {
if (err) throw err
process.exit()
}
)
function compressProject(path, output, cb) {
fs.exists(output, function(exists) {
if (exists) {
return cb&&cb(new Error("Output path already exists"))
}
mkdirp(output, function(err) {
if (err) return cb&&cb(err)
fs.readdir(path, function(err, result) {
if (err) return cb&&cb(err)
forEach(result, function(name, next) {
var setupPath = join(path, name, 'index.json')
var setupOutput = join(output, name, 'index.json')
fs.exists(setupPath, function(exists) {
if (exists) {
fs.mkdir(join(output, name), function(err) {
compressFile(setupPath, setupOutput, next)
})
} else {
next()
}
})
}, cb)
})
})
})
}
function compressFile(path, output, cb) {
console.log(output)
var dir = dirname(path)
var outputDir = dirname(output)
fs.readFile(path, 'utf8', function(err, result) {
if (err) return cb&&cb(err)
var setup = JSON.parse(result)
var chunks = []
var audioBuffers = []
var finalSetup = JSON.stringify(setup, function(key, value) {
if (value && value.node === 'external' && value.src && value.id) {
chunks.push([
join(dir, value.src),
join(outputDir, value.id + '.json')
])
return extend(value, {
src: './' + value.id + '.json'
})
} else if (value && value.buffer && value.buffer.node === 'AudioBuffer' && value.buffer.src) {
var start = value.offset && value.offset[0] || 0
var end = value.offset && value.offset[1] || 1
var ext = extname(value.buffer.src)
var base = basename(value.buffer.src, ext)
var newFileName = base + '_' + ms(start) + '-' + ms(end) + '.ogg'
audioBuffers.push([
join(dir, value.buffer.src),
join(outputDir, newFileName),
start, end
])
return extend(value, {
offset: [0,1],
buffer: extend(value.buffer, {
src: './' + newFileName
})
})
} else {
return value
}
})
fs.writeFile(output, finalSetup, function(err) {
if (err) return cb&&cb(err)
forEach(chunks, function(x, next) {
compressFile(x[0], x[1], next)
}, function(err) {
if (err) return cb&&cb(err)
forEach(audioBuffers, function(x, next) {
compressAudio(x[0], x[1], x[2], x[3], next)
}, cb)
})
})
})
}
function compressAudio(path, output, start, end, cb) {
console.log(output)
fs.exists(output, function(exists) {
if (!exists) {
getAudioDuration(path, function(err, duration) {
var from = (start||0) * duration
var to = (end||1) * duration
execFile('ffmpeg', [
"-i", path,
"-codec:a", "libvorbis",
"-qscale:a", "5",
"-ss", from,
"-to", to,
output
], cb)
})
} else {
cb()
}
})
}
function ms(s) {
return Math.round(s * 1000)
}
function getAudioDuration(path, cb) {
execFile("ffprobe", [
path,
'-show_entries', 'format=duration',
'-v', 'quiet'
], function(err, res) {
if (err) return cb&&cb(err)
var match = /duration=([0-9\.]+)\n/.exec(res)
cb&&cb(null, parseFloat(match[1]))
})
}
function forEach(array, fn, cb){
var i = -1
function next(err){
if (err) return cb&&cb(err)
i += 1
if (i<array.length){
fn(array[i], next, i)
} else {
cb&&cb(null)
}
}
next()
}