-
Notifications
You must be signed in to change notification settings - Fork 5
/
index.js
171 lines (159 loc) · 4.86 KB
/
index.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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
const HLSServer = require('hls-server')
const http = require('http')
const fs = require('fs')
const url = require('url')
const path = require('path')
const Busboy = require('busboy')
const is = require('type-is')
const os = require('os')
const ffmpeg = require('fluent-ffmpeg')
const Readable = require('stream').Readable
const m3u8 = require('m3u8')
const audioPath = __dirname + "/audio/";
const viewPath = __dirname + "/view/";
const maxWindowSize = 5;
let PORT = process.env.PORT || 8000;
let SERVER_ADDR = "127.0.0.1"
var chunklistStream;
var number = 0; //temp file numbering
var sequence_number = 0;
var process_number = 0;
var m3u8_header;
var m3u8_contents = [];
var zero_extension = function(n, l) {
var s = String(n);
if (s.length < l) {
var cnt = l - s.length;
for (var i = 0; i < cnt; i++) {
s = '0' + s;
}
}
return s;
}
var server = http.createServer(function(req, res) {
var uri = url.parse(req.url).pathname;
var ext = uri.split('.').pop();
//hls 미들웨어를 통과한 요청을 처리함. 웹 서버 역할을 함.
if (uri == '/') {
console.log(uri);
res.writeHead(302, {
'Location': '/play_demo'
});
res.end();
return;
} else if (uri == '/play_demo') {
console.log(uri);
res.writeHead(200, {
'Content-Type': 'text/html'
});
var stream = fs.createReadStream(viewPath + "play_demo.html");
stream.pipe(res);
return;
} else if (uri == '/capture_audio') {
console.log(uri);
res.writeHead(200, {
'Content-Type': 'text/html'
})
var stream = fs.createReadStream(viewPath + "capture_audio.html");
stream.pipe(res);
return;
} else if (uri == '/upload') {
console.log(uri);
if (!is(req, ['multipart'])) {
res.writeHead(404, {
'Content-Type': 'text/html'
})
return res.end();
}
var busboy
var tmpAudioFilePath
try {
busboy = new Busboy({
headers: req.headers
});
} catch (err) {
console.error('header parsing error', err);
res.writeHead(500);
return res.end();
}
// busboy.on('field', function(fieldName, value, fieldnameTruncated, valueTruncaed) {
// })
busboy.on('file', function(fieldName, fileStream, fileName, encoding, mimeType) {
// var randString = Math.random().toString().substr(14);
var randString = zero_extension(number, 4);
number++;
tmpAudioFilePath = path.join(os.tmpdir(), path.basename(fieldName + '_' + randString + '.wav'));
console.log('saveTo:', tmpAudioFilePath);
// console.log('encoding:', encoding);
// console.log('mimeType:', mimeType);
fileStream.pipe(fs.createWriteStream(tmpAudioFilePath));
})
busboy.on('finish', function() {
console.log('ffmpeg encoding')
var flag_args = ['omit_endlist', 'delete_segments', 'append_list'];
ffmpeg(tmpAudioFilePath, { timeout: 432000 }).addOptions([
'-profile:v baseline', // baseline profile (level 3.0) for H264 video codec
'-level 3.0',
'-start_number ' + process_number,
'-hls_flags ' + flag_args.join('+'),
'-hls_time 2', // 10 second segment duration
'-hls_list_size 10', // Maxmimum number of playlist entries (0 means all entries/infinite)
'-f hls' // HLS format
]).output(audioPath + 'chunklist.m3u8')
.on('end', function() {
res.writeHead(201, {
'Content-Type': 'text/html'
});
res.end();
})
.on('error', function(err) {
console.error('Error while ffmpeg processing:', err)
res.writeHead(500);
res.end();
})
.run()
})
req.pipe(busboy);
}
})
var hls = new HLSServer(server, { // hls를 위한 미들웨어가 삽입됨. hls 서버 역할을 함
provider: {
exists: function(req, cb) { // 모든 요청에 대해 호출됨
var uri = url.parse(req.url).pathname
var extension = path.extname(uri)
if (extension != '.m3u8' && extension != '.ts') {
return cb(null, true);
}
console.log('exists function called');
var uri = url.parse(req.url).pathname;
var fpath = audioPath + uri;
fs.access(fpath, fs.constants.F_OK, function(err) {
if (err) {
console.log('File not exist', fpath);
}
cb(null, !err);
});
},
getManifestStream: function(req, cb) { // 확장자가 .m3u8 로 끝나는 경우 호출됨
var uri = url.parse(req.url).pathname;
console.log('getManifestStream function called:', req.url, uri);
var ext = uri.split('.').pop();
var filePath = audioPath + uri;
var tsFileStream = fs.createReadStream(filePath);
cb(null, tsFileStream);
},
getSegmentStream: function(req, cb) { // 확장자가 .ts 로 끝나는 경우 호출됨
var uri = url.parse(req.url).pathname;
console.log('getSegmentStream function called:', req.url, uri);
var ext = uri.split('.').pop();
if (ext == 'ts') {
var filePath = audioPath + uri;
var tsFileStream = fs.createReadStream(filePath);
cb(null, tsFileStream);
}
}
}
})
server.listen(PORT, function() {
console.log('Launching server listening on ... ', SERVER_ADDR + ':' + PORT);
})