【问题标题】:Can't play mp4 video in Safari served by nodejs server无法在 nodejs 服务器提供的 Safari 中播放 mp4 视频
【发布时间】:2017-03-17 00:04:34
【问题描述】:

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

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

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

vid2(由我的 nodejs 服务器提供)在 Chrome 上加载正常,但在 Safari 上加载不正常。

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

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

这是我的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 检查器:

【问题讨论】:

    标签: node.js html html5-video


    【解决方案1】:

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

    bytes=0-
    

    而 Safari 发送多个请求:

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

    有关更多信息,请参阅this thread,有关适用于我的特定代码,请参阅this answer

    【讨论】:

    • @stthoms...我面临同样的问题...无法在 safari 上工作...您找到解决方法了吗...如果可以,您可以分享一下吗..
    【解决方案2】:

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

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

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

    最后,如果您要在响应中写入Buffer,则无需指定编码(例如'utf-8'),因为数据已经采用Buffer 形式。

    【讨论】:

    • 支持 nodejs 建议,尽管问题仍然存在。
    猜你喜欢
    • 2016-01-04
    • 1970-01-01
    • 2021-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    相关资源
    最近更新 更多