Skip to content

Instantly share code, notes, and snippets.

@dennishall
Created July 18, 2012 13:11
Show Gist options
  • Save dennishall/3136133 to your computer and use it in GitHub Desktop.
Save dennishall/3136133 to your computer and use it in GitHub Desktop.
temp
// stream media
// urls to consider:
// http://html5doctor.com/video-canvas-magic/
// http://stackoverflow.com/questions/1106955/php-and-ffmpeg-performing-intelligent-video-conversion
// http://stackoverflow.com/questions/6954845/how-to-create-a-webm-video-file
// http://johndyer.name/ffmpeg-settings-for-html5-codecs-h264mp4-theoraogg-vp8webm/
// http://blog.pcode.nl/2010/10/17/encoding-webm-using-ffmpeg/
var fs = require('fs');
var util = require('util');
var express = require('express');
var port = 9001;
var app = express.createServer();
app.requireAuth = false;
//generic config
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'topsecret' }));
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.get('/media/*', function(req, res){
var file = 'media/' + req.params[0];
// TODO - get file info :: bitrate
var bitrate = 1048576; // 1M - rough guess at the bitrate of a 320x240 webm video
// TODO - implement application logic to determine secnodsToBuffer
var secondsToBuffer = 4;
// console.log(util.inspect(req, showHidden=false, depth=2));
// console.log(util.inspect(req.headers, showHidden=false, depth=0));
var stat = fs.statSync(file);
if (!stat.isFile()) return;
var size = stat.size;
var minChunkSize = secondsToBuffer * bitrate; // 512k (half a meg).
var numChunks = 10;
// can't get more than a 10th of the file at a time.
var chunkSize = parseInt(size/numChunks, 10);
if(chunkSize < minChunkSize){
chunkSize = minChunkSize;
}
var start = 0;
var end = 0;
var range = req.header('Range');
if (range != null) {
start = parseInt(range.slice(range.indexOf('bytes=')+6, range.indexOf('-')), 10);
end = parseInt(range.slice(range.indexOf('-')+1, range.length), 10);
}
if (isNaN(end) || end == 0){
end = size - 1;
}
if(end - start > chunkSize){
end = start + chunkSize;
}
if(end >= size){
end = size - 1;
}
if (start > end) return;
console.log('Browser requested bytes '+start+' to '+end+' of '+file);
var date = new Date();
res.writeHead(206, { // 206 is a partial http response
// 'Date':date.toUTCString(),
'Connection':'close',
// 'Cache-Control':'private',
// 'Content-Type':'video/webm',
// 'Content-Length':end - start,
'Content-Range':'bytes '+start+'-'+end+'/'+stat.size,
// 'Accept-Ranges':'bytes',
// 'Server':'CustomStreamer/0.0.1',
'Transfer-Encoding':'chunked'
});
var stream = fs.createReadStream(file, { flags:'r', start:start, end:end });
stream.pipe(res);
});
app.get(/^\/$/, function(req, res){
//res.send('<!doctype html><html><head><title>node stream video</title></head><body style="background:#000;"><video controls autoplay style="display:block;margin:30px auto;box-shadow:0 0 20px #444;border-radius:10px;"><source src="/media/video.webm" type="video/webm"></video></body></html>');
//render the index page
res.render('index.jade', {
locals: {
title: 'node stream video',
examples: []
}
});
});
app.listen(port);
process.on('uncaughtException', function(err) {
console.log(err);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment