Created
July 18, 2012 13:11
-
-
Save dennishall/3136133 to your computer and use it in GitHub Desktop.
temp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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