I've been working on a solution, that would stream a series of jpg's to the client, and show them as they were a video. This is to avoid autoplay issues on iPads within a panoramic presentation. We don't need audio, so I tried looking into MJPEG, but since the browser never caches a stream, it's not a viable solution, although it performs really well on the client.
Have any of you come across something similar, and have you solved it? At this point I'm getting slightly obsessed with getting it to work!
The node.js MJPEG streaming server looks like this so far:
var express = require('express'),
fs = require('fs'),
http = require('http');
var app = express();
var server = http.createServer(app);
// Routes
app.use(express.static('app'));
app.get(/\.(mjpeg)$/i, function(request, res) {
var path = res.req._parsedOriginalUrl.path,
string = path.replace(/.*\\|\..*$/g, ''),
name = string.replace('/', '');
var files = fs.readdirSync('app/assets/streams/' + name + '/');
res.writeHead(200, {
'Content-Type': 'multipart/x-mixed-replace; boundary=myboundary',
'Cache-Control': 'no-cache',
'Connection': 'close',
'Pragma': 'no-cache'
});
var i = 1, id;
var stop = false;
res.connection.on('close', function() { stop = true; });
var send_next = function () {
if (stop)
return;
i = (i + 1);
// Increment with zero based number padding. (SO: ignore this, implementation specific)
if (i < 100 && i >= 10)
id = '0' + i;
else if (i < 10)
id = '00' + i;
else
id = i;
var filename = id + '.jpg';
//console.log(i, id, 'file length:', files.length, 'Path: app/assets/streams/' + name + '/' + filename);
fs.readFile('app/assets/streams/' + name + '/' + filename, function (err, content) {
res.write("--myboundary\r\n");
res.write("Content-Type: image/jpeg\r\n");
res.write("Content-Length: " + content.length + "\r\n");
res.write("\r\n");
res.write(content, 'binary');
res.write("\r\n");
// Start next in stream
setTimeout(send_next, 42);
});
// If we're at the end, reset current stream.
if (i === files.length) i = 1;
};
send_next();
});
// Setup
var port = process.env.PORT || 5000;
server.listen(port, function() {
console.log('Listening on ' + port);
});
I'm aware there are several optimisations that can done in that code, but it's just for demonstration purposes.
Edit: I'm looking for a solution that can serve 400 frames (~20kb, potentially as base64 encoded strings), that I could then cache on the client, and stream in a continuous loop. Curious if anyone else has solved a similar problem, and how.