Video streaming with HTML 5 via node.js

后端 未结 8 1936
青春惊慌失措
青春惊慌失措 2020-11-30 18:01

I\'m trying to set up a web server that will support streaming video to an HTML5 video tag using node.js. Here\'s my code so far:

var range = request.header         


        
相关标签:
8条回答
  • 2020-11-30 18:29

    I am using the MVC framework sails.js on top of Node.js and I managed to get it working fine with the following code:

    /**
     * VideoController
     *
     * @module      :: Controller
     * @description :: Contains logic for handling requests.
     */
    
     var fs = require('fs');
    
    module.exports = {
    
      /* e.g.
      sayHello: function (req, res) {
        res.send('hello world!');
      }
      */
    
      /**
       * /video/stream
       */ 
      stream: function (req,res) {
    
        // This will render the view: 
        // C:\Users\sam\Documents\Dev\Fun\mymoviebank/views/video/stream.ejs
        res.view();
    
      },
    
      play: function (req,res) {
    
        fs.readFile('/Users/sam/Videos/big_buck_bunny.mp4', function (err, data) {
          if (err) throw err;
    
          var range = req.headers.range;
            var total = data.length;
    
            var parts = range.replace(/bytes=/, "").split("-");
            var partialstart = parts[0];
            var partialend = parts[1];
    
            var start = parseInt(partialstart, 10);
            var end = partialend ? parseInt(partialend, 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(data);
    
        });
    
      }
    
    };
    

    Hope this helps

    0 讨论(0)
  • 2020-11-30 18:29

    I found this codesandbox and it seems really helpful https://codesandbox.io/s/14n6q1yr33

    0 讨论(0)
  • 2020-11-30 18:43

    when using express put this in your media_server.js or index.js which will serve the media on port 3000

    const express = require('express')
    const fs = require('fs')
    const path = require('path')
    const app = express()
    
    app.use(express.static(path.join(__dirname, 'public')))
    
    app.get('/', function(req, res) {
      res.sendFile(path.join(__dirname + '/index.html'))
    })
    
    app.get('/video', function(req, res) {
      const path = 'assets/sample.mp4'// your video path
      const stat = fs.statSync(path)
      const fileSize = stat.size
      const range = req.headers.range
    
      if (range) {
        const parts = range.replace(/bytes=/, "").split("-")
        const start = parseInt(parts[0], 10)
        const end = parts[1]
          ? parseInt(parts[1], 10)
          : fileSize-1
    
        const chunksize = (end-start)+1
        const file = fs.createReadStream(path, {start, end})
        const head = {
          'Content-Range': `bytes ${start}-${end}/${fileSize}`,
          'Accept-Ranges': 'bytes',
          'Content-Length': chunksize,
          'Content-Type': 'video/mp4',
        }
    
        res.writeHead(206, head)
        file.pipe(res)
      } else {
        const head = {
          'Content-Length': fileSize,
          'Content-Type': 'video/mp4',
        }
        res.writeHead(200, head)
        fs.createReadStream(path).pipe(res)
      }
    })
    
    app.listen(3000, function () {
      console.log('Listening on port 3000!')
    })
    

    then in your index.html

    <html>
      <head>
        <title>Video stream sample</title>
      </head>
      <body>
        <video id="videoPlayer" controls muted="muted" autoplay> 
          <source src="http://localhost:3000/video" type="video/mp4">
        </video>
      </body>
    </html>
    
    0 讨论(0)
  • 2020-11-30 18:48

    This solution does an asynchronous read of a server side video or audio media file ... it spins up a nodejs server at URL visible at

    http://localhost:8888/

    also it correctly handles client side HTML5 (browser/app) forward/back UI widget slider movements

    save below code snippet as server side file :

    media_server.js
    

    ... execute it on server side using

    node media_server.js
    

    enjoy

    var http = require('http'),
        fs = require('fs'),
        util = require('util');
    
    var path = "/path/to/local/video/or/audio/file/on/server.mp4";
    
    var port = 8888;
    var host = "localhost";
     
    http.createServer(function (req, res) {
    
      var stat = fs.statSync(path);
      var total = stat.size;
    
      if (req.headers.range) { // meaning client (browser) has moved the forward/back slider
                               // which has sent this request back to this server logic ... cool
        var range = req.headers.range;
        var parts = range.replace(/bytes=/, "").split("-");
        var partialstart = parts[0];
        var partialend = parts[1];
     
        var start = parseInt(partialstart, 10);
        var end = partialend ? parseInt(partialend, 10) : total-1;
        var chunksize = (end-start)+1;
        console.log('RANGE: ' + start + ' - ' + end + ' = ' + chunksize);
     
        var file = fs.createReadStream(path, {start: start, end: end});
        res.writeHead(206, { 'Content-Range': 'bytes ' + start + '-' + end + '/' + total, 'Accept-Ranges': 'bytes', 'Content-Length': chunksize, 'Content-Type': 'video/mp4' });
        file.pipe(res);
    
      } else {
    
        console.log('ALL: ' + total);
        res.writeHead(200, { 'Content-Length': total, 'Content-Type': 'video/mp4' });
        fs.createReadStream(path).pipe(res);
      }
    }).listen(port, host);
    
    console.log("Server running at http://" + host + ":" + port + "/");
    
    0 讨论(0)
  • 2020-11-30 18:48

    I found this solution which seems to be simpler and (unlike the checked answer) works for me. (I tried adapting the coffeescript solution at the end of that thread and it kind of worked once I dealt with the fact that the initial request (for "bytes=0-") blows it up.

    http://elegantcode.com/2011/04/06/taking-baby-steps-with-node-js-pumping-data-between-streams/

    My actual implementation:

    function stream_response( res, file_path, content_type ){
        var readStream = fs.createReadStream(file_path);
    
        readStream.on('data', function(data) {
            var flushed = res.write(data);
            // Pause the read stream when the write stream gets saturated
            console.log( 'streaming data', file_path );
            if(!flushed){
                readStream.pause();
            }
        });
    
        res.on('drain', function() {
            // Resume the read stream when the write stream gets hungry 
            readStream.resume();
        });
    
        readStream.on('end', function() {
            res.end();
        });
    
        readStream.on('error', function(err) {
            console.error('Exception', err, 'while streaming', file_path);
            res.end();
        });
    
        res.writeHead(200, {'Content-Type': content_type});
    }
    
    0 讨论(0)
  • 2020-11-30 18:49

    I was able to get this to work with some help from the nodejs forums:

    http://groups.google.com/group/nodejs/browse_thread/thread/8339e0dc825c057f/822b2dd48f36e890

    Highlights from the Google Groups thread:

    Google chrome is known to first make a request with the range 0-1024 and then request the range "1024-".

    response.end(file.slice(start, chunksize), "binary");

    Then:

    I was able to get the video to play no problems in firefox by setting the "connection" header to "close"

    Then:

    Seems that you are incorrectly computing the content-length:

    var chunksize = (end-start)+1;

    If start is 0 and end is 1, in your case chunksize is 2, and it should be 1.

    0 讨论(0)
提交回复
热议问题