From fa6f7d8d4f5491bb7951ec639a18e500fc2feb68 Mon Sep 17 00:00:00 2001 From: Snow Date: Tue, 2 Aug 2016 14:26:07 +1000 Subject: [PATCH 1/2] Support sending frames to websocket server. --- .gitignore | 2 ++ package.json | 5 +++- src/CCapture.js | 51 ++++++++++++++++++++++++++++++++++++++++ utils/websocketserver.js | 33 ++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 utils/websocketserver.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a56a7ef --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules + diff --git a/package.json b/package.json index 10edd46..979033f 100644 --- a/package.json +++ b/package.json @@ -21,5 +21,8 @@ "bugs": { "url": "https://github.com/spite/ccapture.js/issues" }, - "homepage": "https://github.com/spite/ccapture.js#readme" + "homepage": "https://github.com/spite/ccapture.js#readme", + "dependencies": { + "ws": "^1.1.1" + } } diff --git a/src/CCapture.js b/src/CCapture.js index 7fb3934..ee31659 100755 --- a/src/CCapture.js +++ b/src/CCapture.js @@ -372,6 +372,56 @@ CCFFMpegServerEncoder.prototype.safeToProceed = function() { return this.encoder.safeToProceed(); }; + +// http://www.smartjava.org/content/capture-canvas-and-webgl-output-video-using-websockets +// http://fhtr.blogspot.com.au/2014/02/saving-out-video-frames-from-webgl-app.html +function CCWebsocketServerEncoder( settings ) { + + CCFrameEncoder.call( this, settings ); + + this.framerate = this.settings.framerate; + this.type = 'image/png'; + this.extension = '.png'; + this.stream = null; + this.mediaRecorder = null; + this.chunks = []; + this.counter = 0; + + settings.quality = ( settings.quality / 100 ) || .8; + + this.encoder = new WebSocket("ws://localhost:8889/"); + +} + +CCWebsocketServerEncoder.prototype = Object.create( CCFrameEncoder.prototype ); + +CCWebsocketServerEncoder.prototype.add = function( canvas ) { + + if( !this.stream ) { + this.stream = canvas.captureStream( this.framerate ); + this.mediaRecorder = new MediaRecorder( this.stream ); + this.mediaRecorder.start(); + this.mediaRecorder.ondataavailable = function(e) { + this.counter++ + var data = canvas.toDataURL('image/png', this.quality); + this.encoder.send(data); + }.bind( this ); + } + + this.step(); + +} + +CCWebsocketServerEncoder.prototype.save = function( callback ) { + // End the stream + this.mediaRecorder.stop(); + // Close the socket + this.encoder.close() + + this.stop(); +} + + /* HTMLCanvasElement.captureStream() */ @@ -603,6 +653,7 @@ function CCapture( settings ) { gif: CCGIFEncoder, webm: CCWebMEncoder, ffmpegserver: CCFFMpegServerEncoder, + websocketserver: CCWebsocketServerEncoder, png: CCPNGEncoder, jpg: CCJPEGEncoder, 'webm-mediarecorder': CCStreamEncoder diff --git a/utils/websocketserver.js b/utils/websocketserver.js new file mode 100644 index 0000000..c43931c --- /dev/null +++ b/utils/websocketserver.js @@ -0,0 +1,33 @@ +// http://fhtr.blogspot.com.au/2014/02/saving-out-video-frames-from-webgl-app.html +// Adapted from this _WikiBooks OpenGL Programming Video Capture article_. +var port = 8889; +var ws = require('ws'); +var fs = require('fs'); +var frame = 0; +var path = "../../../output"; + +var WebSocketServer = require('ws').Server, wss = new WebSocketServer({ port: port }); + +wss.on('connection', function connection(ws) { + frame = 0; + + var d = new Date(); + var directory = path + "/" + d.toISOString(); + fs.mkdir(path, '755', function() {}); + fs.mkdir(directory, '755', function() {}); + + ws.on('message', function incoming(data) { + // Allows for up to 1 hour of encoded data at 25fps. + var filename = ("00000" + frame).slice(-5)+".png"; + var base64Data = data.replace(/^data:image\/png;base64,/, ""); + + fs.writeFile(directory + "/" + filename, base64Data, 'base64', function(err) { + if ( err ) console.log(err); + }); + + console.log('Wrote ' + filename); + frame++; + }); +}); + +console.log('Server running at ws://127.0.0.1:'+port+'/'); From fdd67c697f2c80585cac97fc36461aa9ad2b1903 Mon Sep 17 00:00:00 2001 From: Z Snow Date: Fri, 5 Aug 2016 07:07:04 +1000 Subject: [PATCH 2/2] Rework capture with filereader instead of mediarecorder. --- src/CCapture.js | 23 ++++++++++++----------- utils/websocketserver.js | 9 +++++++-- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/CCapture.js b/src/CCapture.js index ee31659..508dfdb 100755 --- a/src/CCapture.js +++ b/src/CCapture.js @@ -382,10 +382,11 @@ function CCWebsocketServerEncoder( settings ) { this.framerate = this.settings.framerate; this.type = 'image/png'; this.extension = '.png'; + this.fileExtension = this.extension; this.stream = null; this.mediaRecorder = null; this.chunks = []; - this.counter = 0; + this.count = 0; settings.quality = ( settings.quality / 100 ) || .8; @@ -397,18 +398,18 @@ CCWebsocketServerEncoder.prototype = Object.create( CCFrameEncoder.prototype ); CCWebsocketServerEncoder.prototype.add = function( canvas ) { - if( !this.stream ) { - this.stream = canvas.captureStream( this.framerate ); - this.mediaRecorder = new MediaRecorder( this.stream ); - this.mediaRecorder.start(); - this.mediaRecorder.ondataavailable = function(e) { - this.counter++ - var data = canvas.toDataURL('image/png', this.quality); - this.encoder.send(data); + canvas.toBlob( function( blob ) { + var fileReader = new FileReader(); + fileReader.onload = function() { + frame = new Uint8Array( fileReader.result ); + filename = pad( this.count ) + this.fileExtension; + this.encoder.send(frame); + this.count++; + this.step(); }.bind( this ); - } + fileReader.readAsArrayBuffer(blob); - this.step(); + }.bind( this ), this.type ) } diff --git a/utils/websocketserver.js b/utils/websocketserver.js index c43931c..5db658e 100644 --- a/utils/websocketserver.js +++ b/utils/websocketserver.js @@ -13,13 +13,18 @@ wss.on('connection', function connection(ws) { var d = new Date(); var directory = path + "/" + d.toISOString(); + fs.mkdir(path, '755', function() {}); fs.mkdir(directory, '755', function() {}); - ws.on('message', function incoming(data) { + ws.on('message', function incoming(data, filename, x) { + console.log("filename") + console.log(filename) + + base64Data = data.toString('base64'); + // Allows for up to 1 hour of encoded data at 25fps. var filename = ("00000" + frame).slice(-5)+".png"; - var base64Data = data.replace(/^data:image\/png;base64,/, ""); fs.writeFile(directory + "/" + filename, base64Data, 'base64', function(err) { if ( err ) console.log(err);