简体   繁体   中英

Video streaming in node.js

I want to stream the video using node.js. I have followed this article . And it's working fine from local. But I need to stream video from web.

My requirement is little different. I have to hide the original URL from source code. So, instead of showing original URL, I need to show my own URL like <source src="http://localhost:8888" type="video/mp4"/> . Instead of showing <source src="http://goo.gl/KgGx0s" type="video/mp4"/> .

Using the following codes

var indexPage, movie_webm, movie_mp4, movie_ogg;
fs.readFile(path.resolve(__dirname,"ANY_LOCAL_VIDEO.mp4"), function (err, data) {
    if (err) {
        throw err;
    }
    console.log(data.length);
    movie_mp4 = data;
});

http.createServer(function (req, res) {
    var reqResource = url.parse(req.url).pathname;
    var total;
    total = movie_mp4.length;
    var range = req.headers.range;  
    var positions = range.replace(/bytes=/, "").split("-");
    var start = parseInt(positions[0], 10); 
    var end = positions[1] ? parseInt(positions[1], 10) : total - 1;
    var chunksize = (end-start)+1;
    res.writeHead(206, { "Content-Range": "bytes " + start + "-" + end + "/" + total, 
                         "Accept-Ranges": "bytes",
                         "Content-Length": chunksize,
                         "Content-Type":"video/mp4"});
    res.end(movie_mp4.slice(start, end+1), "binary");

}).listen(8888); 

It's working fine for local videos. But if I give fs.readFile("http://goo.gl/KgGx0s", function (err, data) { instead of above code it's not working. I tried by changing fs.readFile to fs.filepath but still not working. I am getting this error

c:\git\personal\streaming-video-html5\server.js:13
        throw err;
              ^
Error: ENOENT, open 'c:\git\personal\streaming-video-html5\http:\goo.gl\KgGx0s'

This may be because the path is changing. What approach should I follow? Is it possible?

What you're looking for is something like the request module .

You can simply fetch your remote video and then pipe it directly to your response.

What I'd do is first make a HEAD request to the remote video in order to confirm that it accepts byte ranges and also to get the content length of the video.

Once you've got that information you can set your response headers, with a HTTP status code of 206 , indicating that this is a partial response.

Now that you've written your response headers you create a request to the remote video, sending along the byte-range in the original request and pipe that directly to your response ( res );

var fileUrl = 'https://ia800300.us.archive.org/1/items/night_of_the_living_dead/night_of_the_living_dead_512kb.mp4';

var range = req.headers.range;
var positions, start, end, total, chunksize;

// HEAD request for file metadata
request({
  url: fileUrl,
  method: 'HEAD'
}, function(error, response, body){
  setResponseHeaders(response.headers);
  pipeToResponse();
});

function setResponseHeaders(headers){
  positions = range.replace(/bytes=/, "").split("-");
  start = parseInt(positions[0], 10); 
  total = headers['content-length'];
  end = positions[1] ? parseInt(positions[1], 10) : total - 1;
  chunksize = (end-start)+1;

  res.writeHead(206, { 
    "Content-Range": "bytes " + start + "-" + end + "/" + total, 
    "Accept-Ranges": "bytes",
    "Content-Length": chunksize,
    "Content-Type":"video/mp4"
  });
}

function pipeToResponse() {
  var options = {
    url: fileUrl,
    headers: {
      range: "bytes=" + start + "-" + end,
      connection: 'keep-alive'
    }
  };

  request(options).pipe(res);
}

You can probably cache the response from the HEAD request so that you don't need to do it each time a byte-range is requested.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM