Skip to content

Commit 909e20e

Browse files
committed
Add VideoStreamerChunked.js example
1 parent 0b33a99 commit 909e20e

1 file changed

Lines changed: 80 additions & 0 deletions

File tree

examples/VideoStreamerChunked.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/* This is an example of sync copying of large files.
2+
* NEVER DO THIS; ONLY FOR TESTING PURPOSES. WILL CAUSE
3+
* SEVERE BACKPRESSURE AND HORRIBLE PERFORMANCE.
4+
* Try navigating to the adderss with Chrome and see the video
5+
* in real time. */
6+
7+
const uWS = require('uWebSockets.js');
8+
const fs = require('fs');
9+
10+
const port = 9001;
11+
const fileName = 'spritefright.mp4';
12+
const videoFile = toArrayBuffer(fs.readFileSync(fileName));
13+
const totalSize = videoFile.byteLength;
14+
15+
console.log('WARNING: NEVER DO LIKE THIS; WILL CAUSE HORRIBLE BACKPRESSURE!');
16+
console.log('Video size is: ' + totalSize + ' bytes');
17+
18+
const CHUNK_SIZE = 1024 * 64;
19+
20+
/* Helper function converting Node.js buffer to ArrayBuffer */
21+
function toArrayBuffer(buffer) {
22+
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
23+
}
24+
25+
/* Yes, you can easily swap to SSL streaming by uncommenting here */
26+
const app = uWS.App({
27+
key_file_name: 'misc/key.pem',
28+
cert_file_name: 'misc/cert.pem',
29+
passphrase: '1234'
30+
31+
}).get('/spritefright.mp4', (res, req) => {
32+
let aborted = false;
33+
let written = 0;
34+
35+
res.onAborted(() => {
36+
aborted = true;
37+
});
38+
39+
const stream = () => {
40+
let ok = true;
41+
42+
// Use res.cork to pack multiple small writes into one syscall
43+
res.cork(() => {
44+
while (ok && written < videoFile.byteLength) {
45+
let chunk = videoFile.slice(written, Math.min(written + CHUNK_SIZE, videoFile.byteLength));
46+
47+
// If this is the last chunk, use end() instead of write()
48+
if (written + chunk.byteLength === videoFile.byteLength) {
49+
res.end(chunk);
50+
written += chunk.byteLength;
51+
ok = false; // Stop the loop
52+
} else {
53+
ok = res.write(chunk);
54+
written += chunk.byteLength;
55+
}
56+
}
57+
});
58+
59+
return ok;
60+
};
61+
62+
// Initial attempt to stream
63+
let ok = stream();
64+
65+
// If we hit backpressure, set up the drain handler
66+
if (!ok && !aborted && written < videoFile.byteLength) {
67+
res.onWritable((offset) => {
68+
return stream();
69+
});
70+
}
71+
}).get('/*', (res, req) => {
72+
/* Make sure to always handle every route */
73+
res.end('Nothing to see here!');
74+
}).listen(port, (token) => {
75+
if (token) {
76+
console.log('Listening to port ' + port);
77+
} else {
78+
console.log('Failed to listen to port ' + port);
79+
}
80+
});

0 commit comments

Comments
 (0)