-
Notifications
You must be signed in to change notification settings - Fork 2
/
main.js
152 lines (133 loc) · 3.63 KB
/
main.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
const config = require("./config.json");
const spawn = require('child_process').spawn;
const path = require('path');
const fs = require('fs');
var counter = 0;
// hold all running children
var processes = [];
process.on('exit', onExit);
process.on('SIGINT', onExit);
console.log("Starting...");
prepare(function() {
for (var i=0; i<config.streams.length; i++) {
startStream(config.streams[i]);
}
console.log("All streams started.");
});
function prepare(callback) {
fs.mkdir(path.resolve(__dirname, "progress"), function() {
clearFolder(path.resolve(__dirname, "progress"));
callback();
});
}
function startStream(streamConfig) {
const inputNum = streamConfig.input;
const formatMode = streamConfig.formatMode;
const videoBitrate = streamConfig.videoBitrate;
const audioBitrate = streamConfig.audioBitrate;
const audioSampleRate = streamConfig.audioSampleRate;
const frameRate = streamConfig.frameRate;
const url = streamConfig.url;
const progressFile = path.resolve(__dirname, "progress/"+(counter++)+"-"+inputNum+".progress");
var killed = false;
console.log("Starting stream. Input "+inputNum+" => \""+url+"\".");
const child = spawn('bash', [path.resolve(__dirname, "stream.sh")], {
detached: true,
env: {
INPUT_NUMBER: inputNum+"",
FORMAT_MODE: formatMode+"",
VIDEO_BITRATE: videoBitrate+"",
AUDIO_BITRATE: audioBitrate+"",
AUDIO_SAMPLE_RATE: audioSampleRate+"",
STREAM_URL: url,
FRAME_RATE: frameRate+"",
GOP_LENGTH: (frameRate*2)+"",
PROGRESS_FILE: progressFile
}
});
processes.push(child);
// this checks to make sure the progress file exists and contains content,
// if it does it means the stream is still running.
// It then clears the contents of the file.
// If the file is empty when we check then ffmpeg hasn't made any more progress
// so assume something's gone wrong.
const workingCheckTimerId = setInterval(function() {
if (killed) {
return;
}
if (fileExists(progressFile)) {
const data = fs.readFileSync(progressFile, 'utf8');
if (data.length === 0) {
onFailure();
}
else {
fs.truncateSync(progressFile);
}
}
else {
onFailure();
}
function onFailure() {
console.error("It looks like the stream has failed. Terminating.");
killed = true;
process.kill(-child.pid, "SIGKILL");
onClosed();
}
}, 6000);
child.stdout.on('data', function(data) {
console.log(data.toString());
});
child.stderr.on('data', function(data) {
console.error("ERROR: "+data.toString());
});
child.stderr.on('error', function(data) {
console.error("Failed to start: "+data.toString());
});
child.on('close', function(code) {
if (killed) {
// onClosed() will already have been called
return;
}
console.log("Stream terminated with code "+code+".");
onClosed();
});
function onClosed() {
processes.splice(processes.indexOf(child), 1);
console.log("Restarting stream in 5.");
clearInterval(workingCheckTimerId);
setTimeout(function() {
console.log("Restarting...");
startStream(streamConfig);
}, 5000);
}
}
function fileExists(file) {
try {
return fs.statSync(file).isFile();
}
catch(e) {
return false;
}
}
function clearFolder(path) {
if (fs.existsSync(path)) {
fs.readdirSync(path).forEach(function(file, index) {
var curPath = path + "/" + file;
if (fs.lstatSync(curPath).isDirectory()) { // recurse
clearFolder(curPath);
}
else { // delete file
fs.unlinkSync(curPath);
}
});
}
}
function onExit() {
console.log("Terminating...");
console.log("Killing child processes...");
processes.forEach(function(child) {
process.kill(-child.pid, "SIGKILL");
});
console.log("Done.");
process.exit();
}