通过node.js使用HTML 5进行视频流传输

Chr*_*ton 44 video html5 stream node.js

我正在尝试使用node.js设置一个支持将视频流式传输到HTML5视频标签的网络服务器.到目前为止,这是我的代码:

var range = request.headers.range;
var total = file.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;

response.writeHead(206, { "Content-Range": "bytes " + start + "-" + end + "/" + total, "Accept-Ranges": "bytes", "Content-Length": chunksize, "Content-Type": type });
response.end(file);
Run Code Online (Sandbox Code Playgroud)

其中"request"表示http请求,type是"application/ogg"或"video/ogg"(我已尝试过两者),"file"是从文件系统中读取的.ogv文件.以下是响应标头:

Content-Range   bytes 0-14270463/14270464
Accept-Ranges   bytes
Content-Length   14270464
Connection     keep-alive
Content-Type     video/ogg
Run Code Online (Sandbox Code Playgroud)

我已经检查了响应标头,这段代码看起来运行正常,但是有一些问题:

  1. 在本地网络上,视频的加载速度非常慢.据我所知,使用firebug检查响应,文件似乎以大约150 kb /秒的速度流式传输.
  2. 该视频根本不播放.即使我等待加载整个内容,HTML 5视频标记只显示一个大的"x"而不是firefox中的电影.

有没有人有任何想法,我可以做什么来通过node.js使视频流工作?

谢谢!
克里斯

mel*_*oly 24

我知道这是一个非常古老的问题,但是谷歌似乎喜欢它,我认为值得指出的是我写了一个Node.js 视频流模块(Github,或通过NPM),希望值得一看.

  • 我喜欢那种答案!谢谢.:) (5认同)

Chr*_*ton 18

我能够在nodejs论坛的帮助下使用它:

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

Google网上论坛帖子的亮点:

众所周知,Google Chrome首先发出0-1024范围的请求,然后请求范围"1024-".

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

然后:

通过将"连接"标题设置为"关闭",我能够在Firefox中播放视频没有问题

然后:

似乎您错误地计算了内容长度:

var chunksize =(end-start)+1;

如果start为0且end为1,则在你的情况下chunksize为2,它应为1.


Sco*_*and 11

此解决方案执行服务器端视频或音频媒体文件的异步读取...它会在可见的URL处旋转nodejs服务器

HTTP://本地主机:8888 /

它还正确处理客户端HTML5(浏览器/应用程序)前进/后退UI小部件滑块移动

将以下代码段保存为服务器端文件:

media_server.js
Run Code Online (Sandbox Code Playgroud)

...使用在服务器端执行它

node media_server.js
Run Code Online (Sandbox Code Playgroud)

请享用

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 + "/");
Run Code Online (Sandbox Code Playgroud)

  • 有没有办法将视频文件不是从源文件而是从 udp 流传输到浏览器? (2认同)

Udo*_*o G 5

基于Sam9291的回答,我重写了使用createReadStream()和修复一些问题的函数:

/**
 * Sends a static file to the HTTP client, supporting partial transfers.
 * 
 * @req HTTP request object
 * @res HTTP response object
 * @fn Path to file that should be sent
 * @contentType MIME type for the response (defaults to HTML)
 */      
function sendFile(req, res, fn, contentType) {

  contentType = contentType || "text/html";

  fs.stat(fn, function(err, stats) {
    var headers;

    if (err) {
      res.writeHead(404, {"Content-Type":"text/plain"});
      res.end("Could not read file");
      return;
    }

    var range = req.headers.range || "";    
    var total = stats.size;

    if (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;

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

    } else {

      headers = { 
        "Accept-Ranges": "bytes", 
        "Content-Length": stats.size, 
        "Content-Type": contentType 
      };
      res.writeHead(200, headers);

    }

    var readStream = fs.createReadStream(fn, {start:start, end:end});
    readStream.pipe(res);    

  });

}
Run Code Online (Sandbox Code Playgroud)