Wrap res.getWriteOffset, add VideoStreamer example
This commit is contained in:
parent
d132ae2685
commit
79eab43abc
79
examples/VideoStreamer.js
Normal file
79
examples/VideoStreamer.js
Normal file
@ -0,0 +1,79 @@
|
||||
/* This is an example of async streaming of large files.
|
||||
* Try navigating to the adderss with Chrome and see the video
|
||||
* in real time. */
|
||||
|
||||
const uWS = require('../dist/uws.js');
|
||||
const fs = require('fs');
|
||||
const crypto = require('crypto');
|
||||
|
||||
const port = 9001;
|
||||
const fileName = '/home/alexhultman/Downloads/Sintel.2010.720p.mkv';
|
||||
const totalSize = fs.statSync(fileName).size;
|
||||
|
||||
console.log('Video size is: ' + totalSize + ' bytes');
|
||||
|
||||
/* Helper function converting Node.js buffer to ArrayBuffer */
|
||||
function toArrayBuffer(buffer) {
|
||||
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
||||
}
|
||||
|
||||
/* Returns true on success, false if it's having backpressure */
|
||||
function tryStream(res, chunk, requestDataCb) {
|
||||
/* Stream as far as we can */
|
||||
let lastOffset = res.getWriteOffset();
|
||||
if (!res.tryEnd(chunk, totalSize)) {
|
||||
/* Save unsent chunk for when we can send it */
|
||||
res.chunk = chunk;
|
||||
res.chunkOffset = lastOffset;
|
||||
|
||||
res.onWritable((offset) => {
|
||||
if (res.tryEnd(res.chunk.slice(offset - res.chunkOffset), totalSize)) {
|
||||
requestDataCb();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
/* Return failure */
|
||||
return false;
|
||||
}
|
||||
/* Return success */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Yes, you can easily swap to SSL streaming by uncommenting here */
|
||||
const app = uWS./*SSL*/App({
|
||||
key_file_name: '/home/alexhultman/key.pem',
|
||||
cert_file_name: '/home/alexhultman/cert.pem',
|
||||
passphrase: '1234'
|
||||
}).get('/sintel.mkv', (res, req) => {
|
||||
/* Log */
|
||||
console.log("Streaming Sintel video...");
|
||||
|
||||
/* Create read stream with Node.js and start streaming over Http */
|
||||
const readStream = fs.createReadStream(fileName);
|
||||
const hash = crypto.createHash('md5');
|
||||
readStream.on('data', (chunk) => {
|
||||
|
||||
const ab = toArrayBuffer(chunk);
|
||||
hash.update(chunk);
|
||||
|
||||
if (!tryStream(res, ab, () => {
|
||||
/* Called once we want more data */
|
||||
readStream.resume();
|
||||
})) {
|
||||
/* If we could not send this chunk, pause */
|
||||
readStream.pause();
|
||||
}
|
||||
}).on('end', () => {
|
||||
console.log("md5: " + hash.digest('hex'));
|
||||
});
|
||||
}).get('/*', (res, req) => {
|
||||
/* Make sure to always handle every route */
|
||||
res.end('Nothing to see here!');
|
||||
}).listen(port, (token) => {
|
||||
if (token) {
|
||||
console.log('Listening to port ' + port);
|
||||
} else {
|
||||
console.log('Failed to listen to port ' + port);
|
||||
}
|
||||
});
|
@ -14,6 +14,12 @@ struct HttpResponseWrapper {
|
||||
// res.onData(JS function)
|
||||
// res.onAborted
|
||||
|
||||
/* Returns the current write offset */
|
||||
template <bool SSL>
|
||||
static void res_getWriteOffset(const FunctionCallbackInfo<Value> &args) {
|
||||
args.GetReturnValue().Set(Integer::New(isolate, getHttpResponse<SSL>(args)->getWriteOffset()));
|
||||
}
|
||||
|
||||
/* Takes function of bool(int), returns this */
|
||||
template <bool SSL>
|
||||
static void res_onWritable(const FunctionCallbackInfo<Value> &args) {
|
||||
@ -100,6 +106,7 @@ struct HttpResponseWrapper {
|
||||
resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "write"), FunctionTemplate::New(isolate, res_write<SSL>));
|
||||
resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "writeHeader"), FunctionTemplate::New(isolate, res_writeHeader<SSL>));
|
||||
|
||||
resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "getWriteOffset"), FunctionTemplate::New(isolate, res_getWriteOffset<SSL>));
|
||||
resTemplateLocal->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "onWritable"), FunctionTemplate::New(isolate, res_onWritable<SSL>));
|
||||
|
||||
/* Create our template */
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 8efea340e66bc91efbe31b618a446f821c214bbf
|
||||
Subproject commit 0ca061e7727df4fcc0c840e67188e093f966e7d3
|
Loading…
Reference in New Issue
Block a user