-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrecorder.js
113 lines (94 loc) · 4.02 KB
/
recorder.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
const lame = require('lame'),
fs = require('fs'),
Transform = require('stream').Transform,
clock = require('event-clock'),
cleanup = require('./folder-cleanup'),
config = require('./config.json');
//-- Encoder setup
const encoder = new lame.Encoder({
// input
channels: config.common.format.channels,
bitDepth: config.input.format.bitDepth,
sampleRate: config.common.format.sampleRate,
// output
bitRate: config.recorder.format.bitrate,
outSampleRate: config.common.format.sampleRate,
mode: config.common.format.channels == 2 ? lame.STEREO : lame.MONO
});
//-- To connect lossless recording
// TODO: save to .wav instead of .raw
const audioJack = new Transform({
transform: (data, _, done) => done(null, data)
});
//-- Output streams named "reels" to differentiate from streamer
let outputReel = [],
activeReel = 0,
switchReel = () => activeReel = activeReel ? 0 : 1;
const leadZero = num => (num < 10 ? '0' : '') + num;
const startRecording = function(filename) {
if (!filename) {
const date = new Date();
filename = `${date.getFullYear()}-${leadZero(date.getMonth() + 1)}-${leadZero(date.getDate())}_${leadZero(date.getHours())}-${leadZero(date.getMinutes())}`;
}
outputReel[activeReel] = fs.WriteStream(`${config.recorder.output.directory}/${filename}.${config.recorder.format.lossless ? 'raw' : 'mp3'}`);
(config.recorder.format.lossless ? audioJack : encoder).pipe(outputReel[activeReel]);
console.info(`[ REC ] Start: recording "${filename}" on reel ${activeReel + 1}`);
}
const stopRecording = function() {
if (outputReel[activeReel]) {
outputReel[activeReel].end();
outputReel[activeReel] = null;
console.info(`[ REC ] Stop: finished recording on reel ${activeReel + 1}`);
}
}
const cleanFolder = () => cleanup(config.recorder.output.directory, config.recorder.output.keepFor);
const schedule = function(minsPast, bleed) {
const minsToMs = mins => mins * 60000;
for (let hour = 0; hour < 24; hour++) {
for (const mins of minsPast) {
const triggerTime = `${leadZero(hour)}:${leadZero(mins)}`;
let startTime = triggerTime,
endTime = triggerTime;
if (bleed) {
const triggerDate = new Date();
triggerDate.setHours(hour);
triggerDate.setMinutes(mins);
triggerDate.setSeconds(0);
let startDate = new Date(triggerDate.getTime() - minsToMs(bleed)),
endDate = new Date(triggerDate.getTime() + minsToMs(bleed));
startTime = `${leadZero(startDate.getHours())}:${leadZero(startDate.getMinutes())}`;
endTime = `${leadZero(endDate.getHours())}:${leadZero(endDate.getMinutes())}`;
}
// TODO: add bleed
clock.on(startTime, () => {
const date = new Date();
startRecording(
/* label the recording with the time it is set to trigger, instead of
* the time it starts recording; this accounts for bleed time */
`${date.getFullYear()}-${leadZero(date.getMonth() + 1)}-${leadZero(date.getDate())}_${leadZero(hour)}-${leadZero(mins)}`
);
switchReel();
});
clock.on(endTime, () => {
stopRecording();
cleanFolder();
});
}
}
};
const run = function() {
// check output folder exists
if (!fs.existsSync(config.recorder.output.directory)) {
try {
fs.mkdirSync(config.recorder.output.directory);
} catch(err) {
console.error(`[ REC ] Error: ${err}`);
}
}
schedule(config.recorder.minsPast, config.recorder.bleed);
console.info('[ REC ] Initialised');
startRecording(outputReel[activeReel]);
switchReel();
};
exports.input = config.recorder.format.lossless ? audioJack : encoder;
exports.run = run;