无法在nodejs服务器提供的Safari中播放mp4视频

时间:2017-03-17 00:04:35

标签: html node.js html5 html5-video

我在从我的nodejs服务器上提供的Safari上加载mp4视频文件时遇到问题。 Chrome上不存在此问题。

为了说明这个问题,我有一个简单的html网页,它读取了w3schools提供的mp4文件mov_bbb.mp4。然后我下载相同的文件并从我的nodejs服务器提供它。

vid1(来自w3schools)在Chrome和Safari上加载正常。

vid2(从我的nodejs服务器提供)在Chrome上正常加载但在Safari上没有。

这是我在Chrome中看到的截图:

enter image description here

这是我在Safari中看到的截图:

enter image description here

这是我的HTML:

<!DOCTYPE html>
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <video id="vid1" controls preload="auto" src="https://www.w3schools.com/html/mov_bbb.mp4"></video>
    <video id="vid2" controls preload="auto" src="http://localhost:8125/mov_bbb.mp4"></video>
  </body>
</html>

这是我的nodejs服务器:

var http = require('http');
var fs = require('fs');
var path = require('path');

http.createServer(function (request, response) {
    console.log('request starting...');

    var filePath = '.' + request.url;
    if (filePath == './')
        filePath = './index.html';

    var extname = path.extname(filePath);
    var contentType = 'video/mp4';

    fs.readFile(filePath, function(error, content) {
        if (error) {
            if(error.code == 'ENOENT'){
                fs.readFile('./404.html', function(error, content) {
                    response.writeHead(200, { 'Content-Type': contentType });
                    response.end(content, 'utf-8');
                });
            }
            else {
                response.writeHead(500);
                response.end('Sorry, check with the site admin for error: '+error.code+' ..\n');
                response.end();
            }
        }
        else {
            response.writeHead(200, {
            });
            response.end(content, 'utf-8');
        }
    });

}).listen(8125);
console.log('Server running at http://127.0.0.1:8125/');

我们非常感谢任何建议。

更新

修改了nodejs代码。在Safari上仍然存在同样的问题:

var http = require('http');
var fs = require('fs');

http.createServer(function (request, response) {
  console.log('request starting...');

  var filePath = '.' + request.url;
  if (filePath == './') {
    var contentType = 'text/html';
    filePath = './index.html';
  } else {
    var contentType = 'video/mp4';
  }

  var rstream = fs.createReadStream(filePath);
  rstream.on('error', function(error) {
    response.writeHead(404);
    response.end();
  });
  rstream.on('open', function () {
    response.writeHead(200, {
      'Content-Type': contentType,
    });
  });
  rstream.pipe(response);
}).listen(8125);
console.log('Server running at http://127.0.0.1:8125/');

http标头的chrome检查器:

enter image description here

2 个答案:

答案 0 :(得分:1)

首先,不要使用readFile()来提供文件,这会导致不必要的(可能很高的)内存使用,因为它会将整个文件加载到内存中。使用fs.createReadStream()并将其管道传输到response

其次,最重要的是,在成功案例中没有发送Content-Type。此外,Content-Type在错误情况下是错误的,因为文本/ html数据是在响应中发送的,而不是视频/ mp4数据。

此外,不应将任意路径传递给文件系统调用,因为有人可能会传递恶意路径(包括到达文件系统根目录的相对路径)并从文件系统中读取敏感信息(例如私钥,密码等)。

最后,如果您要为回复撰写Buffer,则无需指定编码(例如'utf-8'),因为数据已在{ {1}}表格。

答案 1 :(得分:1)

视频播放的问题与处理必须在服务器上实现的Content-Range范围标题有关。 Chrome和Safari会发送不同的请求标头。在我的情况下,Chrome会发送一个范围为:

的请求
bytes=0-

Safari发送多个请求:

bytes=0-1
bytes=0-1013150
bytes=197534-1013150

有关详细信息,请参阅this thread,有关适用于我的具体代码,请参阅this answer