NodeJS - Stream video that is being downloaded - node.js

I am writing a program that will stream a video file that is currently being downloaded onto the drive. The problem I am having seems to be getting the browser to actually play the video. the script listens for file changes, and then streams the rest, but the browser doesnt do anything besides display a blank Video page.
var fs = require('fs'),
http = require('http'),
filename = '/home/qrpike/Videos/topgears.mp4';
http.createServer(function (req, res) {
console.log(req.url);
if( req.url == '/video.mp4'){
res.writeHead(200,{
'Content-Type' : 'video/mp4',
'Cache-Control' : 'public',
'Connection' : 'keep-alive',
'Content-Disposition' : 'inline; filename=topgears.mp4;',
'Content-Transfer-Encoding' : 'binary',
'Transfer-Encoding' : 'chunked'
});
fs.open(filename, 'r', function(err, fd) {
if (err) throw new Error('Could not open file');
var position = 0;
fs.stat(filename, read);
fs.watchFile(filename, read.bind(null, null));
function read(err, stat) {
var delta = stat.size - position;
if (delta <= 0) return;
fs.read(fd, new Buffer(delta), 0, delta, position, function(err, bytes, buffer) {
console.log("err", err, "bytes", bytes, "position",position,"delta",delta);
res.write(buffer.toString('binary'));
});
position = stat.size;
}
});
}
}).listen(1337);
console.log('Server running at http://127.0.0.1:1337/');

So this answer depends on growing-file, which in theory does what you want. My concern is that the project hasn't had a commit in two years so I have no idea if it still works. That being said, this worked for me locally (though I didn't test piping to the video file):
var fs = require('fs');
var http = require('http');
var GrowingFile = require('growing-file');
var FILENAME = '/home/dave/Desktop/video/video.ogg';
var server = http.createServer(function(req, res) {
var file;
if (req.url === '/video.ogg') {
res.writeHead(200, {
'Content-Type': 'video/ogg'
});
file = GrowingFile.open(FILENAME);
file.pipe(res);
} else {
res.statusCode = 404;
res.end('Not Found');
}
});
server.listen(1337);

Related

How to change data that comes from a text file in node.js?

I am learning node.js and made a simple app, where I have a text file called 'input.txt' with some data and printing it out in localhost. I would like to add some function, for example remove all *, but I get an error with split function. Can you help where I am going wrong? Is there a way to change text file data somehow?
var http = require('http');
var fs = require('fs');
http.createServer(function(req, res) {
fs.readFile('input.txt', function(err, data) {
res.writeHead(200, {
'Content-Type': 'text/html'
});
var data = data.split('*')
res.write(data);
res.end();
});
}).listen(8080);
and here is the example of 'input.txt'
veronika*sandra*carol*bye*
Use split and join
let dataFile=data.split('*').join(' ');
res.write(dataFile);
First of all, you should check error and then it is safe to convert into a string like
var http = require('http');
var fs = require('fs');
http.createServer(function(req, res) {
fs.readFile('input.txt', function(err, data) {
res.writeHead(200, {
'Content-Type': 'text/html'
});
if(err) {
console.log('Error: ', err);
res.end();
} else {
data = data && data.toString().replace(/\*/g, '');
res.write(data);
res.end();
}
});
}).listen(8080);

Node JS Request + Express Pipe

I have a problem with streaming video files from a server to another.
I wrote this script
var request = require("request"),
express = require("express");
var app = express();
app.get("/cast", function(req, res) {
var url = req.query.video;
res.writeHead(200, {
'Content-Type': 'video/mp4'
});
request({
url: url,
headers: {
Referer: "http://example.com/1706398/" + url
}
})
.on('response', function(response) {
response.on('data', function(data) {
console.log("data chunk received: " + data.length)
});
response.on('end', function(data) {
console.log('Video completed');
});
})
.pipe(res);
});
app.listen(8080);
But video response sometimes works sometimes is corrupted, instead if request's data is written in a writeable buffer and saved as video file it works with any url.
I cannot found any error or problem in my code, here some urls :
Here some url that I tryed:
https://gist.github.com/FrancisCan/f2bb86f8ff73b45fa192
Thanks :)
Remove the writeHead 200, when you are streaming, you should return http 206 results back (partial content), and not http200. I have the same scenario as you (streaming a video file from a blob container in the cloud to an angular application), there is no need for the http200 response.
Update: adding some code on how I do it:
AzureStorageHelper.prototype.streamBlob = function streamBlob(req, res, blob, params) {
if(!params){
params.container = container;
}
blob_service.getBlobProperties(params.container, blob, function (error, result, response) {
if(!result) return res.status(404).end();
if(error) return res.status(500).end();
var blobLength = result.contentLength;
var range = req.headers.range ? req.headers.range : "bytes=0-";
var positions = range.replace(/bytes=/, "").split("-");
var start = parseInt(positions[0], 10);
var end = positions[1] ? parseInt(positions[1], 10) : blobLength - 1;
var chunksize = (end - start) + 1;
var options = {
rangeStart: start,
rangeEnd: end,
}
//this is what's interesting for your scenario. I used to set this up myself but it's is now handled by the Azure Storage NodejsSDK
/*res.writeHead(206, {
'Accept-Ranges': 'bytes',
'Content-Range': "bytes " + start + "-" + end + "/" + blobLength,
'Content-Type': result.contentType,
'Content-Length': chunksize,
'Content-MD5': result.contentMD5,
});*/
var options = {
rangeStart: start,
rangeEnd: end,
}
//this is an API from the Azure Storage nodejsSDK I use. You might want to check the source of this method in github to see how this lib deals with the http206 responses and the piping
blob_service.getBlobToStream(params.container, blob, res, options, function (error, result, response) {
if (error) {
return res.status(500).end();
}
});
});

PhantomJS PDF file to Base64

I'm working with PhantomJS and doing PDF Files from rendering my own website, right now works perfectly (the file is creating, everything seems just ok at localhost).
All this comes from a Post all the way from my actual server (NoseJS), i'm trying to send in response the .pdf PhantomJS made, I tried sending binary, base64 and all kind of ways I found in the web... Right now i'm converting the file to base64 in phantom and sending it to Node, Node creates the file and the file comes in blank and bigger in size (Phantom file: 15Mb, Node file: 29Mb)
My question is, does anyone know an easy way through?
My code right now:
PhantomJS:
function utf8_to_b64(str) {
return window.btoa(unescape(encodeURIComponent(str)));
}
var server = require('webserver').create();
var fs = require('fs');
var port = require('system').env.PORT || 8080; // default back to 8080
server.listen(port, function(request, response) {
if (request.method === 'POST') {
var page = new WebPage();
var objeto = request.post;
page.paperSize = {
format: 'A4',
orientation: 'portrait',
margin: '1cm'
};
page.open("http://google.com", function(status) {
if (status !== 'success') {
console.log('Unable to load the address!');
} else {
//page.render(app + '.pdf', {
page.render('prueba.pdf', {
format: 'pdf',
quality: '100'
});
var archivo = fs.open('prueba.pdf', 'r');
archivo = archivo.read();
archivo = utf8_to_b64(archivo);
console.log('done');
//fs.remove('prueba.pdf');
response.statusCode = 200;
response.headers = {
'Content-type': 'text/plain'
};
response.write(archivo);
response.close();
page.close();
//phantom.exit();
}
});
}
});
NodeJS:
request
.post('http://localhost:8080/')
.send({
app: req.body.app,
url: 'google.com'
})
.end(function(err, respond) {
console.log('post a phantom');
console.log('error: ', err);
fs.writeFile('prueba.pdf', respond.text, 'base64', function(err) {
if (err) throw err;
console.log('It\'s saved!');
});
res.json(resJSON.ok());
});
Any ideas?

How do I incorporate seeking with node express audio stream

I have a small podcast feed that I'm hosting and after I finally got it hooked up to Downcast everything worked fine until I tried to skip forward/back. I finally realized that seeking isn't inherently part of pipe streaming. I've searched around and I cannot seem to find anything of use.
With the following code, how would I implement seeking?
app.get('/stream/:id', function(req, res) {
if (!req.params.id) {
res.status(404);
res.send("Not found");
}
var filePath = path.join(Config.media, '**' , req.params.id);
filePath = glob.sync(filePath)[0];
var stat = fs.statSync(filePath);
res.writeHead(200, {
'Content-Type': 'audio/mpeg',
'Content-Length': stat.size,
'Accept-Ranges': 'bytes'
});
var readStream = fs.createReadStream(filePath);
readStream.pipe(res);
});
I was actually able to do this using visionmedia/send (which handled a lot of my work with paths as well).
Here's the new code that works with seeking:
var send = require('send');
...
app.get('/stream/*', function(req, res) {
var path = Url.parse(req.url).pathname.replace('/stream','');
send(req, path)
.root(Config.media)
.on('error', function(err) {
res.statusCode = err.status || 500;
res.end(err.message);
})
.on('directory', function() {
res.statusCode = 403;
res.end("Forbidden");
})
.pipe(res);
});

Empty HTTP response

For some reason, this code keeps failing :
var http = require('http');
var url = require ('url');
var jade = require('jade');
var fs = require('fs');
http.createServer(function(req, res) {
// Request handlers
var path = url.parse(req.url, true).pathname;
var dot = path.lastIndexOf('.');
var extension = path.substr(dot + 1);
// Response handlers
switch(extension) {
case 'css' :
res.writeHeader(200, {"Content-Type": "text/css"});
fs.readFile(path.substr(1, dot - 1) + '.css', function (err, css) {
if(err) {
res.write(err, 'utf8')
};
res.write(css, 'utf8')
});
break;
case 'js' :
res.writeHeader(200, {"Content-Type": "text/javascript"});
fs.readFile(path.substr(1, dot - 1) + '.js', function (err, js) {
if(err) {
res.write(err, 'utf8')
};
res.write(js, 'utf8')
});
break;
default :
res.writeHeader(200, {"Content-Type": "text/html"});
jade.renderFile(path.substr(1, path.length) + '.jade', { title: 'test' }, function(err, html) {
if(err) {
res.write(err, 'utf8')
};
res.write(html, 'utf8');
});
break;
}
res.end();
}).listen(8080);
I don't get any errors, it's just that the responses seem to be empty.
There is a header but no css or javascript file.
The way I link them in Jade is the following :
link(rel='stylesheet', href='/css/bootstrap.min.css')
link(rel='stylesheet', href='/css/style.css')
Thank you in advance !
You've called res.end() too soon. Instead, put it after the last res.write() in each of your fs.readFile handlers.

Resources